在C中修改信号处理程序中的值时出现混淆

时间:2015-12-17 11:53:20

标签: c multiprocessing signals

我正在尝试测试进程捕获信号的速度有多快,所以我编写了一个简单的C代码。

在我的代码中,我分叉N个进程,每个子进程注册一个处理程序,由SIGUSR1触发并等待信号SIGUSR2。捕获SIGUSR1和SIGUSR2之间的等待时间是我想要的。我试图记录将SIGUSR2首先捕获到共享内存或全局随机变量的那一刻。

我遇到的问题是我无法修改全局变量或共享内存的值。 另一件事也让我感到困惑,我还在主进程中设置了一个计时器,它还使用SIGVTALRM来触发处理程序并修改全局变量。但它确实有效。

这是我的代码,感谢您的帮助!

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

#define N 3
#define SHMSIZE 20 

int count = 0;
int record[N];
char* shm;
int test = 0;

void timer_handler(int signum)
{
    ++count;
}

void handler2 (int signum)
{
    printf("%d ends, use %d usecs.\n", getpid(), count);
    *shm = count;
    test+=1;
}

void handler (int signum)
{
    signal(SIGUSR2, handler2); 
    printf("%d begin \n", getpid());
    kill(getpid(),SIGUSR2);
}

void child(int process_index)
{
    struct sigaction sa;

    /* Register */
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sigaction(SIGUSR1, &sa, NULL);

    printf("I am %d.\n", getpid());
    sleep(3);

    exit(0);
}

int main()
{
    int i, k, status, shmid;
    pid_t pid[N];
    pid_t pid_wait;
    struct sigaction sa_main;
    struct itimerval timer;
    key_t key = 123;
    char* shm;

    /* Create shared memory */
    if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0)
            {perror("shmget"); exit(1);}

    /* attach shm */
    if ((shm = shmat(shmid, NULL, 0)) == (char*)-1)
    {
        perror("shmat");
        exit(1);
    }

    /* Init Shm Value */
    *shm = '0';

    /* Register */
    memset(&sa_main, 0, sizeof(sa_main));
    sa_main.sa_handler = timer_handler;
    sigaction(SIGVTALRM, &sa_main, NULL);
    signal(SIGUSR1, SIG_IGN);

    /* Config timer */
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 1;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 1;

    /* Start a virtual timer */
    setitimer( ITIMER_VIRTUAL, &timer, NULL);

    printf(" Main pid is:%d\n", getpid());
    /* Do k times */
    for (k=0;k<3;k++) 
    {

        for (i=0;i<N;i++)
        {
            pid[i] = fork();
            if (pid[i]==0)
            {
                child(i);
            }
        }

        sleep(2);
         kill(0, SIGUSR1);

        for (i=0;i<N;i++)
        {
            do
            {
                pid_wait = waitpid(pid[i], &status, WNOHANG);
                printf("I am waiting..\n");
                sleep(1);
            }while(pid_wait != pid[i]);
        }

        printf("the record is: %d\n", *shm);
        printf("test is:%d\n", test);
    }
    printf("all done\n");

    /* Detach shared memory */
    shmdt(shm);

    /* destroy shared memory */
    printf("shared memory destroyed!\n");
    int retval = shmctl(shmid, IPC_RMID, NULL);
    if (retval <0)
    {
        fprintf(stderr, "remove shared memory fail..\n");
        exit(1);
    }

    return 0;
}

1 个答案:

答案 0 :(得分:0)

我注意到,如果不将共享内存作为参数传递,我就无法修改值。所以,我的解决方案是将修改后的全局值从处理程序传递给子进程,并修改共享内存。

感谢您的帮助!