APUE2e Exercise 10.6 – Solution C
Using Standard I/O Library to read and write the file. Rather than using signal function, I used sigaction. Thus don’t need to call TELL_WAIT in the for body.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | /** * apue-chap10: exercise10-6c.c * * Description: Standard I/O Library + sigaction * * 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> #define __USE_POSIX199309 1 static volatile sig_atomic_t sigflag; static sigset_t newmask, oldmask, zeromask; struct sigaction act, oact1, oact2; static void sig_usr(int signo) { sigflag = 1; } void TELL_WAIT(void) { act.sa_handler = sig_usr; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGUSR1, &act, &oact1) < 0) err_sys("sigaction SIGUSR1 error"); if(sigaction(SIGUSR2, &act, &oact2) < 0) err_sys("sigaction 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"); TELL_WAIT(); 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); 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++){ 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; } |










最新评论