进程Linux之间的信令查询

时间:2017-03-01 06:09:52

标签: c linux

嗨,我只是在处理两个进程之间的信号。我有一个继续运行的主进程(例如MAIN)。这个MAIN是从Wrapper进程分叉的(例如WRAP)。

以下是我的代码,它实际上会启动WRAP进程,而后者又会创建一个子进程MAIN

当在MAIN中完成某些初始化时,我想发布一个信号SIGUSR1,该信号将被WRAP捕获并执行其他一些操作。

我的代码的问题是当信号从MAIN引发时,它永远不会被WRAP进程捕获。 PLS。分享您对此代码的建议,或者是否有任何其他方法可以实现此目的。 谢谢。

在MAIN过程中:

在Init完成后,我添加了这段代码,

main()
{
    // Do some work here
    int pid = GetProcessID(); // Returns the process ID of WRAP process
    kill(pid,SIGUSR1);        // Tries to send signal to WRAP process

    // Other code
}

int GetProcessID()
{
    int pid = 0;
    char results[128];
    FILE *fp = popen("pgrep WRAP", "r");
    if(fp == NULL)
    {
        printf("Error: Failed to get Process ID");
    }
    else
    {
        while(fgets(results, 128, fp) != NULL)
        {
            pid = atoi(results);
        }
        pclose(fp);
    }
    return pid;
}

在WRAP过程中:

main()
{ 
    int pid;

    signal(SIGUSR1,InitComplete);

    if ((pid = fork()) < 0) 
    {
        perror("fork");
        exit(1);
    }

    if (pid == 0)
    { 
        /* child */
        system("mainProc.out");
    }
    else 
     {  
        /* parent */
        if(KeepListening() == 1)
            printf("Init completed successfully\n");
    }

    return 0;
}

int KeepListening()
{
    const int MAX_WAIT_TIME = 180;
    int procStarted = 0;
    int res = 0;
    sigset_t origset;
    sigset_t ss;

    sigemptyset(&ss);
    sigaddset(&ss, SIGWINCH);
    sigaddset(&ss, SIGUSR1);
    res = sigprocmask(SIG_BLOCK, &ss, &origset);

    if(res)
    {
        printf("\nError: sigprocmask returned an error\n");
    }

    struct timespec theTimeout;
    theTimeout.tv_nsec = 0;
    theTimeout.tv_sec = MAX_WAIT_TIME;

    int sig = 0;
    siginfo_t theInfo;
    memset(&theInfo, '\0', sizeof(theInfo));

    int timedwaitcount = 0;

    do
    {
        sig = sigtimedwait(&ss, &theInfo, &theTimeout);
        if(sig < 0)
        {
            if(EAGAIN == errno)
            {
                timedwaitcount++;
            }
            else
            {
                PrintMessage("Error:Error occured with sigtimedwait\n");
            }
        }
        else
        {
            timedwaitcount = 0;
        }

        if(SIGUSR1 == sig)
        {
            return 1;
        }
    }while(SIGWINCH == sig || 0 == sig);

    return procStarted;
}

void InitComplete()

   printf("InitComplete in MAIN. Signal Received.\n");
}

1 个答案:

答案 0 :(得分:0)

我准备了一个简短的样本,演示了它应该如何运作。

您称之为WRAPPER的源文件test-exec.c

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

static int sigUsr1Rcvd = 0;

enum { SleepTimeUS = 50000 /* us */ };

void onSigUsr1(int sig)
{
  if (sig == SIGUSR1) sigUsr1Rcvd = 1;
}

int main(int argc, char **argv)
{
  int pid; char buffer[20]; int status = 0;
  /* report alive */
  printf("%s started...\n", argv[0]);
  /* install signal handler before fork() */
  signal(SIGUSR1, &onSigUsr1);
  /* fork child */
  if (pid = fork()) { /* main process */
    if (pid < 0) {
      perror("ERROR in fork()");
      return -1;
    }
  } else { /* child process */
    if (execl("./test-exec-child", "test-exec-child", NULL)) {
      perror("ERROR in execl()");
      return -1;
    }
    return 0;
  }
  /* main process */
  /* waiting for SIGUSR1 */
  while (!sigUsr1Rcvd) usleep(SleepTimeUS);
  printf("%s: Child inited.\n", argv[0]);
  /* wait for termination of child */
  wait(&status);
  /* done */
  printf("%s exiting...\n", argv[0]);
  return 0;
}

您称之为MAIN的源代码文件test-exec-child.c

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

enum { SleepTimeS = 3 /* s */ };

int main(int argc, char **argv)
{
  char buffer[20];
  /* report alive */
  printf("%s started...\n", argv[0]);
  /* consume some time */
  printf("%s: initializing...\n", argv[0]);
  sleep(SleepTimeS);
  printf("%s: done.\n", argv[0]);
  /* send signal to parent */
  kill(getppid(), SIGUSR1);
  /* spend time until user feed-back */
  printf("Press [ENTER] to continue...");
  fgets(buffer, sizeof buffer, stdin);
  /* done */
  printf("%s exiting...\n", argv[0]);
  return 0;
}

我在cygwin上使用gcc编译并测试了这个:

$ gcc -o test-exec test-exec.c

$ gcc -o test-exec-child test-exec-child.c

$ ./test-exec
./test-exec started...
test-exec-child started...
test-exec-child: initializing...

...

test-exec-child: done.
./test-exec: Child inited.
Press [ENTER] to continue...

[ENTER]

test-exec-child exiting...
./test-exec exiting...

$