⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux_0

📁 Linux 内核源代码(V!1.0.9)
💻
📖 第 1 页 / 共 5 页
字号:
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(&current->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(&current->wait_chldexit,&wait);
574         return retval;
575 }
576 
577 /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -