【问题标题】:getpid(), WIFSHSTOPPED(state) to check child process sleepinggetpid(), WIFSHSTOPPED(state) 检查子进程睡眠
【发布时间】:2017-11-15 12:24:15
【问题描述】:

您好,我正在使用 3 个进程 P0、P1、P2 制作程序 我想做一个像下面这样的循环

init: P0 P1,P2 paused, signal to P0
P0 : wake up by signal -> finish job -> signal to P3 -> pause
P1 : wake up by signal -> finish job -> signal to P2 -> pause
P2 : wake up by signal -> finish job -> signal to P3 -> pause
repeat 0~2

不幸的是,SOMETIMES 信号在目标进程睡眠之前出现

所以我想检查目标进程是否暂停。 我像这样插入[检查代码]

//end job here here
//
int status = 0;
do {
    waitpid(target_pid, &status, WNOHANG); // WNOHANG : check child status without waiting
} while ( ! WIFSTOPPED(status));           // linux man said that WIFSTOPPED
                                           // return true if process stopped
//signal to target_pid and pause() here

但它不起作用。

如果我使用

 while( ! WIFSTOPPED(status))

程序 100% 不能跳出循环。

如果我使用

 while(   WIFSTOPPED(status))

它的工作方式与我输入[检查代码]之前相同

我知道waitpid函数是用来检查进程结束的。

但不能 waitpid() 仅用于检查是否已暂停?

【问题讨论】:

  • 这个作业的第三个实例:(
  • 这不是它的工作原理。我推荐你read the waitpid manual page 并检查它返回
  • 你的意思是 WIFSTOPPED() 的“检查停止”和我说的不一样?
  • 您认为停止进程意味着什么?您不完整的程序片段并没有给我们太多线索,但您应该知道pause()sleep() 都与它无关。 “已停止”的意思是“暂停”。
  • waitpid()(当不与ptraced 进程一起使用时)需要WUNTRACED 才能接收WIFSTOPPED 通知。

标签: c linux fork waitpid


【解决方案1】:

如果child完成normally(延迟过去后)那么你可以使用WIFEXITED(status),如果孩子已经正常退出就可以了。

如果孩子得到killed(使用来自其他终端的kill命令)或被来自其他进程或同一进程的任何信号暂停,那么您可以使用WIFSIGNALED(status)

根据您的要求,我将您的代码修改为

int main()
{

        if(fork()==0) // p1
        {
                int t;
                srand(getpid());
                t = rand()%10 +1;//generating delay b/w 1 to 10 seconds
                printf("child1 delay : [%d] pid : [%d] ppid : [%d] \n",t,getpid(),getppid());
                sleep(t);
                printf("child1 pid : [%d] and its ppid : [%d] exiting \n",getpid(),getppid());
                exit(0);
        }
        else
        {
                if(fork()==0) // p2
                {
                        int t;
                        srand(getpid());
                        t = rand()%10 +1;//generating delay b/w 1 to 10 seconds
                        printf("child2 delay : [%d] pid : [%d] ppid : [%d] \n",t,getpid(),getppid());
                        sleep(t);
                        printf("child2 pid : [%d] and its ppid : [%d] exiting \n",getpid(),getppid());
                        exit(1);
                }
                else // p3
                {
                        int status;
                        printf("In parent...[%d]\n",getpid());
                        int ret;
                        while((ret = waitpid(-1,&status,0))!=-1)//when there is no child left it returns -1
                        {
                                if(WIFEXITED(&status))//if child is completed normally after sleep is over
                                {
                                        printf("child [%d] terminates normally : %d\n",ret,WEXITSTATUS(status));
                                }
                                if(WIFSIGNALED(&status))//true if child was killed by any signal from other process or same process
                                {
                                        printf("child [%d] terminates normally : %d\n",ret,WTERMSIG(status));//it will print the signal no by which it was killed
                                }
                        }
                }
        }
        return 0;
}

没有必要pause(),因为你应该使用pause(),当一个进程应该阻塞直到它没有收到来自其他进程的信号。

请浏览waitpid() 的手册页。

【讨论】:

  • 感谢您的帮助。现在我意识到我使用了错误的功能。 waitpid 用于检测更关键的问题,而不是 pause()
  • 我应该使用其他方法,例如 proc/pid/status
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多