Существует ли функция системного вызова, определение которой вызывает другую функцию системного вызова? - PullRequest
0 голосов
/ 26 апреля 2018

В Linux существует ли функция системного вызова, определение которой вызывает другую функцию системного вызова?

Или все функции системного вызова исключают друг друга в том смысле, что любая функция системного вызова не вызывает другую функцию системного вызова?

Или функции системного вызова в основном исключают друг друга в вышеприведенном смысле?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Хорошо, для каждого системного вызова генерируется только ОДНА ловушка, но некоторые вызовы совместно используют коды, например, sys_epoll_create(), один раз в режиме ядра, вызывает sys_epoll_create1() (см. eventpoll.c для Kernell 2.6.35):

SYSCALL_DEFINE1(epoll_create, int, size)
{
    if (size <= 0)
        return -EINVAL;

    return sys_epoll_create1(0);
}

В более поздних версиях kernelk (4.17-rc2) те же функции совместно используют код :

SYSCALL_DEFINE1(epoll_create1, int, flags)
{
    return do_epoll_create(flags);
}

SYSCALL_DEFINE1(epoll_create, int, size)
{
    if (size <= 0)
        return -EINVAL;

    return do_epoll_create(0);
}

Так что ответ на ваш вопрос - да, но это зависит от версии ядра ...

0 голосов
/ 26 апреля 2018

Это зависит от вашего определения системного вызова.

Мне неизвестны какие-либо ловушки системных вызовов, которые, как только они входят в ядро, преднамеренно приводят к созданию другой ловушки системных вызовов.

Но реализация некоторых системных вызовов - функций sys_xxx в ядре - может завершиться использованием реализации некоторых других системных вызовов.

Одним из примеров этого является creat , который ничего не делает, кроме вызова функции sys_open - реализации системного вызова open - с некоторыми конкретными аргументами:

/*
 * For backward compatibility?  Maybe this should be moved
 * into arch/i386 instead?
 */
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
{
    return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
}
0 голосов
/ 26 апреля 2018

В качестве примера давайте рассмотрим, как реализована функция C write() в Linux.

Реализация библиотеки C по существу:

ssize_t write(int fd, const void *buf, size_t count)
{
    long retval;

    retval = syscall(__NR_write, fd, buf, count);
    if (retval < 0) {
        errno = -retval;
        return -1;
    } else
        return retval;
}

Функция syscall() специфична для каждой аппаратной архитектуры, операционной системы и ядра. Обычно написано на ассемблере. Он загружает параметры в конкретные регистры (в соответствии с используемыми соглашениями о вызовах ядра) и вызывает в ядре.

В этот момент граница безопасности пересекается, и выполнение перемещается в пространство ядра.

Сама реализация syscall write() в ядре использует таблицу описания файлов вызывающего процесса для поиска набора файловых операций, специфичных для этого файла или сокета; Точный путь к коду зависит от того, является ли дескриптор файла файлом (и в этом случае файловой системой, в которой он находится), каналом, сокетом, символьным устройством или блочным устройством.

Почти все системные вызовы возвращают неотрицательное значение для успеха и отрицательный код ошибки для ошибки.

В ядре Linux реализация системного вызова редко вызывает другую функцию, которая реализует системный вызов. Вместо этого общие части учитывают внутренние функции ядра, которые вызываются обеими функциями реализации syscall. Это облегчает обслуживание.

Если мы посмотрим, как ядро ​​Linux реализует системные вызовы faccessat() и access(), мы увидим, что оба просто вызывают внутреннюю функцию ядра do_faccessat().

...