这题虽然看起来简单,但是做的时候还是遇到了些问题
贴码:
贴码:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#defineMAXSIZE 100
sigset_t zeromask, maskset, oldmask;
static void
sig_handler(int signo)
{
}
void
SYNC_INIT(void)
{
structsigaction act;
bzero(&zeromask, sizeof(zeromask));
bzero(&maskset, sizeof(maskset));
sigaddset(&maskset, SIGUSR1);
sigaddset(&maskset, SIGUSR2);
act.sa_handler = sig_handler;
act.sa_flags= 0;
act.sa_flags|= SA_RESTART;
sigemptyset(&act.sa_mask);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
if(sigprocmask(SIG_BLOCK, &maskset, &oldmask) < 0) {
fprintf(stderr, "sigprocmask error\n");
exit(EXIT_FAILURE);
}
}
void
WAIT_PARENT(void)
{
sigsuspend(&zeromask);
}
void
TELL_PARENT(pid_t pid)
{
kill(pid,SIGUSR1);
}
void
WAIT_CHILD(void)
{
sigsuspend(&zeromask);
}
void
TELL_CHILD(pid_t pid)
{
kill(pid,SIGUSR2);
}
int
main(int argc, char **argv[])
{
pid_t pid;
char buf[MAXSIZE];
FILE *fp;
volatileint count =0;
int fd;
if ((fd =open("a", O_RDWR | O_CREAT | O_EXCL, 777)) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
fp =fdopen(fd,"w+");//改成文件流操作相对方便点,不过要注意缓冲问题
SYNC_INIT();
if ((pid =fork()) < 0)
fprintf(stderr, "fork error\n");
else if (pid== 0) {
for (; ;){
rewind(fp);//注意,在这里要把文件流指针重新指向文件的起点,下面读取也是一样的(因为读取时没有这句,所以纠结了一些时间,ps(这时读取返回总是EOF,提示到达文件尾部),所以检查错误真的很重要啊。。。)
fwrite(&count, sizeof(count), 1, fp);
// fprintf(fp,"%d\n", count);
fflush(fp);//这句很重要,因为输出到文件时默认是全缓冲的,我们不能容忍全缓冲,所以当写完时要立刻冲洗缓冲,否则得不到正确结果(也可以用setvbuf或者setbuf,不过我没试)
TELL_PARENT(getppid());
WAIT_PARENT();
rewind(fp);//读取前文件流指针指向文件起点
fread(&count, sizeof(count), 1, fp);
/* if(fscanf(fp, "%d", &count) == EOF)
perror("fscanf");*/
printf("child: %d\n", count);
count++;
sleep(1);
}
exit(0);
}
for (; ;){
WAIT_CHILD();
rewind(fp);//父子进程有各自的文件表项,所以文件流指针指向文件的位置互不影响
fread(&count, sizeof(count), 1, fp);
/* if(fscanf(fp, "%d", &count) == EOF)
perror("fscanf");*/
printf("father: %d\n", count);
count++;
rewind(fp);
fwrite(&count, sizeof(count), 1, fp);
//fprintf(fp, "%d\n", count);
fflush(fp);
TELL_CHILD(pid);
sleep(1);
}
exit(0);
}