📄 linux_0
字号:
216 /*
217 * kill_pg() sends a signal to a process group: this is what the tty
218 * control characters do (^C, ^Z etc)
219 */
220 int kill_pg(int pgrp, int sig, int priv)
221 {
222 struct task_struct *p;
223 int err,retval = -ESRCH;
224 int found = 0;
225
226 if (sig<0 || sig>32 || pgrp<=0)
227 return -EINVAL;
228 for_each_task(p) {
229 if (p->pgrp == pgrp) {
230 if ((err = send_sig(sig,p,priv)) != 0)
231 retval = err;
232 else
233 found++;
234 }
235 }
236 return(found ? 0 : retval);
237 }
238
239 /*
240 * kill_sl() sends a signal to the session leader: this is used
241 * to send SIGHUP to the controlling process of a terminal when
242 * the connection is lost.
243 */
244 int kill_sl(int sess, int sig, int priv)
245 {
246 struct task_struct *p;
247 int err,retval = -ESRCH;
248 int found = 0;
249
250 if (sig<0 || sig>32 || sess<=0)
251 return -EINVAL;
252 for_each_task(p) {
253 if (p->session == sess && p->leader) {
254 if ((err = send_sig(sig,p,priv)) != 0)
255 retval = err;
256 else
257 found++;
258 }
259 }
260 return(found ? 0 : retval);
261 }
262
263 int kill_proc(int pid, int sig, int priv)
264 {
265 struct task_struct *p;
266
267 if (sig<0 || sig>32)
268 return -EINVAL;
269 for_each_task(p) {
270 if (p && p->pid == pid)
271 return send_sig(sig,p,priv);
272 }
273 return(-ESRCH);
274 }
275
276 /*
277 * POSIX specifies that kill(-1,sig) is unspecified, but what we have
278 * is probably wrong. Should make it like BSD or SYSV.
279 */
280 asmlinkage int sys_kill(int pid,int sig)
281 {
282 int err, retval = 0, count = 0;
283
284 if (!pid)
285 return(kill_pg(current->pgrp,sig,0));
286 if (pid == -1) {
287 struct task_struct * p;
288 for_each_task(p) {
289 if (p->pid > 1 && p != current) {
290 ++count;
291 if ((err = send_sig(sig,p,0)) != -EPERM)
292 retval = err;
293 }
294 }
295 return(count ? retval : -ESRCH);
296 }
297 if (pid < 0)
298 return(kill_pg(-pid,sig,0));
299 /* Normal kill */
300 return(kill_proc(pid,sig,0));
301 }
302
303 /*
304 * Determine if a process group is "orphaned", according to the POSIX
305 * definition in 2.2.2.52. Orphaned process groups are not to be affected
306 * by terminal-generated stop signals. Newly orphaned process groups are
307 * to receive a SIGHUP and a SIGCONT.
308 *
309 * "I ask you, have you ever known what it is to be an orphan?"
310 */
311 int is_orphaned_pgrp(int pgrp)
312 {
313 struct task_struct *p;
314
315 for_each_task(p) {
316 if ((p->pgrp != pgrp) ||
317 (p->state == TASK_ZOMBIE) ||
318 (p->p_pptr->pid == 1))
319 continue;
320 if ((p->p_pptr->pgrp != pgrp) &&
321 (p->p_pptr->session == p->session))
322 return 0;
323 }
324 return(1); /* (sighing) "Often!" */
325 }
326
327 static int has_stopped_jobs(int pgrp)
328 {
329 struct task_struct * p;
330
331 for_each_task(p) {
332 if (p->pgrp != pgrp)
333 continue;
334 if (p->state == TASK_STOPPED)
335 return(1);
336 }
337 return(0);
338 }
339
340 static void forget_original_parent(struct task_struct * father)
341 {
342 struct task_struct * p;
343
344 for_each_task(p) {
345 if (p->p_opptr == father)
346 if (task[1])
347 p->p_opptr = task[1];
348 else
349 p->p_opptr = task[0];
350 }
351 }
352
353 NORET_TYPE void do_exit(long code)
354 {
355 struct task_struct *p;
356 int i;
357
358 if (intr_count) {
359 printk("Aiee, killing interrupt handler\n");
360 intr_count = 0;
361 }
362 fake_volatile:
363 if (current->semun)
364 sem_exit();
365 if (current->shm)
366 shm_exit();
367 free_page_tables(current);
368 for (i=0 ; i<NR_OPEN ; i++)
369 if (current->filp[i])
370 sys_close(i);
371 forget_original_parent(current);
372 iput(current->pwd);
373 current->pwd = NULL;
374 iput(current->root);
375 current->root = NULL;
376 iput(current->executable);
377 current->executable = NULL;
378 /* Release all of the old mmap stuff. */
379
380 {
381 struct vm_area_struct * mpnt, *mpnt1;
382 mpnt = current->mmap;
383 current->mmap = NULL;
384 while (mpnt) {
385 mpnt1 = mpnt->vm_next;
386 if (mpnt->vm_ops && mpnt->vm_ops->close)
387 mpnt->vm_ops->close(mpnt);
388 kfree(mpnt);
389 mpnt = mpnt1;
390 }
391 }
392
393 if (current->ldt) {
394 vfree(current->ldt);
395 current->ldt = NULL;
396 for (i=1 ; i<NR_TASKS ; i++) {
397 if (task[i] == current) {
398 set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, &default_ldt, 1);
399 load_ldt(i);
400 }
401 }
402 }
403
404 /*
405 * Check to see if any process groups have become orphaned
406 * as a result of our exiting, and if they have any stopped
407 * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
408 *
409 * Case i: Our father is in a different pgrp than we are
410 * and we were the only connection outside, so our pgrp
411 * is about to become orphaned.
412 */
413 if ((current->p_pptr->pgrp != current->pgrp) &&
414 (current->p_pptr->session == current->session) &&
415 is_orphaned_pgrp(current->pgrp) &&
416 has_stopped_jobs(current->pgrp)) {
417 kill_pg(current->pgrp,SIGHUP,1);
418 kill_pg(current->pgrp,SIGCONT,1);
419 }
420 /* Let father know we died */
421 notify_parent(current);
422
423 /*
424 * This loop does two things:
425 *
426 * A. Make init inherit all the child processes
427 * B. Check to see if any process groups have become orphaned
428 * as a result of our exiting, and if they have any stopped
429 * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
430 */
431 while ((p = current->p_cptr) != NULL) {
432 current->p_cptr = p->p_osptr;
433 p->p_ysptr = NULL;
434 p->flags &= ~(PF_PTRACED|PF_TRACESYS);
435 if (task[1] && task[1] != current)
436 p->p_pptr = task[1];
437 else
438 p->p_pptr = task[0];
439 p->p_osptr = p->p_pptr->p_cptr;
440 p->p_osptr->p_ysptr = p;
441 p->p_pptr->p_cptr = p;
442 if (p->state == TASK_ZOMBIE)
443 notify_parent(p);
444 /*
445 * process group orphan check
446 * Case ii: Our child is in a different pgrp
447 * than we are, and it was the only connection
448 * outside, so the child pgrp is now orphaned.
449 */
450 if ((p->pgrp != current->pgrp) &&
451 (p->session == current->session) &&
452 is_orphaned_pgrp(p->pgrp) &&
453 has_stopped_jobs(p->pgrp)) {
454 kill_pg(p->pgrp,SIGHUP,1);
455 kill_pg(p->pgrp,SIGCONT,1);
456 }
457 }
458 if (current->leader)
459 disassociate_ctty(1);
460 if (last_task_used_math == current)
461 last_task_used_math = NULL;
462 current->state = TASK_ZOMBIE;
463 current->exit_code = code;
464 current->rss = 0;
465 #ifdef DEBUG_PROC_TREE
466 audit_ptree();
467 #endif
468 schedule();
469 /*
470 * In order to get rid of the "volatile function does return" message
471 * I did this little loop that confuses gcc to think do_exit really
472 * is volatile. In fact it's schedule() that is volatile in some
473 * circumstances: when current->state = ZOMBIE, schedule() never
474 * returns.
475 *
476 * In fact the natural way to do all this is to have the label and the
477 * goto right after each other, but I put the fake_volatile label at
478 * the start of the function just in case something /really/ bad
479 * happens, and the schedule returns. This way we can try again. I'm
480 * not paranoid: it's just that everybody is out to get me.
481 */
482 goto fake_volatile;
483 }
484
485 asmlinkage int sys_exit(int error_code)
486 {
487 do_exit((error_code&0xff)<<8);
488 }
489
490 asmlinkage int sys_wait4(pid_t pid,unsigned long * stat_addr, int options, struct rusage * ru)
491 {
492 int flag, retval;
493 struct wait_queue wait = { current, NULL };
494 struct task_struct *p;
495
496 if (stat_addr) {
497 flag = verify_area(VERIFY_WRITE, stat_addr, 4);
498 if (flag)
499 return flag;
500 }
501 add_wait_queue(¤t->wait_chldexit,&wait);
502 repeat:
503 flag=0;
504 for (p = current->p_cptr ; p ; p = p->p_osptr) {
505 if (pid>0) {
506 if (p->pid != pid)
507 continue;
508 } else if (!pid) {
509 if (p->pgrp != current->pgrp)
510 continue;
511 } else if (pid != -1) {
512 if (p->pgrp != -pid)
513 continue;
514 }
515 /* wait for cloned processes iff the __WCLONE flag is set */
516 if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
517 continue;
518 flag = 1;
519 switch (p->state) {
520 case TASK_STOPPED:
521 if (!p->exit_code)
522 continue;
523 if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
524 continue;
525 if (stat_addr)
526 put_fs_long((p->exit_code << 8) | 0x7f,
527 stat_addr);
528 p->exit_code = 0;
529 if (ru != NULL)
530 getrusage(p, RUSAGE_BOTH, ru);
531 retval = p->pid;
532 goto end_wait4;
533 case TASK_ZOMBIE:
534 current->cutime += p->utime + p->cutime;
535 current->cstime += p->stime + p->cstime;
536 current->cmin_flt += p->min_flt + p->cmin_flt;
537 current->cmaj_flt += p->maj_flt + p->cmaj_flt;
538 if (ru != NULL)
539 getrusage(p, RUSAGE_BOTH, ru);
540 flag = p->pid;
541 if (stat_addr)
542 put_fs_long(p->exit_code, stat_addr);
543 if (p->p_opptr != p->p_pptr) {
544 REMOVE_LINKS(p);
545 p->p_pptr = p->p_opptr;
546 SET_LINKS(p);
547 notify_parent(p);
548 } else
549 release(p);
550 #ifdef DEBUG_PROC_TREE
551 audit_ptree();
552 #endif
553 retval = flag;
554 goto end_wait4;
555 default:
556 continue;
557 }
558 }
559 if (flag) {
560 retval = 0;
561 if (options & WNOHANG)
562 goto end_wait4;
563 current->state=TASK_INTERRUPTIBLE;
564 schedule();
565 current->signal &= ~(1<<(SIGCHLD-1));
566 retval = -ERESTARTSYS;
567 if (current->signal & ~current->blocked)
568 goto end_wait4;
569 goto repeat;
570 }
571 retval = -ECHILD;
572 end_wait4:
573 remove_wait_queue(¤t->wait_chldexit,&wait);
574 return retval;
575 }
576
577 /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -