Archive

Archive for February 16th, 2012

APUE2e Exercise 10.6 – Solution C

February 16th, 2012 No comments

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

APUE2e Exercise 10.6 – Solution B

February 16th, 2012 No comments

Using Standard I/O Library to read and write the file.

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
/**   
 * apue-chap10: exercise10-6b.c
 *
 * Description: Standard I/O Library
 *
 * 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>
 
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;
	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");
 
	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();
 
			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++){
			TELL_WAIT(); //set up signal handler
 
			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;
}

APUE2e Exercise 10.6 – Solution A

February 16th, 2012 No comments

Using File I/O to read and write the file.

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
169
170
171
172
173
174
175
176
177
/**   
 * 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;
}