int sys_waitpid(pid_t pid,unsigned long * stat_add

1556阅读 2评论2009-08-04 jhluroom
分类:LINUX

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 语名???

上一篇:exit.c
下一篇:fork.c

文章评论