Using File I/O to read and write the file.
/**
* apue-chap10: exercise10-6a.c
*
* Description: FILE I/O
*
* Created On: Feb 15, 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;
char *filename = "counter.file";
char *rbuf, *wbuf;
int i, j;
rbuf = (char *)malloc(sizeof(int));
wbuf = (char *)malloc(sizeof(int));
if((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
err_sys("open error");
if(sprintf(wbuf, "%d", 0) < 0)
err_sys("sprintf error");
if(write(fd, wbuf, sizeof(int)) > 0 ){
printf("Writing initial value of the counter: %s\n", wbuf);
fsync(fd);
}
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(); //set up signal handler
counter = -1;
if(lseek(fd, 0, SEEK_SET) != 0)
err_sys("Child: lseek error");
if(read(fd, rbuf, sizeof(int)) < 0)
err_sys("Child: read error");
if(sscanf(rbuf, "%d", &counter) == EOF)
err_sys("Child: sscanf error");
printf("Child: read counter from the file: %d\n", counter);
counter++;
printf("Child: increase counter to: %d\n", counter);
if(lseek(fd, 0, SEEK_SET) != 0)
err_sys("Child: lseek error");
if(sprintf(wbuf, "%d", counter) < 0)
err_sys("Child: sprintf error");
if(write(fd, wbuf, sizeof(int)) > 0 ){
printf("Child: Write counter to the file: %s\n", wbuf);
fsync(fd);
}
TELL_PARENT(ppid);
WAIT_PARENT();
}
counter = -1;
if(lseek(fd, 0, SEEK_SET) != 0)
err_sys("Child: lseek error");
if(read(fd, rbuf, sizeof(int)) < 0)
err_sys("Child: read error");
if(sscanf(rbuf, "%d", &counter) == EOF)
err_sys("Child: sscanf error");
printf("\nChild: read counter from the file: %d\n", counter);
close(fd);
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;
if(lseek(fd, 0, SEEK_SET) != 0)
err_sys("Parent: lseek error");
if(read(fd, rbuf, sizeof(int)) < 0)
err_sys("Parent: read error");
if(sscanf(rbuf, "%d", &counter) == EOF)
err_sys("Parent: sscanf error");
printf("Parent: read counter from the file: %d\n", counter);
counter++;
printf("Parent: increase counter to: %d\n", counter);
if(lseek(fd, 0, SEEK_SET) != 0)
err_sys("Parent: lseek error");
if(sprintf(wbuf, "%d", counter) < 0)
err_sys("Parent: sprintf error");
if(write(fd, wbuf, sizeof(int)) > 0 ){
printf("Parent: Write counter to the file: %s\n", wbuf);
fsync(fd);
}
TELL_CHILD(pid);
}
}
close(fd);
return 0;
}