关于Linux系统如何实现fork的研究(5)

1 /* 展开前 */
 2
 3 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 4          int __user *, parent_tidptr,
 5          int __user *, child_tidptr,
 6          int, tls_val)
 7 #endif
 8 {
 9    /* 应用层默认fork参数(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, NULL, NULL, NULL, &THREAD_SELF->tid) */
10    return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
11 }
12
13  /* 展开后 */
14
15 asmlinkage long sys_clone (unsigned long clone_flags, unsigned long newsp, int __user * parent_tidptr, int __user * child_tidptr, int tls_val)
16 {
17    return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
18 }

终于看到最后系统会调用do_fork函数进行操作,接下来我们看看do_fork函数

1 /* 应用层的fork最后会通过sys_clone系统调用调用到此函数 */
 2 /* 应用层默认fork参数(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, NULL, NULL, NULL, &THREAD_SELF->tid)
 3  * clone_flags: CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD
 4  * stack_start: NULL
 5  * stack_size: NULL
 6  * parent_tidptr: NULL
 7  * child_tidptr: &THREAD_SELF->tid
 8  * pid: NULL
 9  */
10 long do_fork(unsigned long clone_flags,
11      unsigned long stack_start,
12      unsigned long stack_size,
13      int __user *parent_tidptr,
14      int __user *child_tidptr)
15 {
16    struct task_struct *p;
17    int trace = 0;
18    long nr;
19
20    /* 判断是否进行跟踪 */
21    if (!(clone_flags & CLONE_UNTRACED)) {
22        if (clone_flags & CLONE_VFORK)
23            trace = PTRACE_EVENT_VFORK;
24        else if ((clone_flags & CSIGNAL) != SIGCHLD)
25            trace = PTRACE_EVENT_CLONE;
26        else
27            trace = PTRACE_EVENT_FORK;
28
29        if (likely(!ptrace_event_enabled(current, trace)))
30            trace = 0;
31    }
32
33    /* 调用copy_process进行初始化,返回初始化好的struct task_struct结构体,当我们调用fork时返回两次的原因也是在这个函数当中,下回分析 */
34    p = copy_process(clone_flags, stack_start, stack_size,
35              child_tidptr, NULL, trace);
36
37
38    if (!IS_ERR(p)) {
39        /* 创建成功 */
40        struct completion vfork;
41        struct pid *pid;
42
43        trace_sched_process_fork(current, p);
44
45        /* 获取子进程PID */
46        pid = get_task_pid(p, PIDTYPE_PID);
47        /* 返回子进程pid所属的命名空间所看到的局部PID */
48        nr = pid_vnr(pid);
49
50        if (clone_flags & CLONE_PARENT_SETTID)
51            put_user(nr, parent_tidptr);
52
53        if (clone_flags & CLONE_VFORK) {
54            p->vfork_done = &vfork;
55            init_completion(&vfork);
56            get_task_struct(p);
57        }
58
59        /* 将新进程加入到CPU的运行队列中 */
60        wake_up_new_task(p);
61
62        /* 跟踪才会用到 */
63        if (unlikely(trace))
64            ptrace_event_pid(trace, pid);
65
66        /* 如果是vfork调用,则在此等待vfork的进程结束 */
67        if (clone_flags & CLONE_VFORK) {
68            if (!wait_for_vfork_done(p, &vfork))
69                ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
70        }
71
72        put_pid(pid);
73    } else {
74        /* 创建失败 */
75        nr = PTR_ERR(p);
76    }
77        /* 返回新进程PID(新进程在这会返回0) */
78    return nr;
79 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b33989c2b19c44d30b132667ae89ee74.html