APUE exercises 10.6 pp 381

来源:互联网 发布:叶罗丽娃娃淘宝 编辑:程序博客网 时间:2024/05/01 01:47

10.6 Write the following program to test the parent–child synchronization functions in Figure 10.24. The process creates a file and writes the integer 0 to the file. The process then calls fork, and the parent and child alternate incrementing the counter in the file. Each time the counter is incremented, print which process (parent or child) is doing the increment.

#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/wait.h>#include "apue.h"#include <errno.h>#include <signal.h>#include <assert.h>#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */static sigset_t newmask, oldmask, zeromask;static voidsig_usr(int signo)  /* one signal handler for SIGUSR1 and SIGUSR2 */{    sigflag = 1; }voidINIT(void){    if (signal(SIGUSR1, sig_usr) == SIG_ERR)        err_sys("signal(SIGUSR1) error");    if (signal(SIGUSR2, sig_usr) == SIG_ERR)        err_sys("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)        err_sys("SIG_BLOCK error");}voidTELL_PARENT(pid_t pid){    kill(pid, SIGUSR2);}voidWAIT_PARENT(void){/* tell parent we’re done */    while (sigflag == 0)        sigsuspend(&zeromask);  /* and wait for parent */    sigflag = 0;/* Reset signal mask to original value */    // if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)    //  err_sys("SIG_SETMASK error");}voidTELL_CHILD(pid_t pid){    kill(pid, SIGUSR1);}voidWAIT_CHILD(void)/* tell child we’re done */{    while (sigflag == 0)        sigsuspend(&zeromask);  /* and wait for child */    sigflag = 0;    /* Reset signal mask to original value */    // if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)    //  err_sys("SIG_SETMASK error");}void END(void){    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        err_sys("SIG_SETMASK error");}int counter;int buf[1];int main(int argc, char const *argv[]){    int pid;    counter = 0;    INIT();    printf("INIT: counter: %d pid: %d\n", counter,getpid());    umask(0);    creat("./tmp.txt", RWRWRW);    int fd = open("./tmp.txt", O_CREAT|O_RDWR, RWRWRW);    write(fd, &counter, 4);    if ((pid = fork()) < 0) {        err_sys("fork error");    }    else if (pid == 0)    {        while(1)        {            lseek(fd, 0, SEEK_SET);            read(fd, buf, 4);            printf("Child: counter: %d pid: %d\n", ++buf[0],getpid());            lseek(fd, 0, SEEK_SET);            write(fd, &buf, 4);            TELL_PARENT(getppid());                 WAIT_PARENT();        }        END();        exit(0);     }    while(1)    {        WAIT_CHILD();        lseek(fd, 0, SEEK_SET);        read(fd, buf, 4);        printf("Parent: counter: %d pid: %d\n", ++buf[0],getpid());        lseek(fd, 0, SEEK_SET);        write(fd, &buf, 4);        TELL_CHILD(pid);     }    END();    return 0;}
0 0