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),
//也就是等待到了子进程的结束
{
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),
//也就是等待到了子进程的结束