int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)//挂起当前进程,直到pid指定的子进程退出终止或者收到要求终止该进程 的信号 ,或者需要调用 一个信号处理函数
{ int flag, code; struct task_struct ** p;
verify_area(stat_addr,4);//验证区域大小是否可用
repeat: flag=0; for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { if (!*p || *p == current)//空项,本进程项跳过
continue; if ((*p)->father != current->pid)//不是当前进程的子进程跳过,
continue; //以下的语名定为当前进程 的子进程
if (pid>0) {//pid>0,等待指定的进程pid
if ((*p)->pid != pid)//不是当前要找的子进程,跳过
continue; } else if (!pid) {//pid==0 等待进程组号等于当前进程组号的任何子进程
if ((*p)->pgrp != current->pgrp)//扫描 的进程组号与当前的进程组号不相等,跳过
continue; } else if (pid != -1) {// pid<-1等待指定进程pid 绝对值的进程
if ((*p)->pgrp != -pid)//不是当前要找的子进程,跳过
continue; } //以下的语名定为要找到的进程
switch ((*p)->state) { case TASK_STOPPED://子进程非正常结束
if (!(options & WUNTRACED))//参数 option 可以为 0 或WNOHANG(如果没有任何已经结束的子进程则马上返回, 不予以等待)或 WUNTRACED (如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会),如果WUNTRACED没有置位,无需产即返回,可继续扫描其他进程
continue; put_fs_long(0x7f,stat_addr);//如果WUNTRACED置位,则写入状态信息,返回此子进程 号
return (*p)->pid; case TASK_ZOMBIE://子进程非正常结束
current->cutime += (*p)->utime;//用户态运行时间累计到当前进程(父进程中)
current->cstime += (*p)->stime;//系统态运行时间累计到当前进程(父进程中)
flag = (*p)->pid; //取子进程号
code = (*p)->exit_code;//取子进程的退出码
release(*p);//释放该子进程
put_fs_long(code,stat_addr);//置状态信息为退出码值
return flag; default://找到一个符合要求的子进程,它处于运行态或睡眠态,flag=1
flag=1; continue;//这个地方是否可以换成break 语名???
} } if (flag) { if (options & WNOHANG)//如果options==WNOHANG(如果没有任何已经结束的子进程则马上返回, 不予以等待)时,则立即返回
return 0; current->state=TASK_INTERRUPTIBLE;//置当前进程为可中断等待状态
schedule();//重新进程调度,重新调度后,当又轮到本程序进行时,则从下面的语句开始进行
if (!(current->signal &= ~(1<<(SIGCHLD-1))))//如果本程序还没有收到子进程发过来的SIGCHLD信号,则重新开始查找
goto repeat; else return -EINTR; } return -ECHILD; } //说明:LINE 190行的重新任务调度,是很有必要的,这样一任务调度,父进程就
//有可能暂时不运行,转让于子进程加以运行,这样就有可能子进程运行结束,
//当轮到父进程运行时,正好执行if (!(current->signal &= ~(1<<(SIGCHLD-1))))语句,
//也就是说能够收到子进程传过来的SIGCHLD信号,从而返回-EINTR(4),
//也就是等待到了子进程的结束
|
default://找到一个符合要求的子进程,它处于运行态或睡眠态,flag=1
flag=1;
continue;//这个地方是否可以换成break 语名???