与多进程系统中的sigwait相关的混淆

时间:2012-09-17 01:34:50

标签: multithreading multiprocessing

我很难理解多进程系统中的IPC。我有这个系统,其中有三个子进程向其进程组发送两种类型的信号。有四种类型的信号处理过程负责特定类型的信号。

这个监控过程会等待两个信号,然后相应地进行处理。当我运行该程序一段时间后,监控过程似乎不会接收信号以及信号处理过程。我可以在日志中看到信号只是生成但根本没有处理。

我的代码如下:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

using namespace std;

double timestamp() {
  struct timeval tp;
  gettimeofday(&tp, NULL);
  return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}

double getinterval() { 
  srand(time(NULL));
  int r = rand()%10 + 1;
  double s = (double)r/100;
}

int count;
int count_1;
int count_2;
double time_1[10];
double time_2[10];


pid_t senders[1];
pid_t handlers[4];
pid_t reporter;

void catcher(int sig) {
  printf("Signal catcher called for %d",sig);
}

int main(int argc, char *argv[]) {

  void signal_catcher_int(int);

  pid_t pid,w;
  int status;

  if(signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
    perror("1");
    return 1;
  }

  if(signal(SIGUSR2 ,SIG_IGN) == SIG_ERR) {
    perror("2");
    return 2;
  }

  if(signal(SIGINT,signal_catcher_int) == SIG_ERR) {
    perror("3");
    return 2;
  }

  //Registering the signal handler
  for(int i=0; i<4; i++) {
    if((pid = fork()) == 0) {
      cout << i << endl;
      //struct sigaction sigact;
      sigset_t sigset;
      int sig;
      int result = 0;

      sigemptyset(&sigset);

      if(i%2 == 0) {

        if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
          perror("2");
          return 2;
        }

        sigaddset(&sigset, SIGUSR1);
        sigprocmask(SIG_BLOCK, &sigset, NULL);
      } else {
            if(signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
          perror("2");
          return 2;
        }

        sigaddset(&sigset, SIGUSR2);
        sigprocmask(SIG_BLOCK, &sigset, NULL);
      }

      while(true) {
        int result = sigwait(&sigset, &sig);
        if(result == 0) {
          cout << "The caught signal is " << sig << endl;
        }
      }
      exit(0);

    } else {
      cout << "Registerd the handler " << pid << endl;
      handlers[i] = pid;
    }
  }

  //Registering the monitoring process
  if((pid = fork()) == 0) {
    sigset_t sigset;
    int sig;
    int result = 0;

    sigemptyset(&sigset);
    sigaddset(&sigset, SIGUSR1);
    sigaddset(&sigset, SIGUSR2);

    sigprocmask(SIG_BLOCK, &sigset, NULL);

    while(true) {
      int result = sigwait(&sigset, &sig);
      if(result == 0) {
        cout << "The monitored signal is " << sig << endl;
      } else {
        cout << "error" << endl;
      } 
    }

  } else {
    reporter = pid;
  }


  sleep(3);
  //Registering the signal generator
  for(int i=0; i<1; i++) {
    if((pid = fork()) == 0) {

      if(signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
        perror("1");
        return 1;
      }

      if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
        perror("2");
        return 2;
      }
      srand(time(0));
      while(true) {
        volatile int signal_id = rand()%2 + 1;
        cout << "Generating the signal " << signal_id << endl;
        if(signal_id == 1) {
          killpg(getpgid(getpid()), SIGUSR1);
        } else {
              killpg(getpgid(getpid()), SIGUSR2);
        }     
        int r = rand()%10 + 1;
        double s = (double)r/100;  
        sleep(s);
      }

      exit(0); 
    } else {
      cout << "Registered the sender " << pid << endl;
      senders[i] = pid;

    } 

  }


  while(w = wait(&status)) {
    cout << "Wait on PID " << w << endl;
  }

}



void signal_catcher_int(int the_sig) {
  //cout << "Handling the Ctrl C signal " << endl;
  for(int i=0; i<1; i++) {
    kill(senders[i],SIGKILL);
  }

  for(int i=0; i<4; i++) {
    kill(handlers[i],SIGKILL);
  }

  kill(reporter,SIGKILL);

  exit(3);
}

有什么建议吗?

以下是输出的示例

一开始

Registerd the handler 9544
Registerd the handler 9545
1
Registerd the handler 9546
Registerd the handler 9547
2
3
0
Registered the sender 9550
Generating the signal 1
The caught signal is 10
The monitored signal is 10
The caught signal is 10
Generating the signal 1
The caught signal is 10
The monitored signal is 10
The caught signal is 10
Generating the signal 1
The caught signal is 10
The monitored signal is 10
The caught signal is 10
Generating the signal 1
The caught signal is 10
The monitored signal is 10
The caught signal is 10
Generating the signal 2
The caught signal is 12
The caught signal is 12
The monitored signal is 12
Generating the signal 2
Generating the signal 2
The caught signal is 12
The caught signal is 12
Generating the signal 1
The caught signal is 12
The monitored signal is 10
The monitored signal is 12
Generating the signal 1
Generating the signal 2
The caught signal is 12
Generating the signal 1
Generating the signal 2
10
The monitored signal is 10
The caught signal is 12
Generating the signal 1
The caught signal is 12
The monitored signal is GenThe caught signal is TheThe caught signal is 10
Generating the signal 2

稍后

The monitored signal is GenThe monitored signal is 10
Generating the signal 1
Generating the signal 2
The caught signal is 10
The caught signal is 10
The caught signal is 10
The caught signal is 12
Generating the signal 1
Generating the signal 2
Generating the signal 1
Generating the signal 1
Generating the signal 2
Generating the signal 2
Generating the signal 2
Generating the signal 2
Generating the signal 2
Generating the signal 1
The caught signal is 12
The caught signal is 10
The caught signal is 10
Generating the signal 2
Generating the signal 1
Generating the signal 1
Generating the signal 2
Generating the signal 1
Generating the signal 2
Generating the signal 2
Generating the signal 2
Generating the signal 1
Generating the signal 2
Generating the signal 1
Generating the signal 2
Generating the signal 2
The caught signal is 10
Generating the signal 2
Generating the signal 1
Generating the signal 1

正如您最初所看到的,信号是由我的信号处理程序和监控过程生成和处理的。但后来信号产生了很多,但它并不像以前那么大。此外,我可以通过监控过程看到非常少的信号处理

任何人都可以提供一些见解。发生了什么事?

1 个答案:

答案 0 :(得分:1)

如果同一类型的多个信号处于待处理状态,则默认情况下Linux仅提供一个此类信号。这与sigwait documentation

一致
  

如果在调用sigwait()之前有多个挂起的实例   对于单个信号编号,它是依赖于实现的   成功返回有任何剩余的未决信号   信号编号。

因此,程序的输出取决于调度程序,如果多次调用kill并且调度程序不会同时唤醒监视进程,则相同类型的信号将折叠为一个。

Linux允许change默认行为。