10.6主要实现父子进程对一个文件进行同步读写,要求分别父子进程交替对文件中的变量加1后再写入文件中。
父子进程之间实现信号同步代码,并包含在头文件”sync.h“中:
主要代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include "sync.h"
#define BUF_SIZE 100
static volatile sig_atomic_t sigflag;
//static long last_off=0;
void int2chars(char* chars, int count, char* cat)
{
int b=0, flag = count;
do{
flag /= 10;
b++;
}while(flag);
chars[b--] = '\0';
while(b>=0){
chars[b--] = count%10 + '0';
count /= 10;
}
strcat(chars, cat);
return ;
}
int chars2int(char* chars)
{
int count = 0, flag = 1;
int i = strlen(chars) - 1;
while(i >= 0)
{
count += (chars[i] - '0') * flag;
flag *= 10;
i--;
}
return count;
}
int main(int argc, char *argv[])
{
FILE *fp;
pid_t pid;
int count = 0, shmid;
char buf[1024] = "";
long *lastoffptr;
shmid=shmget(IPC_PRIVATE, BUF_SIZE, IPC_CREAT|0666);
if(shmid == -1)
{
printf("Shared Memory Created error...\n");
exit(-127);
}
lastoffptr = shmat(shmid, NULL, 0);
if((fp = fopen("tt.txt", "w+")) < 0)
{
perror("open error or write error!");
exit(-1);
}
fprintf(fp, "0\ttest\n");
fflush(fp);
TELL_WAIT();
alarm(2);
if((pid = fork()) > 0)//parent
{
while(1){
WAIT_CHILD();
printf("the current ftell=%ld\n", ftell(fp));
fseek(fp, *lastoffptr, SEEK_SET);
fscanf(fp, "%d\t%s\n", &count, buf);
printf("parent read from the file count=%d.\n", count);
*lastoffptr = ftell(fp);
fprintf(fp,"%d\t%s\n", count+1, "parent");
fflush(fp);
TELL_CHILD(pid);
}
}else //child
{
while(1){
fseek(fp, *lastoffptr, SEEK_SET);
fscanf(fp, "%d\t%s\n", &count, buf);
printf("child read from the file count=%d.\n", count);
*lastoffptr = ftell(fp);
if(fprintf(fp,"%d\t%s\n", count+1, "child")<0){printf("child write error\n");}
fflush(fp);
TELL_PARENT(getppid());
WAIT_PARENT();
}
}
fclose(fp);
return 0;
}
父子进程之间实现信号同步代码,并包含在头文件”sync.h“中:
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask, zeromask;
//one signal handler for SIGUSR1 and SIGUSR2
static void sig_usr(int signo)
{
sigflag = 1;
}
void TELL_WAIT(void)
{
if(signal(SIGUSR1, sig_usr) == SIG_ERR)
{
perror("signal(SIGUSR1) error");
exit(-1);
}
if(signal(SIGUSR2, sig_usr) == SIG_ERR)
{
perror("signal(SIGUSR2) error");
exit(-2);
}
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");
exit(-3);
}
}
void TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}
void WAIT_PARENT(void)
{
while(sigflag == 0)
{
sigsuspend(&zeromask);
}
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
perror("SIG_SETMASK error");
exit(-4);
}
}
void TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);
}
void WAIT_CHILD(void)
{
while(sigflag == 0)
{
sigsuspend(&zeromask);
}
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
perror("SIG_SETMASK error");
exit(-5);
}
}