使用信号

时间:2016-04-10 15:58:29

标签: c linux process signals

我正在学习如何在linux中使用信号。有4个子进程和一个父进程。我的输出应该在这些阶段进行:

家长收到来自孩子1的信号

家长收到来自孩子2的信号

家长收到来自孩子3的信号

家长收到来自孩子4的信号

初始结束

第1阶段开始

儿童1收到来自父母的信号

儿童2收到来自父母的信号

儿童3收到来自父母的信号

儿童4接收来自父母的信号

家长收到来自孩子1的信号

家长收到来自孩子2的信号

家长收到来自孩子3的信号

家长收到来自孩子4的信号

阶段1结束

第2阶段开始

儿童1收到来自父母的信号

儿童2收到来自父母的信号

儿童3收到来自父母的信号

儿童4接收来自父母的信号

我目前正试图在第一阶段结束之前做这个部分而且我正在努力。这是我的代码:

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXCP 3
int ccount=0;
void p_action(int sig){
   if (sig == SIGUSR2){
      printf("\ncontroller(%d): Received signal SIGUSR2 from child   process\n", 
            (int)getpid());
    }
    --ccount;
 }

 void c_action(int sig){
    if (sig == SIGUSR1){
      printf("\ncompute(%d): Received signal SIGUSR1 from parent process %d\n", 
            (int)getpid(), (int)getppid());
    }
    exit(0);
 }

int main(){

pid_t pid[MAXCP], parent_pid;
//int nprocs = 0;
ccount = MAXCP;

static struct sigaction pact, cact[MAXCP];

pact.sa_handler = p_action;
sigaction(SIGUSR2, &pact, NULL);


int count;
for (count = 0; count < MAXCP; count++){
    switch(pid[count] = fork()){
        case -1:
            perror("Fork error");
            exit(1);
        case 0:
            //sleep(1);
            cact[count].sa_handler = c_action;
            sigaction(SIGUSR1, &cact[count], NULL);
            printf("Sending SIGUSR2 to parent");
            kill(getppid(), SIGUSR2);
            pause();
            break;
        default:
            pause();
            //printf("Parent is sleeping");

            while (ccount != MAXCP){
                sleep(60);
            }
            for (ccount = 0; ccount < MAXCP; ccount++)
                kill(pid[count], SIGUSR1);
            break;

    }   
}


return 0;
}

我的输出是这样的:

// When I use the above code
controller(3132): Received signal SIGUSR2 from child process
// When I comment out the pause in the child section
controller(3140): Received signal SIGUSR2 from child process
Sending SIGUSR2 to parent
controller(3141): Received signal SIGUSR2 from child process
Sending SIGUSR2 to parentSending SIGUSR2 to parentSending SIGUSR2 to     parentSending SIGUSR2 to parentSending SIGUSR2 to parent
controller(3142): Received signal SIGUSR2 from child process
^C

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

您想要使用信号的内容与其设计目标不完全匹配。最重要的问题是信号充当硬件中断控制器。如果同一值的多个信号同时发生&#34;同时#34;它们将看起来合并为接收器中的一个信号。在下面的示例中,我们通过在每个孩子中使用具有不同值的睡眠来解决这个问题。

因此,当内核重新安排进程时,它只检查自上次进程激活后是否已收到每个信号,并在需要时将它们转发到进程中。它不知道发生了多少次。

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXCP 3
volatile int ccount=0;
void p_action(int sig, siginfo_t *info, void *ptr){
   if (sig == SIGUSR2){
      printf("\ncontroller(%d): Received signal SIGUSR2 from child %d process\n",
            (int)getpid(), (int)info->si_pid);
    }
    --ccount;
 }

 void c_action(int sig){
    if (sig == SIGUSR1){
      printf("\ncompute(%d): Received signal SIGUSR1 from parent process %d\n",
            (int)getpid(), (int)getppid());
    }
 }

int main(){
    int count;
    pid_t pid[MAXCP];
    ccount = MAXCP;

    struct sigaction pact;

    pact.sa_flags = SA_SIGINFO | SA_RESTART; /* if signal comes on top of each other, we need this */
    pact.sa_sigaction = p_action;
    sigaction(SIGUSR2, &pact, NULL);

    /* spawdn children */
    for (count = 0; count < MAXCP; count++){
        switch(pid[count] = fork()){
            case -1:
                perror("Fork error");
                exit(1);
            case 0:
                {
                    struct sigaction cact;
                    cact.sa_flags = 0;
                    cact.sa_handler = c_action;
                    sigaction(SIGUSR1, &cact, NULL);
                    pause();
                    sleep(1);
                    printf("Sending SIGUSR2 to parent (%d)\n", getppid());
                    sleep(count+1);
                    kill(getppid(), SIGUSR2);
                    exit(0);
                    break;
                }
            default:
                break;
        }
    }

    sleep (1); /* let children have time to configure sigaction() */

    /* notify all children */
    for (count = 0; count < MAXCP; count++){
        printf ("Sending SIGUSR1 to child %d\n", (int)pid[count]);
        kill(pid[count], SIGUSR1);
    }

    /* wait for children to notify back */
    while (ccount)
    {
         usleep(10000); /* else CPU throttles */
    }

    for (count = 0; count < MAXCP; count++){
        int status;
        waitpid (pid[count], &status, 0);
        printf ("Child process %d reaped. status=%d\n", pid[count], status);
        kill(pid[count], SIGUSR1);
    }

    return 0;
}

图像内核每个进程都有一个记录,它记录了睡眠时收到的信号。

struct Process
{
   bool hasReceivedSIGINT;
   bool hasReceivedSIGUSR1;
   bool hasReceivedSIGUSR2;
   bool hasReceivedSIGUSR3;
};

信号用于&#34;轻推&#34;其他过程。一个很好的例子是创建一个进程重新加载配置文件。对于IPC通信,pipe()是一种更好的方法。

相关问题