me, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
50
51 #define SYSCALL_DEFINEx(x, sname, ...) \
52? ? SYSCALL_METADATA(sname, x, __VA_ARGS__) \
53? ? __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
54
55 #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
56 #define __SYSCALL_DEFINEx
可以看出系统调用是使用SYSCALL_DEFINEx进行定义的,以我们的例子,实际上最后clone函数被定义为
?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 }
? ? 在do_fork函数中,首先会根据clone_flags判断是否对父进程进行了跟踪(调试使用),如果进行了函数跟踪(还需要判断是否对子进程进行跟踪),之后调用copy_process(do_fork的核心函数,之后的文章会对它进行分析),在copy_process中会对子进程的许多结构体和参数进行初始化(同时在fork正常情况中为什么会返回两次也是在此函数中实现的),do_fork最后就判断是否是通过vfo