调用 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
获取__res
return值。
中断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
举行。
我正在检查 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
获取__res
return值。
中断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
举行。