调用 fork() 然后变成调用 sys_fork() 的过程是什么?

What's the procedure when calling fork() then it becomes calling sys_fork()?

我正在检查 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 [=11=]x80"
....

我们有 'open' 使用中断 0x80 的函数,很好。

但是,在检查时,'fork',我们看不到它的功能与 'open' 相同,例如:

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()?

您正在寻找的东西不在内核中。它在 C 库中。不幸的是,历史悠久的 C 库不是 linux-0.11.tar.gz 的一部分,因此我们只能推测它是如何编写的。

C 库使用来自 <unistd.h> 的这个宏:

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

with arguments int, fork(是的,它似乎没有使用 pid_t 作为 return 值,即使该类型存在),它将扩展为

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

此函数定义在 C 库的 一个 翻译单元中编译。此外,内核的 unistd.h 文件是可供用户使用的文件 space。

内联汇编器简单地将__NR_fork的值放入eax,调用中断0x80并从eax获取__resreturn值。

中断0x80从system_call.s进入_system_call,代码如下:

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

eax 首先与最大系统调用数进行比较,如果超过,则发生错误;然后从系统调用 table 调用第 eax 个 4 字节指针,最后从中断调用 iret returns,被调用函数的 return 值在 eax 举行。