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