1. 检查clone标志:
不能同时设NEWNS, FS
不能设THREAD, 但未设SIGHAND
不能设SIGHAND,但未设VM
2. 调用dup_task_struct()为子进程获取task_struct, thread_info结构
atomic_set(&tsk->usage,2);
3. 检查用户进程数
if (atomic_read(&p->user->processes) >= p->signal->rlim[RLIMIT_NPROC].rlim_cur) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && p->user != &root_user) goto bad_fork_free; }
4.增加module执行域(必须包含在内核模块中)的count
if (!try_module_get(p->thread_info->exec_domain->module))
if (p->binfmt && !try_module_get(p->binfmt->module))
5. 保存clone flgs 和 pid
6. 如果SETID被设置, copy子进程pid到父进程的tidptr字段
if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr))
7. 初始化进程描述符的list_head, 自旋锁, 挂起信号, 定时器及时间统计表等
8. copy描述符的各个字段
9. 调用copy_thread, 初始化内核栈, i/o位图
10. 调用sched_fork对新进程调度程序数据结构的初始化。 把新进程的状态设为TASK_RUNNING. 并设置preempt_count字段为1, 从而禁止内核抢占。父子进程共享时间片
11. 初始化亲子关系
12. 调用attach_pid把新进程描述符的pid插入pidhash散列表
13. (CLONE_THREAD被清0, 表示创建领头进程)
14. 返回子进程描述符指针
系统调用返回给子进程的是0, 返回给父进程的是子进程的pid