亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

fork之后發生了什么(基于3.16-rc4)

2024-06-28 13:24:59
字體:
來源:轉載
供稿:網友
fork之后發生了什么(基于3.16-rc4)

在linux c編程中,我們可以使用fork,vfork,clone三個系統調用來創建子進程。下面我們先分析下fork系統調用的實現原理。代碼如下(kernel/fork.c):

 1 #ifdef __ARCH_WANT_SYS_FORK 2 SYSCALL_DEFINE0(fork) 3 { 4 #ifdef CONFIG_MMU 5     return do_fork(SIGCHLD, 0, 0, NULL, NULL); 6 #else 7     /* can not support in nommu mode */ 8     return -EINVAL; 9 #endif10 }11 #endif

看見了么,linux中系統調用就是這樣定義的??梢钥匆奻ork系統調用是do_fork函數的一個封裝,它會通過軟中斷(系統門)的形式跳到內核函數do_fork中。下面我們來分析下do_fork函數(kernel/fork.c):

 1 long do_fork(unsigned long clone_flags, 2           unsigned long stack_start, 3           unsigned long stack_size, 4           int __user *parent_tidptr, 5           int __user *child_tidptr) 6 { 7     struct task_struct *p; 8     int trace = 0; 9     long nr;10 11     /*12      * Determine whether and which event to report to ptracer.  When13      * called from kernel_thread or CLONE_UNTRACED is explicitly14      * requested, no event is reported; otherwise, report if the event15      * for the type of forking is enabled.16      */17     if (!(clone_flags & CLONE_UNTRACED)) {18         if (clone_flags & CLONE_VFORK)19             trace = PTRACE_EVENT_VFORK;20         else if ((clone_flags & CSIGNAL) != SIGCHLD)21             trace = PTRACE_EVENT_CLONE;22         else23             trace = PTRACE_EVENT_FORK;24 25         if (likely(!ptrace_event_enabled(current, trace)))26             trace = 0;27     }28 29     p = copy_PRocess(clone_flags, stack_start, stack_size,30              child_tidptr, NULL, trace);31     /*32      * Do this prior waking up the new thread - the thread pointer33      * might get invalid after that point, if the thread exits quickly.34      */35     if (!IS_ERR(p)) {36         struct completion vfork;37         struct pid *pid;38 39         trace_sched_process_fork(current, p);40 41         pid = get_task_pid(p, PIDTYPE_PID);42         nr = pid_vnr(pid);43 44         if (clone_flags & CLONE_PARENT_SETTID)45             put_user(nr, parent_tidptr);46 47         if (clone_flags & CLONE_VFORK) {48             p->vfork_done = &vfork;49             init_completion(&vfork);50             get_task_struct(p);51         }52 53         wake_up_new_task(p);54 55         /* forking complete and child started to run, tell ptracer */56         if (unlikely(trace))57             ptrace_event_pid(trace, pid);58 59         if (clone_flags & CLONE_VFORK) {60             if (!wait_for_vfork_done(p, &vfork))61                 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);62         }63 64         put_pid(pid);65     } else {66         nr = PTR_ERR(p);67     }68     return nr;69 }

第17-27行對函數接收到的標志進行判斷,如果設置了追蹤標志,則依據創建進程所使用的系統調用,在trace變量中放入不同的類型值。第29行創建子進程的描述符以及其他的數據結構,返回值為子進程的描述符指針,保存在變量p中,該函數可以說最核心的函數,待會來分析它。第35行,如果p指針沒有出錯,則進入if體。第41行獲取子進程的pid號。第42行更新子進程的pid命名空間,并獲得進程的pid號,存放在nr變量中。第44-45行,如果設置了CLONE_PARENT_SETTID標志,則將子進程的命名空間保存到父進程的一個用戶態變量中,該變量的指針就是傳進來的參數parent_tidptr。該函數中大部分是跟子進程追蹤有關,我們暫且不分析這部分,主要分析下copy_process函數,代碼如下(kernel/fork.c):

  1 static struct task_struct *copy_process(unsigned long clone_flags,  2                     unsigned long stack_start,  3                     unsigned long stack_size,  4                     int __user *child_tidptr,  5                     struct pid *pid,  6                     int trace)  7 {  8     int retval;  9     struct task_struct *p; 10  11     if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) 12         return ERR_PTR(-EINVAL); 13  14     if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) 15         return ERR_PTR(-EINVAL); 16  17     /* 18      * Thread groups must share signals as well, and detached threads 19      * can only be started up within the thread group. 20      */ 21     if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) 22         return ERR_PTR(-EINVAL); 23  24     /* 25      * Shared signal handlers imply shared VM. By way of the above, 26      * thread groups also imply shared VM. Blocking this case allows 27      * for various simplifications in other code. 28      */ 29     if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) 30         return ERR_PTR(-EINVAL); 31  32     /* 33      * Siblings of global init remain as zombies on exit since they are 34      * not reaped by their parent (swapper). To solve this and to avoid 35      * multi-rooted process trees, prevent global and container-inits 36      * from creating siblings. 37      */ 38     if ((clone_flags & CLONE_PARENT) && 39                 current->signal->flags & SIGNAL_UNKILLABLE) 40         return ERR_PTR(-EINVAL); 41  42     /* 43      * If the new process will be in a different pid or user namespace 44      * do not allow it to share a thread group or signal handlers or 45      * parent with the forking task. 46      */ 47     if (clone_flags & CLONE_SIGHAND) { 48         if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) || 49             (task_active_pid_ns(current) != 50                 current->nsproxy->pid_ns_for_children)) 51             return ERR_PTR(-EINVAL); 52     } 53  54     retval = security_task_create(clone_flags); 55     if (retval) 56         goto fork_out; 57  58     retval = -ENOMEM; 59     p = dup_task_struct(current); 60     if (!p) 61         goto fork_out; 62  63     ftrace_graph_init_task(p); 64     get_seccomp_filter(p); 65  66     rt_mutex_init_task(p); 67  68 #ifdef CONFIG_PROVE_LOCKING 69     DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); 70     DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); 71 #endif 72     retval = -EAGAIN; 73     if (atomic_read(&p->real_cred->user->processes) >= 74             task_rlimit(p, RLIMIT_NPROC)) { 75         if (p->real_cred->user != INIT_USER && 76             !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) 77             goto bad_fork_free; 78     } 79     current->flags &= ~PF_NPROC_EXCEEDED; 80  81     retval = copy_creds(p, clone_flags); 82     if (retval < 0) 83         goto bad_fork_free; 84  85     /* 86      * If multiple threads are within copy_process(), then this check 87      * triggers too late. This doesn't hurt, the check is only there 88      * to stop root fork bombs. 89      */ 90     retval = -EAGAIN; 91     if (nr_threads >= max_threads) 92         goto bad_fork_cleanup_count; 93  94     if (!try_module_get(task_thread_info(p)->exec_domain->module)) 95         goto bad_fork_cleanup_count; 96  97     delayacct_tsk_init(p);    /* Must remain after dup_task_struct() */ 98     p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); 99     p->flags |= PF_FORKNOEXEC;100     INIT_LIST_HEAD(&p->children);101     INIT_LIST_HEAD(&p->sibling);102     rcu_copy_process(p);103     p->vfork_done = NULL;104     spin_lock_init(&p->alloc_lock);105 106     init_sigpending(&p->pending);107 108     p->utime = p->stime = p->gtime = 0;109     p->utimescaled = p->stimescaled = 0;110 #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE111     p->prev_cputime.utime = p->prev_cputime.stime = 0;112 #endif113 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN114     seqlock_init(&p->vtime_seqlock);115     p->vtime_snap = 0;116     p->vtime_snap_whence = VTIME_SLEEPING;117 #endif118 119 #if defined(SPLIT_rss_COUNTING)120     memset(&p->rss_stat, 0, sizeof(p->rss_stat));121 #endif122 123     p->default_timer_slack_ns = current->timer_slack_ns;124 125     task_io_accounting_init(&p->ioac);126     acct_clear_integrals(p);127 128     posix_cpu_timers_init(p);129 130     do_posix_clock_monotonic_gettime(&p->start_time);131     p->real_start_time = p->start_time;132     monotonic_to_bootbased(&p->real_start_time);133     p->io_context = NULL;134     p->audit_context = NULL;135     if (clone_flags & CLONE_THREAD)136         threadgroup_change_begin(current);137     cgroup_fork(p);138 #ifdef CONFIG_NUMA139     p->mempolicy = mpol_dup(p->mempolicy);140     if (IS_ERR(p->mempolicy)) {141         retval = PTR_ERR(p->mempolicy);142         p->mempolicy = NULL;143         goto bad_fork_cleanup_threadgroup_lock;144     }145 #endif146 #ifdef CONFIG_CPUSETS147     p->cpuset_mem_spread_rotor = NUMA_NO_NODE;148     p->cpuset_slab_spread_rotor = NUMA_NO_NODE;149     seqcount_init(&p->mems_allowed_seq);150 #endif151 #ifdef CONFIG_TRACE_IRQFLAGS152     p->irq_events = 0;153     p->hardirqs_enabled = 0;154     p->hardirq_enable_ip = 0;155     p->hardirq_enable_event = 0;156     p->hardirq_disable_ip = _THIS_IP_;157     p->hardirq_disable_event = 0;158     p->softirqs_enabled = 1;159     p->softirq_enable_ip = _THIS_IP_;160     p->softirq_enable_event = 0;161     p->softirq_disable_ip = 0;162     p->softirq_disable_event = 0;163     p->hardirq_context = 0;164     p->softirq_context = 0;165 #endif166 #ifdef CONFIG_LOCKDEP167     p->lockdep_depth = 0; /* no locks held yet */168     p->curr_chain_key = 0;169     p->lockdep_recursion = 0;170 #endif171 172 #ifdef CONFIG_DEBUG_MUTEXES173     p->blocked_on = NULL; /* not blocked yet */174 #endif175 #ifdef CONFIG_MEMCG176     p->memcg_batch.do_batch = 0;177     p->memcg_batch.memcg = NULL;178 #endif179 #ifdef CONFIG_BCACHE180     p->sequential_io    = 0;181     p->sequential_io_avg    = 0;182 #endif183 184     /* Perform scheduler related setup. Assign this task to a CPU. */185     retval = sched_fork(clone_flags, p);186     if (retval)187         goto bad_fork_cleanup_policy;188 189     retval = perf_event_init_task(p);190     if (retval)191         goto bad_fork_cleanup_policy;192     retval = audit_alloc(p);193     if (retval)194         goto bad_fork_cleanup_policy;195     /* copy all the process information */196     retval = copy_semundo(clone_flags, p);197     if (retval)198         goto bad_fork_cleanup_audit;199     retval = copy_files(clone_flags, p);200     if (retval)201         goto bad_fork_cleanup_semundo;202     retval = copy_fs(clone_flags, p);203     if (retval)204         goto bad_fork_cleanup_files;205     retval = copy_sighand(clone_flags, p);206     if (retval)207         goto bad_fork_cleanup_fs;208     retval = copy_signal(clone_flags, p);209     if (retval)210         goto bad_fork_cleanup_sighand;211     retval = copy_mm(clone_flags, p);212     if (retval)213         goto bad_fork_cleanup_signal;214     retval = copy_namespaces(clone_flags, p);215     if (retval)216         goto bad_fork_cleanup_mm;217     retval = copy_io(clone_flags, p);218     if (retval)219         goto bad_fork_cleanup_namespaces;220     retval = copy_thread(clone_flags, stack_start, stack_size, p);221     if (retval)222         goto bad_fork_cleanup_io;223 224     if (pid != &init_struct_pid) {225         retval = -ENOMEM;226         pid = alloc_pid(p->nsproxy->pid_ns_for_children);227         if (!pid)228             goto bad_fork_cleanup_io;229     }230 231     p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;232     /*233      * Clear TID on mm_release()?234      */235     p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;236 #ifdef CONFIG_BLOCK237     p->plug = NULL;238 #endif239 #ifdef CONFIG_FUTEX240     p->robust_list = NULL;241 #ifdef CONFIG_COMPAT242     p->compat_robust_list = NULL;243 #endif244     INIT_LIST_HEAD(&p->pi_state_list);245     p->pi_state_cache = NULL;246 #endif247     /*248      * sigaltstack should be cleared when sharing the same VM249      */250     if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)251         p->sas_ss_sp = p->sas_ss_size = 0;252 253     /*254      * Syscall tracing and stepping should be turned off in the255      * child regardless of CLONE_PTRACE.256      */257     user_disable_single_step(p);258     clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);259 #ifdef TIF_SYSCALL_EMU260     clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);261 #endif262     clear_all_latency_tracing(p);263 264     /* ok, now we should be set up.. */265     p->pid = pid_nr(pid);266     if (clone_flags & CLONE_THREAD) {267         p->exit_signal = -1;268         p->group_leader = current->group_leader;269         p->tgid = current->tgid;270     } else {271         if (clone_flags & CLONE_PARENT)272             p->exit_signal = current->group_leader->exit_signal;273         else274             p->exit_signal = (clone_flags & CSIGNAL);275         p->group_leader = p;276         p->tgid = p->pid;277     }278 279     p->nr_dirtied = 0;280     p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);281     p->dirty_paused_when = 0;282 283     p->pdeath_signal = 0;284     INIT_LIST_HEAD(&p->thread_group);285     p->task_works = NULL;286 287     /*288      * Make it visible to the rest of the system, but dont wake it up yet.289      * Need tasklist lock for parent etc handling!290      */291     write_lock_irq(&tasklist_lock);292 293     /* CLONE_PARENT re-uses the old parent */294     if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {295         p->real_parent = current->real_parent;296         p->parent_exec_id = current->parent_exec_id;297     } else {298         p->real_parent = current;299         p->parent_exec_id = current->self_exec_id;300     }301 302     spin_lock(&current->sighand->siglock);303 304     /*305      * Process group and session signals need to be delivered to just the306      * parent before the fork or both the parent and the child after the307      * fork. Restart if a signal comes in before we add the new process to308      * it's process group.309      * A fatal signal pending means that current will exit, so the new310      * thread can't slip out of an OOM kill (or normal SIGKILL).311     */312     recalc_sigpending();313     if (signal_pending(current)) {314         spin_unlock(&current->sighand->siglock);315         write_unlock_irq(&tasklist_lock);316         retval = -ERESTARTNOINTR;317         goto bad_fork_free_pid;318     }319 320     if (likely(p->pid)) {321         ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);322 323         init_task_pid(p, PIDTYPE_PID, pid);324         if (thread_group_leader(p)) {325             init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));326             init_task_pid(p, PIDTYPE_SID, task_session(current));327 328             if (is_child_reaper(pid)) {329                 ns_of_pid(pid)->child_reaper = p;330                 p->signal->flags |= SIGNAL_UNKILLABLE;331             }332 333             p->signal->leader_pid = pid;334             p->signal->tty = tty_kref_get(current->signal->tty);335             list_add_tail(&p->sibling, &p->real_parent->children);336             list_add_tail_rcu(&p->tasks, &init_task.tasks);337             attach_pid(p, PIDTYPE_PGID);338             attach_pid(p, PIDTYPE_SID);339             __this_cpu_inc(process_counts);340         } else {341             current->signal->nr_threads++;342             atomic_inc(&current->signal->live);343             atomic_inc(&current->signal->sigcnt);344             list_add_tail_rcu(&p->thread_group,345                       &p->group_leader->thread_group);346             list_add_tail_rcu(&p->thread_node,347                       &p->signal->thread_head);348         }349         attach_pid(p, PIDTYPE_PID);350         nr_threads++;351     }352 353     total_forks++;354     spin_unlock(&current->sighand->siglock);355     syscall_tracepoint_update(p);356     write_unlock_irq(&tasklist_lock);357 358     proc_fork_connector(p);359     cgroup_post_fork(p);360     if (clone_flags & CLONE_THREAD)361         threadgroup_change_end(current);362     perf_event_fork(p);363 364     trace_task_newtask(p, clone_flags);365     uprobe_copy_process(p, clone_flags);366 367     return p;368 369 bad_fork_free_pid:370     if (pid != &init_struct_pid)371         free_pid(pid);372 bad_fork_cleanup_io:373     if (p->io_context)374         exit_io_context(p);375 bad_fork_cleanup_namespaces:376     exit_task_namespaces(p);377 bad_fork_cleanup_mm:378     if (p->mm)379         mmput(p->mm);380 bad_fork_cleanup_signal:381     if (!(clone_flags & CLONE_THREAD))382         free_signal_struct(p->signal);383 bad_fork_cleanup_sighand:384     __cleanup_sighand(p->sighand);385 bad_fork_cleanup_fs:386     exit_fs(p); /* blocking */387 bad_fork_cleanup_files:388     exit_files(p); /* blocking */389 bad_fork_cleanup_semundo:390     exit_sem(p);391 bad_fork_cleanup_audit:392     audit_free(p);393 bad_fork_cleanup_policy:394     perf_event_free_task(p);395 #ifdef CONFIG_NUMA396     mpol_put(p->mempolicy);397 bad_fork_cleanup_threadgroup_lock:398 #endif399     if (clone_flags & CLONE_THREAD)400         threadgroup_change_end(current);401     delayacct_tsk_free(p);402     module_put(task_thread_info(p)->exec_domain->module);403 bad_fork_cleanup_count:404     atomic_dec(&p->cred->user->processes);405     exit_creds(p);406 bad_fork_free:407     free_task(p);408 fork_out:409     return ERR_PTR(retval);410 }
copy_process

第11-52行對傳遞進來的clone_flags標志進行一致性檢查,如果有錯誤,返回錯誤代碼。第54行對clone_flags進行附加性安全檢查。第59行為子進程創建進程描述符。第63行,這個版本的linux內核源碼中該函數為空函數,不研究它。第64行增加子進程p的seccomp.filter結構體成員的引用數量。第66行初始化子進程中的互斥鎖。第73-77行比較子進程的擁有者所擁有的進程數量是否超過限制,如果超過了限制并且該擁有者不是root用戶,就會跳到錯誤處理代碼。第81行將父進程的擁有者信息拷貝給子進程。第91行檢查系統中的進程數量是否超過了限制,nr_threads是內核中的全局變量,存放著進程的總數。第94行檢查子進程的執行域(要執行的代碼)所在的模塊是否已經加載進了內核,如果沒有的話就進行出錯處理。第98-99行對子進程flags進程初始化。第100-101對子進程的孩子鏈表和兄弟鏈表進行初始化。第102行初始化子進程的rcu(一種鎖機制)。第104行初始化子進程的alloc_lock自旋鎖。第106行初始化進程的掛起信號集。第108-116對進行的各種時間進程初始化。第125行初始化子進程的io計數。第126行對子進程的多個計數域進行清零。第128行初始化子進程的定時器。第185-222行,使用了多個copy_***函數創建了子進程要用的各種數據結構,并將父進程的相應結構體中的內容拷貝進來,或者根據flags指定的內容來初始化子進程的這些數據結構。第224-228行,如果傳進來的pid指針和全局結構體變量init_struct_pid的地址不相同的話,就要為子進程分配pid結構體。第265行從pid結構體中獲取到子進程的pid號,保存到子進程描述符的pid域。第266-269行,如果設置了CLONE_THREAD標志,說明子進程和父進程在同一個線程組,那么子進程將繼承父進程的tgid,否則第275-276行,子進程的組領導者就是它自己,組號tgpid是它自己的pid號。第279-281行設置一些和進程臟頁限制有關的成員。下面291-356行的代碼需要關掉中斷并且獲取寫鎖。第294-296行對進程親子關系初始化,如果設置了CLONE_PARENT和CLONE_THREAD標志,子進程的真實父進程設置為它的父進程的真實父進程(它的爺爺進程),否則第298-299行,子進程的真實父進程設置為它的父進程。第302行-354行需要獲取自旋鎖。第321行初始化子進程的ptraced字段(和進程追蹤有關)。第323行,對子進程的pid結構體進行初始化。第324-340行,如果子進程是線程組的組長,則對子進程進行相應處理,其中,第325-326行將子進程的進程組和會話組的組長分別設置為父進程的組領導的進程組和會話組組長,第337-338行,將子進程加入它所在組的哈希鏈表中。否則,子進程不是線程組組長的話,第341-347行不對子進程做pid相關的操作。第349行,同樣要將子進程加入到pid哈希表中。第350行全局變量nr_threads自加1,說明系統中的進程又多了一個。如果整個函數內部沒有出錯的話,第367行返回創建好的子進程描述符指針p。第369行到結束,均為錯誤處理的代碼,如果函數中有出錯的地方,就會跳到這些代碼中。下面我們接著分析第59行的dup_task_struct函數,代碼如下(kernel/fork.c):

 1 static struct task_struct *dup_task_struct(struct task_struct *orig) 2 { 3     struct task_struct *tsk; 4     struct thread_info *ti; 5     unsigned long *stackend; 6     int node = tsk_fork_get_node(orig); 7     int err; 8  9     tsk = alloc_task_struct_node(node);10     if (!tsk)11         return NULL;12 13     ti = alloc_thread_info_node(tsk, node);14     if (!ti)15         goto free_tsk;16 17     err = arch_dup_task_struct(tsk, orig);18     if (err)19         goto free_ti;20 21     tsk->stack = ti;22 23     setup_thread_stack(tsk, orig);24     clear_user_return_notifier(tsk);25     clear_tsk_need_resched(tsk);26     stackend = end_of_stack(tsk);27     *stackend = STACK_END_MAGIC;    /* for overflow detection */28 29 #ifdef CONFIG_CC_STACKPROTECTOR30     tsk->stack_canary = get_random_int();31 #endif32 33     /*34      * One for us, one for whoever does the "release_task()" (usually35      * parent)36      */37     atomic_set(&tsk->usage, 2);38 #ifdef CONFIG_BLK_DEV_IO_TRACE39     tsk->btrace_seq = 0;40 #endif41     tsk->splice_pipe = NULL;42     tsk->task_frag.page = NULL;43 44     account_kernel_stack(ti, 1);45 46     return tsk;47 48 free_ti:49     free_thread_info(ti);50 free_tsk:51     free_task_struct(tsk);52     return NULL;53 }

在該函數中創建了子進程的進程描述符,并將描述符指針返回。第6行,如果使用到了NUMA技術的話,函數返回父進程描述符的pref_node_fork字段值,否則,返回-1。第9行為子進程創建進程描述符,將描述符指針保存在tsk變量中。第13行為子進程創建thread_info結構體(也就是創建內核棧),并返回結構體指針(該指針實際上也是子進程堆棧的內核棧指針)。第17行將父進程描述符的各個成員值全部復制給子進程描述符的成員。第21行將子進程內核棧地址ti賦給stack成員。第23行對子進程的thread_info結構體進行初始化,將父進程的該結構體成員值復制給子進程,然后將子進程的描述符指針存入thread_info結構體的task域(從thread_info就可找到進程描述符了)。第25行清除子進程thread_info結構體中的flag標志(具體而言,就是need_resched標志,取消內核搶占)。第26行將自進程內核棧頂指針保存到stackend變量中。第27行向子進程內核堆棧中存入STACK_END_MAGIC,來進行堆棧溢出檢測。第23行將子進程描述符使用計數置為2(一個表示父進程的引用,一個表示自己)。第44行將子進程的內核棧所在的zone結構體使用計數置為1。第46行返回子進程描述符指針。接下來,我們回到do_fork函數中,第53行wake_up_new_task函數會將剛創建好的子進程加入到運行隊列中并且喚醒它,下面看看該函數(kernel/sched/core.c)。

 1 void wake_up_new_task(struct task_struct *p) 2 { 3     unsigned long flags; 4     struct rq *rq; 5  6     raw_spin_lock_irqsave(&p->pi_lock, flags); 7 #ifdef CONFIG_SMP 8     /* 9      * Fork balancing, do it here and not earlier because:10      *  - cpus_allowed can change in the fork path11      *  - any previously selected cpu might disappear through hotplug12      */13     set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));14 #endif15 16     /* Initialize new task's runnable average */17     init_task_runnable_average(p);18     rq = __task_rq_lock(p);19     activate_task(rq, p, 0);20     p->on_rq = 1;21     trace_sched_wakeup_new(p, true);22     check_preempt_curr(rq, p, WF_FORK);23 #ifdef CONFIG_SMP24     if (p->sched_class->task_woken)25         p->sched_class->task_woken(rq, p);26 #endif27     task_rq_unlock(rq, p, &flags);28 }

該函數暫且放到這里,帶我把進程調度這塊的博文完成之后,再完善這里。該函數執行完后,第68行父進程返回子進程的pid號,回到do_fork中,子進程創建的工作就完成了。此后父子進程公平的參與進程調度。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91情侣偷在线精品国产| 亚洲欧洲日本专区| 中文字幕亚洲欧美日韩2019| 亚洲国产精品一区二区三区| 久久久久久久国产精品| 91高清在线免费观看| 亚洲第一精品福利| 中文字幕日本精品| 精品精品国产国产自在线| 成人黄色生活片| 隔壁老王国产在线精品| 欧美日韩另类视频| 国产成人福利夜色影视| 欧美在线亚洲一区| 亚洲精品ady| 精品久久久久久久久国产字幕| 黄色精品一区二区| 亚洲色图色老头| 日韩高清有码在线| 日本欧美一级片| 亚洲欧美在线x视频| 欲色天天网综合久久| 日韩精品中文字幕久久臀| 日韩精品极品在线观看播放免费视频| 国产精品69久久| 亚洲3p在线观看| 国产精品扒开腿做爽爽爽的视频| 琪琪亚洲精品午夜在线| 日韩av在线电影网| 国产视频999| 国产成人在线播放| 国产视频亚洲精品| 国产精品日韩久久久久| 精品在线观看国产| 国产精品男人爽免费视频1| 国产成人综合一区二区三区| 97人人爽人人喊人人模波多| 精品亚洲夜色av98在线观看| 国产精品免费久久久久久| 精品一区二区三区电影| 91精品国产91久久久久福利| 亚洲毛片在线看| 91成人国产在线观看| 在线免费观看羞羞视频一区二区| 国产精品扒开腿做| 久久久www成人免费精品| 亚洲人成电影在线观看天堂色| 欧美日韩福利在线观看| 亚洲图片欧美日产| 成人精品福利视频| 夜夜嗨av一区二区三区免费区| 欧美激情乱人伦| 萌白酱国产一区二区| 国产一区二区久久精品| 亚洲电影在线观看| 国产欧美日韩亚洲精品| 午夜剧场成人观在线视频免费观看| 国产视频精品一区二区三区| 亚洲高清福利视频| 欧美激情一级精品国产| 久久久久久久影视| 欧美中文字幕第一页| 日韩一区二区精品视频| 97在线视频免费观看| 自拍偷拍免费精品| 亚洲一区免费网站| 久久久欧美一区二区| 欧美xxxx18性欧美| 国产成人一区二区在线| 91精品免费久久久久久久久| 亚洲精品日韩丝袜精品| 最新91在线视频| 欧美性视频在线| 欧美激情三级免费| 国产精品视频大全| 午夜精品国产精品大乳美女| 国产不卡视频在线| 国产欧美在线播放| 亚洲xxx视频| 成人做爰www免费看视频网站| 欧美丰满片xxx777| 亚洲bt天天射| 亚洲激情自拍图| 在线国产精品视频| 国产成人精品综合久久久| 国产精品久久久久aaaa九色| 亚洲欧洲在线看| 亚洲大胆美女视频| 欧美日韩国产一区在线| 国产精品白嫩美女在线观看| 国产美女精品视频免费观看| 久久久91精品国产| 欧美性猛交99久久久久99按摩| 欧美精品在线观看91| 精品久久久视频| 欧美老少配视频| 久久精品视频导航| 亚洲free性xxxx护士白浆| 成人免费淫片视频软件| 国产欧美一区二区三区在线看| 亚洲国产精彩中文乱码av在线播放| 91精品久久久久久久久久入口| 91黑丝在线观看| 欧美福利视频在线观看| 久久久av电影| 亚洲免费一级电影| 久久成人精品视频| 欧美激情视频网站| 欧美巨大黑人极品精男| 中文字幕精品在线| 日韩电影中文字幕在线观看| 一区二区三区在线播放欧美| 欧美高跟鞋交xxxxhd| 国产+成+人+亚洲欧洲| 欧美激情中文字幕乱码免费| 国产精品日韩欧美大师| 91免费人成网站在线观看18| 精品毛片三在线观看| 日韩精品久久久久久福利| 性欧美暴力猛交69hd| 久久福利视频网| 久久大大胆人体| 伦理中文字幕亚洲| 九九热在线精品视频| 成人久久精品视频| 伊人久久久久久久久久久久久| 日韩电影免费在线观看| 久久成年人免费电影| 97视频在线观看视频免费视频| 不卡在线观看电视剧完整版| 91精品视频大全| 久久国产加勒比精品无码| 91精品视频免费观看| 亚洲国产精品悠悠久久琪琪| 色综合男人天堂| 亚洲天堂男人天堂| 狠狠躁夜夜躁人人爽天天天天97| 九九视频这里只有精品| 国产视频在线观看一区二区| 亚洲理论电影网| 日韩精品一区二区三区第95| 岛国av一区二区三区| 欧美高清无遮挡| 色综合久综合久久综合久鬼88| 欧美日韩性视频在线| 美乳少妇欧美精品| 日韩电影免费观看在线| 国产精品一区电影| 亚洲精品国产成人| 欧美一级黑人aaaaaaa做受| 亚洲大胆人体av| 国产v综合ⅴ日韩v欧美大片| 国产成人小视频在线观看| 粉嫩av一区二区三区免费野| 性色av一区二区三区在线观看| 成人a级免费视频| 久久久久久69| 中文字幕国产精品久久| 成人黄色激情网| 91亚洲精品在线| 久久99青青精品免费观看| 日韩国产欧美精品在线| 91精品综合视频| 日韩欧美在线视频日韩欧美在线视频|