Какая процедура при вызове fork (), тогда она становится вызывающей sys_fork ()? - PullRequest
0 голосов
/ 18 января 2019

Я проверяю Linux 0.11. https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/old-versions/

Когда мы находим функцию 'open', мы видим:

\ Lib \ open.c

int open(const char * filename, int flag, ...)
{
    register int res;
    va_list arg;

    va_start(arg,flag);
    __asm__("int $0x80"
....

у нас есть функция 'open', которая использует прерывание 0x80, отлично.

Однако, при проверке «fork» мы не можем видеть его функцию как «открытую», например:

int fork ( xxx )
{
  ....
}

Тем не менее, мы можем видеть что-то похожее:

fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,

#define __NR_fork   2

Код, кажется, говорит мне, да, sys_fork () - это второй указатель на функцию, тогда вы получите вызов:

system_call.s

.align 2
_sys_fork:
    call _find_empty_process
....

а как? и почему? почему вызов fork () будет направлен на вызов sys_fork ()?

1 Ответ

0 голосов
/ 18 января 2019

То, что вы ищете не в ядре. это находится в библиотеке C. К сожалению, историческая библиотека C не является частью linux-0.11.tar.gz, поэтому мы можем только предполагать, как она написана.

Библиотека C использует этот макрос из <unistd.h>:

#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name)); \
if (__res >= 0) \
        return (type) __res; \
errno = -__res; \
return -1; \
}

с аргументами int, fork (да, похоже, он не использует pid_t в качестве возвращаемого значения, даже если этот тип существует), который расширится до

int fork(void) { 
    long __res; 
    __asm__ volatile ("int $0x80" : 
                      "=a" (__res) : 
                      "0" (__NR_fork)); 
    if (__res >= 0) 
        return (int) __res; e
    errno = -__res; 
    return -1;
}

Это определение функции скомпилировано в одной единице перевода библиотеки C. Кроме того, unistd.h файл ядра - это файл, доступный для пространства пользователя.

Встроенный ассемблер просто помещает значение __NR_fork в eax, вызывает прерывание 0x80 и получает __res возвращаемое значение от eax.

Прерывание 0x80 входит в _system_call из system_call.s, которое имеет следующий код:

.align 2
_system_call:
        cmpl $nr_system_calls-1,%eax
        ja bad_sys_call
        [...]
        call _sys_call_table(,%eax,4)
        [...]
        iret

т.е. eax сначала сравнивается с максимальным номером системного вызова, и, если указано выше, возникает ошибка; затем eax th 4-байтовый указатель вызывается из таблицы системных вызовов, и, наконец, iret возвращается из прерывания, возвращаемое значение вызываемой функции сохраняется в eax.

...