您的位置:首页 > 产品设计 > UI/UE

APUE2e之Exercise 10.6 Solution B

2012-09-28 04:45 99 查看
Using Standard I/O Library to read and write the file.

/**
* apue-chap10: exercise10-6b.c
*
* Description: Standard I/O Library
*
* Created On: Feb 16, 2012
*
* @author: Huang Zhu
*
* @email: zhuhuang.zp@gmail.com
*/

#include <apueerr.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>

static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask, zeromask;

static void sig_usr(int signo)
{
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);
}

void TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);
}

void WAIT_PARENT(void)
{
while(sigflag == 0)
sigsuspend(&zeromask); //set mask and sleep and wait
sigflag = 0;

if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
perror("SIG_SETMASK error");
}

void WAIT_CHILD(void)
{
while(sigflag == 0)
sigsuspend(&zeromask); //set mask and sleep and wait
sigflag = 0;

if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
perror("SIG_SETMASK error");
}

int main(void)
{
int fd, pid, ppid, counter, round = 5;
FILE* fp;
char *filename = "counter.file";
int i, j;

if((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
err_sys("open error");

if((fp = fdopen(fd, "r+")) == NULL )
err_sys("fdopen error");

if(fputc(0, fp) != EOF){
printf("Writing initial value of the counter: 0\n");
fflush(fp); //if fflush is not used, the change of counter cannot be seen instantly by other readers.
}

if(ferror(fp))
err_sys("fputc error");

if((pid = fork()) < 0){
err_sys("fork error");
}else if(pid == 0){ //child
ppid = getppid();

for(i = 0; i < round; i++){
printf("\nChild: round %d\n", i+1);

TELL_WAIT();

counter = -1;

rewind(fp);
counter = fgetc(fp);
printf("Child: read counter from the file: %d\n", counter);

counter++;
printf("Child: increase counter to: %d\n", counter);

rewind(fp);
if(fputc(counter, fp) != EOF){
printf("Child: Write counter to the file: %d\n", counter);
fflush(fp);
}
if(ferror(fp))
err_sys("Child: fputc error");

TELL_PARENT(ppid);

WAIT_PARENT();
}

counter = -1;
rewind(fp);
counter = fgetc(fp);
printf("\nChild: read counter from the file: %d\n", counter);

exit(0);
}else{ //parent
for(j = 0; j < round; j++){
TELL_WAIT(); //set up signal handler

WAIT_CHILD();
printf("\nParent: round %d\n", j+1);
counter = -1;

rewind(fp);
counter = fgetc(fp);
printf("Parent: read counter from the file: %d\n", counter);

counter++;
printf("Parent: increase counter to: %d\n", counter);

rewind(fp);
if(fputc(counter, fp) != EOF){
printf("Parent: Write counter to the file: %d\n", counter);
fflush(fp);
}
if(ferror(fp))
err_sys("Parent: fputc error");

TELL_CHILD(pid);
}
}

fclose(fp);
close(fd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fp signal file library null kill