`

窥探 kernel,just for fun --- copy_process

阅读更多

本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7479714

邮箱:muge0913@sina.com


在do_fork中调用了copy_process,该函数及其重要。该函数创建进程描述符和子进程需要的其他数据结构。它定义在linux2.6.xxx/kernel/fork.c。

只对关键部分进行了注释如下:

 

  1. /* 
  2.  * This creates a new process as a copy of the old one, 
  3.  * but does not actually start it yet. 
  4.  * 
  5.  * It copies the registers, and all the appropriate 
  6.  * parts of the process environment (as per the clone 
  7.  * flags). The actual kick-off is left to the caller. 
  8.  */  
  9.    
  10.    
  11.  /*这部分代码是在2.6.38中实现的*/  
  12. static struct task_struct *copy_process(unsigned long clone_flags,  
  13.                     unsigned long stack_start,  
  14.                     struct pt_regs *regs,  
  15.                     unsigned long stack_size,  
  16.                     int __user *child_tidptr,  
  17.                     struct pid *pid,  
  18.                     int trace)  
  19. {  
  20.     int retval;  
  21.     struct task_struct *p;//保存新的进程描述符地址  
  22.     int cgroup_callbacks_done = 0;  
  23.     /*CLONE_NEWNS和CLONE_FS是冲突的不能同时设置,否则出错*/  
  24.     if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))  
  25.         return ERR_PTR(-EINVAL);  
  26.   
  27.     /* 
  28.      * Thread groups must share signals as well, and detached threads 
  29.      * can only be started up within the thread group. 
  30.      */  
  31.      /*CLONE_THREAD和CLONE_SIGHAND是冲突的不能同时设置,否则出错*/  
  32.     if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))  
  33.         return ERR_PTR(-EINVAL);  
  34.   
  35.     /* 
  36.      * Shared signal handlers imply shared VM. By way of the above, 
  37.      * thread groups also imply shared VM. Blocking this case allows 
  38.      * for various simplifications in other code. 
  39.      */  
  40.      /*CLONE_SIGHAND和CLONE_VM冲突不能同时设置。否则出错*/  
  41.     if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))  
  42.         return ERR_PTR(-EINVAL);  
  43.   
  44.     /* 
  45.      * Siblings of global init remain as zombies on exit since they are 
  46.      * not reaped by their parent (swapper). To solve this and to avoid 
  47.      * multi-rooted process trees, prevent global and container-inits 
  48.      * from creating siblings. 
  49.      */  
  50.     if ((clone_flags & CLONE_PARENT) &&  
  51.                 current->signal->flags & SIGNAL_UNKILLABLE)  
  52.         return ERR_PTR(-EINVAL);  
  53.     /*调用系统安全框架创建进程,在配置内核时没有选择CONFIG_SECURITY,则系统安全框架函数为空*/  
  54.     retval = security_task_create(clone_flags);  
  55.     if (retval)  
  56.         goto fork_out;  
  57.   
  58.     retval = -ENOMEM;  
  59.     /*来复制一份当前进程的进程描述符,为子进程描述符做准备 
  60.     *该函数为子进程创建一个新的内核栈,并分配一个新的进程描述符和thread_info结构,然后 
  61.     *把父进程的进程描述符和thread_info拷贝进去。这里是完全拷贝,子进程和父进程的描述符完全 
  62.     *相同。 
  63.     */  
  64.     p = dup_task_struct(current);  
  65.     if (!p)  
  66.         goto fork_out;  
  67.   
  68.     ftrace_graph_init_task(p);  
  69.   
  70.     rt_mutex_init_task(p);  
  71.   
  72. #ifdef CONFIG_PROVE_LOCKING  
  73.     DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);  
  74.     DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);  
  75. #endif  
  76.   
  77.     /*判断是否超出了设置权限*/  
  78.     retval = -EAGAIN;  
  79.     if (atomic_read(&p->real_cred->user->processes) >=  
  80.             task_rlimit(p, RLIMIT_NPROC)) {  
  81.         if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&  
  82.             p->real_cred->user != INIT_USER)  
  83.             goto bad_fork_free;  
  84.     }  
  85.   
  86.     retval = copy_creds(p, clone_flags);  
  87.     if (retval < 0)  
  88.         goto bad_fork_free;  
  89.   
  90.     /* 
  91.      * If multiple threads are within copy_process(), then this check 
  92.      * triggers too late. This doesn't hurt, the check is only there 
  93.      * to stop root fork bombs. 
  94.      */  
  95.      /*判断线程数量是否超出系统允许范围,否则释放已经申请到的资源*/  
  96.     retval = -EAGAIN;  
  97.     if (nr_threads >= max_threads)//max_threads在kernel_fork中的fork_init中有定义。  
  98.                     //系统最大进程数和系统的内存有关  
  99.         goto bad_fork_cleanup_count;  
  100.   
  101.   
  102.     /*下面的代码主要是对子进程的描述符初始化和复制父进程的资源给子进程*/  
  103.       
  104.       
  105.     /*模块引用计数操作*/  
  106.     if (!try_module_get(task_thread_info(p)->exec_domain->module))  
  107.         goto bad_fork_cleanup_count;  
  108.     /*execve系统调用数初始化为0*/  
  109.     p->did_exec = 0;  
  110.     delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */  
  111.     /*设置状态标记,因为目前状态表示是从父进程拷贝过来的*/  
  112.     copy_flags(clone_flags, p);  
  113.     INIT_LIST_HEAD(&p->children);  
  114.     INIT_LIST_HEAD(&p->sibling);  
  115.     rcu_copy_process(p);  
  116.     p->vfork_done = NULL;  
  117.     spin_lock_init(&p->alloc_lock);  
  118.   
  119.     init_sigpending(&p->pending);  
  120.   
  121.     p->utime = cputime_zero;  
  122.     p->stime = cputime_zero;  
  123.     p->gtime = cputime_zero;  
  124.     p->utimescaled = cputime_zero;  
  125.     p->stimescaled = cputime_zero;  
  126. #ifndef CONFIG_VIRT_CPU_ACCOUNTING  
  127.     p->prev_utime = cputime_zero;  
  128.     p->prev_stime = cputime_zero;  
  129. #endif  
  130. #if defined(SPLIT_RSS_COUNTING)  
  131.     memset(&p->rss_stat, 0, sizeof(p->rss_stat));  
  132. #endif  
  133.   
  134.     p->default_timer_slack_ns = current->timer_slack_ns;  
  135.   
  136.     task_io_accounting_init(&p->ioac);  
  137.     acct_clear_integrals(p);  
  138.   
  139.     posix_cpu_timers_init(p);  
  140.   
  141.     p->lock_depth = -1;      /* -1 = no lock */  
  142.     do_posix_clock_monotonic_gettime(&p->start_time);  
  143.     p->real_start_time = p->start_time;  
  144.     monotonic_to_bootbased(&p->real_start_time);  
  145.     p->io_context = NULL;  
  146.     p->audit_context = NULL;  
  147.     cgroup_fork(p);  
  148. #ifdef CONFIG_NUMA  
  149.     p->mempolicy = mpol_dup(p->mempolicy);  
  150.     if (IS_ERR(p->mempolicy)) {  
  151.         retval = PTR_ERR(p->mempolicy);  
  152.         p->mempolicy = NULL;  
  153.         goto bad_fork_cleanup_cgroup;  
  154.     }  
  155.     mpol_fix_fork_child_flag(p);  
  156. #endif  
  157. #ifdef CONFIG_TRACE_IRQFLAGS  
  158.     p->irq_events = 0;  
  159. #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW  
  160.     p->hardirqs_enabled = 1;  
  161. #else  
  162.     p->hardirqs_enabled = 0;  
  163. #endif  
  164.     p->hardirq_enable_ip = 0;  
  165.     p->hardirq_enable_event = 0;  
  166.     p->hardirq_disable_ip = _THIS_IP_;  
  167.     p->hardirq_disable_event = 0;  
  168.     p->softirqs_enabled = 1;  
  169.     p->softirq_enable_ip = _THIS_IP_;  
  170.     p->softirq_enable_event = 0;  
  171.     p->softirq_disable_ip = 0;  
  172.     p->softirq_disable_event = 0;  
  173.     p->hardirq_context = 0;  
  174.     p->softirq_context = 0;  
  175. #endif  
  176. #ifdef CONFIG_LOCKDEP  
  177.     p->lockdep_depth = 0; /* no locks held yet */  
  178.     p->curr_chain_key = 0;  
  179.     p->lockdep_recursion = 0;  
  180. #endif  
  181.   
  182. #ifdef CONFIG_DEBUG_MUTEXES  
  183.     p->blocked_on = NULL; /* not blocked yet */  
  184. #endif  
  185. #ifdef CONFIG_CGROUP_MEM_RES_CTLR  
  186.     p->memcg_batch.do_batch = 0;  
  187.     p->memcg_batch.memcg = NULL;  
  188. #endif  
  189.   
  190.     /* Perform scheduler related setup. Assign this task to a CPU. */  
  191.     sched_fork(p, clone_flags);  
  192.   
  193.     retval = perf_event_init_task(p);  
  194.     if (retval)  
  195.         goto bad_fork_cleanup_policy;  
  196.   
  197.     if ((retval = audit_alloc(p)))  
  198.         goto bad_fork_cleanup_policy;  
  199.     /* copy all the process information */  
  200.     if ((retval = copy_semundo(clone_flags, p)))  
  201.         goto bad_fork_cleanup_audit;  
  202.     if ((retval = copy_files(clone_flags, p)))  
  203.         goto bad_fork_cleanup_semundo;  
  204.     if ((retval = copy_fs(clone_flags, p)))  
  205.         goto bad_fork_cleanup_files;  
  206.     if ((retval = copy_sighand(clone_flags, p)))  
  207.         goto bad_fork_cleanup_fs;  
  208.     if ((retval = copy_signal(clone_flags, p)))  
  209.         goto bad_fork_cleanup_sighand;  
  210.     if ((retval = copy_mm(clone_flags, p)))  
  211.         goto bad_fork_cleanup_signal;  
  212.     if ((retval = copy_namespaces(clone_flags, p)))  
  213.         goto bad_fork_cleanup_mm;  
  214.     if ((retval = copy_io(clone_flags, p)))  
  215.         goto bad_fork_cleanup_namespaces;  
  216.     retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);  
  217.     if (retval)  
  218.         goto bad_fork_cleanup_io;  
  219.   
  220.     if (pid != &init_struct_pid) {  
  221.         retval = -ENOMEM;  
  222.         pid = alloc_pid(p->nsproxy->pid_ns);  
  223.         if (!pid)  
  224.             goto bad_fork_cleanup_io;  
  225.   
  226.         if (clone_flags & CLONE_NEWPID) {  
  227.             retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);  
  228.             if (retval < 0)  
  229.                 goto bad_fork_free_pid;  
  230.         }  
  231.     }  
  232.   
  233.     p->pid = pid_nr(pid);  
  234.     p->tgid = p->pid;  
  235.     if (clone_flags & CLONE_THREAD)  
  236.         p->tgid = current->tgid;  
  237.   
  238.     if (current->nsproxy != p->nsproxy) {  
  239.         retval = ns_cgroup_clone(p, pid);  
  240.         if (retval)  
  241.             goto bad_fork_free_pid;  
  242.     }  
  243.   
  244.     p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;  
  245.     /* 
  246.      * Clear TID on mm_release()? 
  247.      */  
  248.     p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr:   
  249. NULL;  
  250. #ifdef CONFIG_FUTEX  
  251.     p->robust_list = NULL;  
  252. #ifdef CONFIG_COMPAT  
  253.     p->compat_robust_list = NULL;  
  254. #endif  
  255.     INIT_LIST_HEAD(&p->pi_state_list);  
  256.     p->pi_state_cache = NULL;  
  257. #endif  
  258.     /* 
  259.      * sigaltstack should be cleared when sharing the same VM 
  260.      */  
  261.     if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)  
  262.         p->sas_ss_sp = p->sas_ss_size = 0;  
  263.   
  264.     /* 
  265.      * Syscall tracing and stepping should be turned off in the 
  266.      * child regardless of CLONE_PTRACE. 
  267.      */  
  268.     user_disable_single_step(p);  
  269.     clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);  
  270. #ifdef TIF_SYSCALL_EMU  
  271.     clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);  
  272. #endif  
  273.     clear_all_latency_tracing(p);  
  274.   
  275.     /* ok, now we should be set up.. */  
  276.     p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);  
  277.     p->pdeath_signal = 0;  
  278.     p->exit_state = 0;  
  279.   
  280.     /* 
  281.      * Ok, make it visible to the rest of the system. 
  282.      * We dont wake it up yet. 
  283.      */  
  284.     p->group_leader = p;  
  285.     INIT_LIST_HEAD(&p->thread_group);  
  286.   
  287.     /* Now that the task is set up, run cgroup callbacks if 
  288.      * necessary. We need to run them before the task is visible 
  289.      * on the tasklist. */  
  290.     cgroup_fork_callbacks(p);  
  291.     cgroup_callbacks_done = 1;  
  292.   
  293.     /* Need tasklist lock for parent etc handling! */  
  294.     write_lock_irq(&tasklist_lock);  
  295.   
  296.     /* CLONE_PARENT re-uses the old parent */  
  297.     if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {  
  298.         p->real_parent = current->real_parent;  
  299.         p->parent_exec_id = current->parent_exec_id;  
  300.     } else {  
  301.         p->real_parent = current;  
  302.         p->parent_exec_id = current->self_exec_id;  
  303.     }  
  304.   
  305.     spin_lock(¤t->sighand->siglock);  
  306.   
  307.     /* 
  308.      * Process group and session signals need to be delivered to just the 
  309.      * parent before the fork or both the parent and the child after the 
  310.      * fork. Restart if a signal comes in before we add the new process to 
  311.      * it's process group. 
  312.      * A fatal signal pending means that current will exit, so the new 
  313.      * thread can't slip out of an OOM kill (or normal SIGKILL). 
  314.      */  
  315.     recalc_sigpending();  
  316.     if (signal_pending(current)) {  
  317.         spin_unlock(¤t->sighand->siglock);  
  318.         write_unlock_irq(&tasklist_lock);  
  319.         retval = -ERESTARTNOINTR;  
  320.         goto bad_fork_free_pid;  
  321.     }  
  322.   
  323.     if (clone_flags & CLONE_THREAD) {  
  324.         current->signal->nr_threads++;  
  325.         atomic_inc(¤t->signal->live);  
  326.         atomic_inc(¤t->signal->sigcnt);  
  327.         p->group_leader = current->group_leader;  
  328.         list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);  
  329.     }  
  330.   
  331.     if (likely(p->pid)) {  
  332.         tracehook_finish_clone(p, clone_flags, trace);  
  333.   
  334.         if (thread_group_leader(p)) {  
  335.             if (clone_flags & CLONE_NEWPID)  
  336.                 p->nsproxy->pid_ns->child_reaper = p;  
  337.   
  338.             p->signal->leader_pid = pid;  
  339.             p->signal->tty = tty_kref_get(current->signal->tty);  
  340.             attach_pid(p, PIDTYPE_PGID, task_pgrp(current));  
  341.             attach_pid(p, PIDTYPE_SID, task_session(current));  
  342.             list_add_tail(&p->sibling, &p->real_parent->children);  
  343.             list_add_tail_rcu(&p->tasks, &init_task.tasks);  
  344.             __get_cpu_var(process_counts)++;  
  345.         }  
  346.         attach_pid(p, PIDTYPE_PID, pid);  
  347.         nr_threads++;  
  348.     }  
  349.   
  350.     total_forks++;  
  351.     spin_unlock(¤t->sighand->siglock);  
  352.     write_unlock_irq(&tasklist_lock);  
  353.     proc_fork_connector(p);  
  354.     cgroup_post_fork(p);  
  355.     perf_event_fork(p);  
  356.     /*返回子进程描述符的指针*/  
  357.     return p;  
  358.   
  359. bad_fork_free_pid:  
  360.     if (pid != &init_struct_pid)  
  361.         free_pid(pid);  
  362. bad_fork_cleanup_io:  
  363.     if (p->io_context)  
  364.         exit_io_context(p);  
  365. bad_fork_cleanup_namespaces:  
  366.     exit_task_namespaces(p);  
  367. bad_fork_cleanup_mm:  
  368.     if (p->mm) {  
  369.         task_lock(p);  
  370.         if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)  
  371.             atomic_dec(&p->mm->oom_disable_count);  
  372.         task_unlock(p);  
  373.         mmput(p->mm);  
  374.     }  
  375. bad_fork_cleanup_signal:  
  376.     if (!(clone_flags & CLONE_THREAD))  
  377.         free_signal_struct(p->signal);  
  378. bad_fork_cleanup_sighand:  
  379.     __cleanup_sighand(p->sighand);  
  380. bad_fork_cleanup_fs:  
  381.     exit_fs(p); /* blocking */  
  382. bad_fork_cleanup_files:  
  383.     exit_files(p); /* blocking */  
  384. bad_fork_cleanup_semundo:  
  385.     exit_sem(p);  
  386. bad_fork_cleanup_audit:  
  387.     audit_free(p);  
  388. bad_fork_cleanup_policy:  
  389.     perf_event_free_task(p);  
  390. #ifdef CONFIG_NUMA  
  391.     mpol_put(p->mempolicy);  
  392. bad_fork_cleanup_cgroup:  
  393. #endif  
  394.     cgroup_exit(p, cgroup_callbacks_done);  
  395.     delayacct_tsk_free(p);  
  396.     module_put(task_thread_info(p)->exec_domain->module);  
  397. bad_fork_cleanup_count:  
  398.     atomic_dec(&p->cred->user->processes);  
  399.     exit_creds(p);  
  400. bad_fork_free:  
  401.     free_task(p);  
  402. fork_out:  
  403.     return ERR_PTR(retval);  
  404. }  

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics