使用信号signal,实现进程之间的同步

来源:互联网 发布:snmp端口号是多少 编辑:程序博客网 时间:2024/06/06 10:38

 

下面是具体的代码,其中四个函数是重点。

TELL_WAIT, WAIT_PARTEN, TELL_PARTEN, WAIT_CHILD, TELL_CHILD。

TELL_WAIT是用来初始化信号掩码的。至于为什么要block SIGUSR1 和 SIGUSR2我还不清楚。

其余四个就是两对,用来等待和告知。

关键的是两个

1.用了一个static volatile sig_atomic_t sigflag 变量来做flag。

2. 用sigsuspend来等待信号的到来。

 

在调试的过程中发现,因为文件写的时候会有延时,所以要每次写完后fclose该文件。

 

/*
 * =====================================================================================
 *
 *       Filename:  parent_child.c
 *
 *    Description: 
 *
 *        Version:  1.0
 *        Created:  08/12/2010 10:47:11 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *        Company: 
 *
 * =====================================================================================
 */

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

static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;

static void
sig_usr(int signo)   /* one signal handler for SIGUSR1 and SIGUSR2 */
{
    sigflag = 1;
}

void
TELL_WAIT(void)
{
    if (signal(SIGUSR1, sig_usr) == SIG_ERR)
        perror("signal(SIGUSR1) error");
    if (signal(SIGUSR2, sig_usr) == SIG_ERR)
        perror("signal(SIGUSR2) error");
    sigemptyset(&zeromask);
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGUSR1);
    sigaddset(&newmask, SIGUSR2);

    /*
     * Block SIGUSR1 and SIGUSR2, and save current signal mask.
     */
    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        perror("SIG_BLOCK error");
}

void
TELL_PARENT(pid_t pid)
{
    kill(pid, SIGUSR2);              /* tell parent we're done */
}

void
WAIT_PARENT(void)
{
    while (sigflag == 0)
        sigsuspend(&zeromask);   /* and wait for parent */
    sigflag = 0;

    /*
     * Reset signal mask to original value.
     */
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        perror("SIG_SETMASK error");
}

void
TELL_CHILD(pid_t pid)
{
    kill(pid, SIGUSR1);             /* tell child we're done */
}

void
WAIT_CHILD(void)
{
    while (sigflag == 0)
        sigsuspend(&zeromask);  /* and wait for child */
    sigflag = 0;

    /*
     * Reset signal mask to original value.
     */
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        perror("SIG_SETMASK error");
}

int main()
{
    FILE * pFile;
    char   buffer[10] = {0};
    pid_t  pid;
    int    i;
    int    d;
    pFile = fopen("interaction","wb+");

    fwrite("2", 1, 1, pFile);
    fclose(pFile);

    TELL_WAIT();
    pid = fork();
    if (pid < 0)
    {
        perror("fork error");
        return 0;
    }
    else if(pid == 0)
    {
        for (i=0;i<10;i++)
        {
            pFile = fopen("interaction","rb+");
            fread(buffer, 1, sizeof(buffer), pFile);
            printf("chile get: %s/n", buffer);
            sscanf(buffer, "%d", &d);
            rewind(pFile);
            sprintf(buffer, "%d", d+1);
            fwrite(buffer, 1, sizeof(buffer), pFile);
            fclose(pFile);
            printf("child put: %s/n", buffer);
            TELL_PARENT(getppid());
            WAIT_PARENT();
        }
    }
    else if (pid > 0)
    {
        for (i=0;i<10;i++)
        {
            WAIT_CHILD();
            pFile = fopen("interaction","rb+");
            fread(buffer, 1, sizeof(buffer), pFile);
            printf("father get: %s/n", buffer);
            sscanf(buffer, "%d", &d);
            rewind(pFile);
            sprintf(buffer, "%d", d+1);
            fwrite(buffer, 1, sizeof(buffer), pFile);
            fclose(pFile);
            printf("father put: %s/n", buffer);
            TELL_CHILD(pid);
        }
    }
    return 0;
}

原创粉丝点击