我正在检查 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"
....
我们有使用中断 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() 是第二个函数指针,然后您将调用:
系统调用.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 $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
从系统调用表调用第 4 字节指针,最后是 iret
从中断返回,被调用函数的返回值保存在eax
中.
关于c - 调用fork()然后变成调用sys_fork()的过程是怎样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54247386/