等待来自父母的信号并再次完成工作和阻塞

Posted

技术标签:

【中文标题】等待来自父母的信号并再次完成工作和阻塞【英文标题】:Wait for signal from parent and does job and blocks again 【发布时间】:2019-12-03 06:25:37 【问题描述】:

编写一个可以显示文本字符串(仅由 26 个字母和空格组成)的程序。该程序应该分叉 27 个工作进程。每个工作进程运行一个无限循环,在该循环中它等待来自控制器(即父级)的信号,休眠 1 秒,打印其预定义字符,向控制器发出信号,然后再次阻塞。控制器从键盘读取一个字符串,然后以正确的顺序向工作人员发出信号以显示该字符串 以下是我的代码,但我没有得到输出,它没有打印任何东西。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <string.h>
int
main()

  /*...declarations and stuff....*/
  scanf("%s",inputString);
  length=strlen(inputString);
  for (i=0;i<27;i++)
  
    pid[i]=fork();
    if (pid[i]==0)
     
       /*...Declare my character...*/
       while (1)
       
          pause();
          sleep(1);
          printf("%c",myChar);
          kill(ppid,SIGCONT);
       
       return 0;
     
  
  for (i=0;i<length;i++)
  
    int temp=inputString[i];
    if (temp==32)
    
      kill(pid[0],SIGCONT);
    
    else
    
      kill(pid[temp-96],SIGCONT);
    
    pause();
  
  for(i=0;i<27;i++)
    kill(pid[i],SIGTERM);
  return 0;

【问题讨论】:

for(i=0;i 【参考方案1】:

    首先不要使用SIGCONT 或其他类似的信号来自定义使用。更喜欢使用SIGUSR1SIGUSR2SIGCONT 有一些特殊的语义。

    现在即使您将CONT 更改为USR1,您使用pause() 的方式也是一个问题。子进程被唤醒后,它会因为你没有捕捉到信号而被杀死。手册说:

pause() 导致调用进程(或线程)休眠,直到 发出的信号要么终止进程,要么导致 调用信号捕获函数。

    由于您没有将 ppid 设置为正确的值,因此孩子永远不会发出正确的信号。

    您将永远无法正确体验打印,因为写入被缓冲并且没有刷新。使用printf("%c",myChar); fflush(stdout);printf("%c\n",myChar);

这将导致类似:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>  
#include <sys/types.h>
#include <string.h>

void handler(int sig) 


int main() 
  pid_t ppid;
  int length;
  char inputString[256];
  pid_t pid[256];
  int i;
  char myChar;
  scanf("%s",inputString);
  length=strlen(inputString);
  struct sigaction action;
  sigemptyset(&(action.sa_mask));
  action.sa_flags = 0;
  action.sa_handler = handler;
  sigaction(SIGUSR1,&action,NULL);
  ppid = getpid();
  for (i=0;i<27;i++) 
    pid[i]=fork();
    if (pid[i]==0) 
       myChar='a'+i;
       while (1) 
          pause();
          sleep(1);
          printf("%c\n",myChar);
          kill(ppid,SIGUSR1);
       
       return 0;
     
  
  for (i=0;i<length;i++) 
    int temp=inputString[i];
    if (temp==32) 
      kill(pid[0],SIGUSR1);
    
    else 
      kill(pid[temp-'a'],SIGUSR1);
    
    pause();
  
  for(i=0;i<27;i++)
    kill(pid[i],SIGTERM);
  return 0;

    没什么好说的,比如为什么要循环超过 27 个? 等等,但这些实际上都是小问题(这并不是说以后不纠正)。

【讨论】:

在我看来,您应该使用sigsuspendsigwait 来避免race condition with pause

以上是关于等待来自父母的信号并再次完成工作和阻塞的主要内容,如果未能解决你的问题,请参考以下文章

进程的阻塞和挂起的区别

进程的阻塞和挂起的区别

生成一个后台进程并阻塞等待它完成

异步/同步/阻塞/非阻塞

等待QThread时UI会阻塞/如何正确使用QThread

使用 c 安排警报