APUE2e之Exercise 10.6 Solution A

17 篇文章 0 订阅
11 篇文章 0 订阅

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值