ag旗舰厅官网_ag旗舰厅下载客户端

热门关键词: ag旗舰厅官网,ag旗舰厅下载客户端

计算机网络

当前位置:ag旗舰厅官网 > 计算机网络 > fork之后发生了怎样,Linux进度的基本知识

fork之后发生了怎样,Linux进度的基本知识

来源:http://www.pedaLyourcycLe.com 作者:ag旗舰厅官网 时间:2019-10-24 01:21

进度的内部存款和储蓄器布局

fork之后发生了如何(基于3.16-rc4),fork3.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 #endif
10 }
11 #endif

眼见了么,linux中系统调用便是那样定义的。能够瞥见fork系统调用是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.  When
13      * called from kernel_thread or CLONE_UNTRACED is explicitly
14      * requested, no event is reported; otherwise, report if the event
15      * 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         else
23             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 pointer
33      * 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 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_NATIVE 111 p->prev_cputime.utime = p->prev_cputime.stime = 0; 112 #endif 113 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 114 seqlock_init(&p->vtime_seqlock); 115 p->vtime_snap = 0; 116 p->vtime_snap_whence = VTIME_SLEEPING; 117 #endif 118 119 #if defined(SPLIT_RSS_COUNTING) 120 memset(&p->rss_stat, 0, sizeof(p->rss_stat)); 121 #endif 122 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_NUMA 139 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 #endif 146 #ifdef CONFIG_CPUSETS 147 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 #endif 151 #ifdef CONFIG_TRACE_IRQFLAGS 152 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 #endif 166 #ifdef CONFIG_LOCKDEP 167 p->lockdep_depth = 0; /* no locks held yet */ 168 p->curr_chain_key = 0; 169 p->lockdep_recursion = 0; 170 #endif 171 172 #ifdef CONFIG_DEBUG_MUTEXES 173 p->blocked_on = NULL; /* not blocked yet */ 174 #endif 175 #ifdef CONFIG_MEMCG 176 p->memcg_batch.do_batch = 0; 177 p->memcg_batch.memcg = NULL; 178 #endif 179 #ifdef CONFIG_BCACHE 180 p->sequential_io = 0; 181 p->sequential_io_avg = 0; 182 #endif 183 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_BLOCK 237 p->plug = NULL; 238 #endif 239 #ifdef CONFIG_FUTEX 240 p->robust_list = NULL; 241 #ifdef CONFIG_COMPAT 242 p->compat_robust_list = NULL; 243 #endif 244 INIT_LIST_HEAD(&p->pi_state_list); 245 p->pi_state_cache = NULL; 246 #endif 247 /* 248 * sigaltstack should be cleared when sharing the same VM 249 */ 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 the 255 * 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_EMU 260 clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); 261 #endif 262 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 else 274 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(¤t->sighand->siglock); 303 304 /* 305 * Process group and session signals need to be delivered to just the 306 * parent before the fork or both the parent and the child after the 307 * fork. Restart if a signal comes in before we add the new process to 308 * it's process group. 309 * A fatal signal pending means that current will exit, so the new 310 * thread can't slip out of an OOM kill (or normal SIGKILL). 311 */ 312 recalc_sigpending(); 313 if (signal_pending(current)) { 314 spin_unlock(¤t->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(¤t->signal->live); 343 atomic_inc(¤t->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(¤t->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_NUMA 396 mpol_put(p->mempolicy); 397 bad_fork_cleanup_threadgroup_lock: 398 #endif 399 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_STACKPROTECTOR
30     tsk->stack_canary = get_random_int();
31 #endif
32 
33     /*
34      * One for us, one for whoever does the "release_task()" (usually
35      * parent)
36      */
37     atomic_set(&tsk->usage, 2);
38 #ifdef CONFIG_BLK_DEV_IO_TRACE
39     tsk->btrace_seq = 0;
40 #endif
41     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 path
11      *  - any previously selected cpu might disappear through hotplug
12      */
13     set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
14 #endif
15 
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_SMP
24     if (p->sched_class->task_woken)
25         p->sched_class->task_woken(rq, p);
26 #endif
27     task_rq_unlock(rq, p, &flags);
28 }

该函数一时放到这里,带自身把进程调治那块的博文完毕未来,再通盘这里。该函数实践完后,第68行父进程再次来到子进度的pid号,回到do_fork中,子进度创造的职业就变成了。从此以后老爹和儿子进度公平的插足进程调节。

进程从逻辑上能够分成

1.Text:程序的指令

在linux c编程中,大家得以接收fork,vfork,clone两个系统调用来创建子进度。上面大家先解析下...

2.Data:程序选择的静态变量

3.Heap:程序能够动态分分配的定额外累积空间的区域

3.Stack:当调用函数和再次来到函数是那片内部存款和储蓄器空间增进和紧缩,用来给部分变量和函数调用s时有关的新闻分配空间的内部存款和储蓄器区域

进程的开创和举行

1.创立:一个经过经过调用fork()系统调用创制二个子历程(调用fork()的是父进度)

        调用fork()时,制造的子进度复制父进程的data,heap,stack段,共享父进度的Text段(Text段只读)

2.实施:子进程能够通过调用execve()函数来载入和平运动行另二个顺序,那时子进度的Text,Data,Heap,Stack将被新程序对应的东西替换

        C library里面有部分exec最早的函数功能是大概的

经过的停下和停息景况

1.自杀:调用_exit()(或然连带的library中的exit()函数)

2.他杀:给进度传送某种signal

_exit()能够内定终结的动静(终结的动静平日便是八个异常的小的板寸)

透过某种signal终结进度,终结的意况遵照signal的体系而各异

父进度经过wait()系统调用函数能够获取子进程终结后的终结状态

进程本人的三种ID

1.每叁个历程都有一个process identifier(PID)和parent process identifier(PPID)

进程与客商和组相关的后生可畏对ID

1.Real user id 标记进度属于哪个客商

  Real group id 注明进度属于哪组群组

2.Effective user id 基于那一个顾客id,进度对某个能源的权能

  Effective group id 根据这些群组id,进度对某个财富的权力

  那三个常备与real xxx id是千篇后生可畏律的值,那五个值能够改进的

3.Supplementary IDs 这几个ids表示一些额外的群组,而经过属于那些群组

  (以上3种那么些IDs值承继自父进度)

privileged process(特权进度) 和 unprivileged process

1.privileged process:Effective user id 值为0的进程,id的值为0意味着是一级客商,能够绕开权限的范围

2.unprivileged process:Effective user id 的值非0的进度,要根据权限来实行

capabilities(能力)

从kernel2.2发轫,Linux将privileges分成大器晚成多级迥然分歧的单元叫做capabilities.每多个privileged operation关联到三个活灵活现的capability,每三个经过能够实行有些操作仅当以此历程有对应的capability。古板的super process具备全数的capabilities。

init process

当运转操作系统的之后基本成立贰个叫init的进程,它是装有进程的父进度,init是程序的路线为/sbin/init(在Fedora15中/sbin/init是贰个链接 真正文件为/bin/systemd) init进程具备super user权限並且经过号为1。init进度唯有在shut down时才干被干掉,纵然super user也杀不了它。

daemon process

和别的进度大约,有八个特点

1.不足为道长日子生存,日常景观下与系统同病相怜。(当然能够kill掉)

2.在后台运转,未有决定终端让它输入或输出

如syslogd进程

environment list

每贰个经过都有三个environment list,它是在经过的客户空间中被保卫安全的会集environment variables。每三个元素是 名字和值 组成的,通过fork()创制二个新进度时,environment list承接自父进度。当通过exec()类别的函数替换进度的前后相继时,能够由此钦赐environment list来替换本来的,或然不点名则保留原本进度的。C语言程序能够经过行使外界变量char **environ来获取environment list只怕改革它。

resource limits

每二个进程都要消耗一些能源如张开文件,内部存款和储蓄器,cpu时间。通过调用系统调用setrlimit(),三个历程能够范围花费各个能源的上限。每风华正茂种财富节制有三个有关的值:二个是soft limit,这些界定进程消耗电源的数额;另一个是hard limit,那几个是三个同意调度的soft limit的值的上限。三个unprivileged process仅仅能调动soft limit的值在0-hard limit之间,只可以收缩hard limit的值,无法充实。fork()二个新进度,那几个新进度的resource limits承袭自父进度。shell能够因而ulimit改造limits的值。

图片 2

本文由ag旗舰厅官网发布于计算机网络,转载请注明出处:fork之后发生了怎样,Linux进度的基本知识

关键词:

上一篇:怎么是内核

下一篇:没有了