内核中哪个文件指定了fork(),vfork()…以使用sys_clone()系统调用


9

当使用ltrace跟踪系统调用时,我可以看到fork()使用sys_clone()而不是sys_fork()。但是我找不到定义它的linux源。

我的程序是

#include<stdio.h>
main()
{
        int pid,i=0,j=0;
        pid=fork();
        if(pid==0)
                printf("\nI am child\n");
        else
                printf("\nI am parent\n");

}

和ltrace输出是

SYS_brk(NULL)                                                                               = 0x019d0000
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_mmap(0, 8192, 3, 34, 0xffffffff)                                                        = 0x7fe3cf84f000
SYS_access("/etc/ld.so.preload", 04)                                                        = -2
SYS_open("/etc/ld.so.cache", 0, 01)                                                         = 3
SYS_fstat(3, 0x7fff47007890)                                                                = 0
SYS_mmap(0, 103967, 1, 2, 3)                                                                = 0x7fe3cf835000
SYS_close(3)                                                                                = 0
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_open("/lib/x86_64-linux-gnu/libc.so.6", 0, 00)                                          = 3
SYS_read(3, "\177ELF\002\001\001", 832)                                                     = 832
SYS_fstat(3, 0x7fff470078e0)                                                                = 0
SYS_mmap(0, 0x389858, 5, 2050, 3)                                                           = 0x7fe3cf2a8000
SYS_mprotect(0x7fe3cf428000, 2097152, 0)                                                    = 0
SYS_mmap(0x7fe3cf628000, 20480, 3, 2066, 3)                                                 = 0x7fe3cf628000
SYS_mmap(0x7fe3cf62d000, 18520, 3, 50, 0xffffffff)                                          = 0x7fe3cf62d000
SYS_close(3)                                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf834000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf833000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf832000
SYS_arch_prctl(4098, 0x7fe3cf833700, 0x7fe3cf832000, 34, 0xffffffff)                        = 0
SYS_mprotect(0x7fe3cf628000, 16384, 1)                                                      = 0
SYS_mprotect(0x7fe3cf851000, 4096, 1)                                                       = 0
SYS_munmap(0x7fe3cf835000, 103967)                                                          = 0
__libc_start_main(0x40054c, 1, 0x7fff47008298, 0x4005a0, 0x400590 <unfinished ...>
fork( <unfinished ...>
SYS_clone(0x1200011, 0, 0, 0x7fe3cf8339d0, 0)                                               = 5967
<... fork resumed> )                                                                        = 5967
puts("\nI am parent" <unfinished ...>
SYS_fstat(1, 0x7fff47008060)                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff
)                                                        = 0x7fe3cf84e000
I am child
SYS_write(1, "\n", 1
)                                                                       = 1
SYS_write(1, "I am parent\n", 12)                                                           = -512
--- SIGCHLD (Child exited) ---
SYS_write(1, "I am parent\n", 12I am parent
)                                                           = 12
<... puts resumed> )                                                                        = 13
SYS_exit_group(13 <no return ...>
+++ exited (status 13) +++

这可能对您有所帮助:lxr.linux.no/linux+v3.10.9
重播

@ mauro.stettler我在lxr中找不到它
user3539

1700行附近的意思是git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/…吗?您希望找出什么?
msw

Answers:


29

glibc中的fork()vfork()包装器是通过clone()系统调用实现的。为了更好地理解之间的关系fork()clone(),我们必须考虑在Linux的进程和线程之间的关系。

传统上,fork()将复制父进程拥有的所有资源,并将副本分配给子进程。这种方法会产生相当大的开销,如果孩子立即呼叫,那么所有开销可能都是零花exec()。在Linux中,fork()利用写时复制页面来延迟或完全避免复制可在父进程和子进程之间共享的数据。因此,正常fork()情况下唯一的开销是复制父级的页表以及为子级分配唯一的过程描述符结构task_struct

Linux还对线程采取了一种特殊的方法。在Linux中,线程只是普通的进程,碰巧与其他进程共享一些资源。与其他操作系统(例如,进程和线程是完全不同的野兽)(例如Windows或Solaris)相比,这是与线程完全不同的方法。在Linux中,每个线程都有task_struct自己的一个普通对象,恰好以与父进程共享某些资源(例如地址空间)的方式进行设置。

系统调用的flags参数clone()包括一组标志,这些标志指示父进程和子进程应共享哪些资源(如果有)。进程和线程都是通过创建的clone(),唯一的区别是传递给的标志集clone()

fork()可以将法线实现为:

clone(SIGCHLD, 0);

这将创建一个任务,该任务与其父级不共享任何资源,并且设置为SIGCHLD在退出时将终止信号发送给父级。

相反,可以创建一个与父节点共享地址空间,文件系统资源,文件描述符和信号处理程序的任务,换句话说,可以使用以下命令创建线程

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

vfork()依次通过单独的CLONE_VFORK标志实现,这将导致父进程进入睡眠状态,直到子进程通过信号将其唤醒。在调用exec()或退出之前,子级将是父级名称空间中的唯一执行线程。不允许该子代写入存储器。相应的clone()调用如下:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

的实现sys_clone()是特定于体系结构的,但是大部分工作都在中do_fork()定义kernel/fork.c。此函数调用static clone_process(),它创建一个新进程作为父进程的副本,但尚未启动它。clone_process()复制寄存器,为新任务分配PID,并复制或共享克隆指定的过程环境的适当部分flags。当clone_process()返回时,do_clone()将唤醒新创建的进程,并安排其运行。


2
+1很好地说明了与clone()线程和派生相关的意义。
goldilocks 2013年

1
消除

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.