Linux从用户层到内核层系列 – 进程管理系列1: 进程之子承父业

释放双眼,带上耳机,听听看~!

题记:本系列文章的目的是抛开书本从源代码和使用的角度分析Linux内核和相关源代码,byhankswang和你一起玩转linux开发


轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.comLinux从用户层到内核层系列 - 进程管理系列1: 进程之子承父业

欢迎加入到CHLK – Linux开发交流群 QQ:327084515 讨论Linux开发相关问题

进程之子承父业

在创建用户进程、用户线程和内核线程的时候,不同的系统调用对新创建的进程或线程如何继承父进程相关的属性?对于虚拟内存、文件系统、相关文件、信号量等等属性是如何区分的的?

1.首先从克隆父进程时的FLAG说起

CLONE时的FLAG就好比父亲签署的文件,直接指定儿子可以继承父亲的哪些家产,哪些目前是父子共用的,哪些需要儿子独立打拼白手起家的,下面的这些FLAG注释简单明了,就不翻译了。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1//within file linux-3.9.3/include/uapi/linux/sched.h
2/*
3 * cloning flags:
4 */
5#define CSIGNAL 0x000000ff/* signal mask to be sent at exit */
6#define CLONE_VM 0x00000100/* set if VM shared between processes */
7#define CLONE_FS 0x00000200/* set if fs info shared between processes */
8#define CLONE_FILES 0x00000400/* set if open files shared between processes */
9#define CLONE_SIGHAND 0x00000800/* set if signal handlers and blocked signals shared */
10#define CLONE_PTRACE 0x00002000/* set if we want to let tracing continue on the child too */
11#define CLONE_VFORK 0x00004000/* set if the parent wants the child to wake it up on mm_release */
12#define CLONE_PARENT 0x00008000/* set if we want to have the same parent as the cloner */
13#define CLONE_THREAD 0x00010000/* Same thread group? */
14#define CLONE_NEWNS 0x00020000/* New namespace group? */
15#define CLONE_SYSVSEM 0x00040000/* share system V SEM_UNDO semantics */
16#define CLONE_SETTLS 0x00080000/* create a new TLS for the child */
17#define CLONE_PARENT_SETTID 0x00100000/* set the TID in the parent */
18#define CLONE_CHILD_CLEARTID 0x00200000/* clear the TID in the child */
19#define CLONE_DETACHED 0x00400000/* Unused, ignored */
20#define CLONE_UNTRACED 0x00800000/* set if the tracing process can't force CLONE_PTRACE on this clone */
21#define CLONE_CHILD_SETTID 0x01000000/* set the TID in the child */
22/* 0x02000000 was previously the unused CLONE_STOPPED (Start in stopped state)
23   and is now available for re-use. */
24#define CLONE_NEWUTS 0x04000000/* New utsname group? */
25#define CLONE_NEWIPC 0x08000000/* New ipcs */
26#define CLONE_NEWUSER 0x10000000/* New user namespace */
27#define CLONE_NEWPID 0x20000000/* New pid namespace */
28#define CLONE_NEWNET 0x40000000/* New network namespace */
29#define CLONE_IO 0x80000000/* Clone io context */
30

2.系统调用fork和vfork

在用户空间我们使用fork来创建一个进程的时候,系统调用fork的实现,可以参考对系统调用的分析博文《
Linux从用户层到内核层系列 – TCP/IP协议栈部分系列6:linux 系统调用中断向量表》和姊妹篇博文《Linux从用户层到内核层系列 – TCP/IP协议栈部分系列11: 再话Linux系统调用》,相信看完这两篇博文之后,对系统调用会有直观的理解。来点干活吧,我们从标记为的角度来看看系统调用fork是如何为子进程合法的获得父进程的资源的。


1
2
3
4
5
6
7
8
9
10
11
12
1#ifdef __ARCH_WANT_SYS_FORK
2SYSCALL_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
12

其实fork函数只是对do_fork函数的一个简单的封装,与处理器平台无关的内核代码部分中,fork、vfork和kernel_thread都对do_fork进程了封装,略有区别的就是标记为的不同,我们再看一下vfork和kernel_thread对do_fork是如何使用标记位的。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1#ifdef __ARCH_WANT_SYS_VFORK
2SYSCALL_DEFINE0(vfork)
3{
4   return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
5           0, NULL, NULL);
6}
7#endif
8
9/*
10 * Create a kernel thread.
11 */
12pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
13{
14  return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
15      (unsigned long)arg, NULL, NULL);
16}
17

源码告诉了我们一切,从用户层开发角度,你说fork和vfork的区别千千万,不过直接看kernel的源码,一目了然。

fork使用的标记位:SIGCHLD     //新创建的子进程终结的时候,发送信号通知其父进程

vfork使用的标记位:CLONE_VFORK | CLONE_VM | SIGCHLD    //新创建的子进程是要共享除了父进程的数据段的,至于如何copy请看内核源码copy_process函数

kernel_thread使用的标记位: CLONE_VM | CLONE_UNTREACED

而且我们


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1#ifdef __ARCH_WANT_SYS_VFORK
2SYSCALL_DEFINE0(vfork)
3{
4   return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
5           0, NULL, NULL);
6}
7#endif
8
9/*
10 * Create a kernel thread.
11 */
12pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
13{
14  return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
15      (unsigned long)arg, NULL, NULL);
16}
17

1
2
1  可以看到,新创建的内核线程是需要指定起始执行函数和其参数的。
2

另外列上源码,看看do_fork的参数:


1
2
1long do_fork(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr)
2

1
2
1  对于创建进程和线程比较重要的do_fork函数和copy_process函数我们这里列出源代码,对于懒的看源码的童鞋可以直接读下面的代码即可。如何使用上面的这些标记为,下面的代码写的清清楚楚,请保持耐心,仔细品味。
2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
1long 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   * Do some preliminary argument and permissions checking before we
13   * actually start allocating stuff
14   */
15  if (clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) {
16      if (clone_flags & (CLONE_THREAD|CLONE_PARENT))
17          return -EINVAL;
18  }
19
20  /*
21   * Determine whether and which event to report to ptracer.  When
22   * called from kernel_thread or CLONE_UNTRACED is explicitly
23   * requested, no event is reported; otherwise, report if the event
24   * for the type of forking is enabled.
25   */
26  if (!(clone_flags & CLONE_UNTRACED)) {
27      if (clone_flags & CLONE_VFORK)
28          trace = PTRACE_EVENT_VFORK;
29      else if ((clone_flags & CSIGNAL) != SIGCHLD)
30          trace = PTRACE_EVENT_CLONE;
31      else
32          trace = PTRACE_EVENT_FORK;
33
34      if (likely(!ptrace_event_enabled(current, trace)))
35          trace = 0;
36  }
37
38  p = copy_process(clone_flags, stack_start, stack_size,
39           child_tidptr, NULL, trace);
40  /*
41   * Do this prior waking up the new thread - the thread pointer
42   * might get invalid after that point, if the thread exits quickly.
43   */
44  if (!IS_ERR(p)) {
45      struct completion vfork;
46
47      trace_sched_process_fork(current, p);
48
49      nr = task_pid_vnr(p);
50
51      if (clone_flags & CLONE_PARENT_SETTID)
52          put_user(nr, parent_tidptr);
53
54      if (clone_flags & CLONE_VFORK) {
55          p->vfork_done = &vfork;
56          init_completion(&vfork);
57          get_task_struct(p);
58      }
59
60      wake_up_new_task(p);
61
62      /* forking complete and child started to run, tell ptracer */
63      if (unlikely(trace))
64          ptrace_event(trace, nr);
65
66      if (clone_flags & CLONE_VFORK) {
67          if (!wait_for_vfork_done(p, &vfork))
68              ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
69      }
70  } else {
71      nr = PTR_ERR(p);
72  }
73  return nr;
74}
75
76

1
2
1  copy_process函数源码,可以看到copy_process函数返回的是task_struct,真是我们所关心的。
2

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

进程管理的内容不是一篇博文就能说的明白的,尽可能每次从一个小的点入手,以点搏面,娓娓道来。  

给TA打赏
共{{data.count}}人
人已打赏
安全运维

WordPress网站专用docker容器环境带Waf

2020-7-18 20:04:44

安全运维

运维安全-Gitlab管理员权限安全思考

2021-9-19 9:16:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索