do_fork函数
do_fork函數
在內核中創建并執行新的程序的各種系統調用最終都是調用了do_fork來實現進程的創建。
asmlinkage int sys_fork(unsigned long r4, unsigned long r5,unsigned long r6, unsigned long r7,struct pt_regs __regs) { #ifdef CONFIG_MMUstruct pt_regs *regs = RELOC_HIDE(&__regs, 0);return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); #else/* fork almost works, enough to trick you into looking elsewhere :-( */return -EINVAL; #endif } asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,unsigned long parent_tidptr,unsigned long child_tidptr,struct pt_regs __regs) {struct pt_regs *regs = RELOC_HIDE(&__regs, 0);if (!newsp)newsp = regs->regs[15];return do_fork(clone_flags, newsp, regs, 0,(int __user *)parent_tidptr,(int __user *)child_tidptr); } asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,unsigned long r6, unsigned long r7,struct pt_regs __regs) {struct pt_regs *regs = RELOC_HIDE(&__regs, 0);return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,0, NULL, NULL); }以上幾個創建進程的系統調用最終都調用 do_fork 來實現; do_fork函數的具體代碼如下:
long do_fork(unsigned long clone_flags,unsigned long stack_start,unsigned long stack_size,int __user *parent_tidptr,int __user *child_tidptr) {struct task_struct *p;int trace = 0;long nr;/** Determine whether and which event to report to ptracer. When* called from kernel_thread or CLONE_UNTRACED is explicitly* requested, no event is reported; otherwise, report if the event* for the type of forking is enabled.*/if (!(clone_flags & CLONE_UNTRACED)) {if (clone_flags & CLONE_VFORK)trace = PTRACE_EVENT_VFORK;else if ((clone_flags & CSIGNAL) != SIGCHLD)trace = PTRACE_EVENT_CLONE;elsetrace = PTRACE_EVENT_FORK;if (likely(!ptrace_event_enabled(current, trace)))trace = 0;}p = copy_process(clone_flags, stack_start, stack_size,child_tidptr, NULL, trace);/** Do this prior waking up the new thread - the thread pointer* might get invalid after that point, if the thread exits quickly.*/if (!IS_ERR(p)) {struct completion vfork;struct pid *pid;trace_sched_process_fork(current, p);pid = get_task_pid(p, PIDTYPE_PID);nr = pid_vnr(pid);if (clone_flags & CLONE_PARENT_SETTID)put_user(nr, parent_tidptr);if (clone_flags & CLONE_VFORK) {p->vfork_done = &vfork;init_completion(&vfork);get_task_struct(p);}wake_up_new_task(p);/* forking complete and child started to run, tell ptracer */if (unlikely(trace))ptrace_event_pid(trace, pid);if (clone_flags & CLONE_VFORK) {if (!wait_for_vfork_done(p, &vfork))ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);}put_pid(pid);} else {nr = PTR_ERR(p);}return nr; }do_fork() 函數生成一個新的進程,大致分為三個步驟。
1、建立進程控制結構并賦初值,使其成為進程映像。
2、為新進程的執行設置跟蹤進程執行情況的相關內核數據結構。包括 任務數組、自由時間列表 tarray_freelist 以及 pidhash[] 數組。
3、啟動調度程序,使子進程獲得運行的機會。
總結
- 上一篇: python求解线性规划问题
- 下一篇: 人工智能数学基础--概率与统计8:一个很