[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
îÅÓËÏÌØËÏ ÞÉÔÁÀÝÉÈ ÐÒÏÃÅÓÓÏ× É ÜËÓËÌÀÚÉ×ÎÙÊ ÐÒÏÃÅÓÓ ÚÁÐÉÓÉ
ðéûõýéê ðòïãåóó é îåóëïìøëï þéôáàýéè, upd1_rdn.c :
1 #include <sys/types.h>
2 #include <sys/ipc.h>
3 #include <unistd.h>
4 #include <sys/sem.h>
5 #include <sys/shm.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <memory.h>
10 #define NPROC 6
11 #define NTRANSACTIONS 5
12 #define UPD 0
13
14 struct ACTIVITY {
15 int read_count;
16 int update_count;
17 };
18 static struct ACTIVITY *activity_ptr;
19 static int activity_index;
20
21 static key_t key;
22 static int semid, shmid ;
23 /* three semaphores in the set:
24 index 0 the count of the number of readers
25 having a value from 0 to n
26 index 1 only one updater - a binary semaphore
27 index 2 set when process desires an update
28 used to lock out any new readers while
29 there are any unfufilled updaters
30 */
31 static struct sembuf wait_no_readers = { 0, 0, 0};
32 static struct sembuf read_start = { 0, 1, 0};
33 static struct sembuf read_end = { 0, -1, 0};
34
35 static struct sembuf wait_no_upd_lock = { 1, 0, 0};
36 static struct sembuf upd_lock = { 1, 1, 0};
37 static struct sembuf upd_unlock = {1,-1,0};
38
39 static struct sembuf upd_desire = { 2, 1, 0};
40 static struct sembuf in_progress_up = { 2, -1, 0};
41 static struct sembuf wait_no_upd_desire = { 2, 0, 0};
42
43 static char pname[14];
44 static void rpterror(char *);
45 static void print_usage(void);
46 static void read_simulate(void);
47 static void upd_simulate(void);
48 static void print_usage(void);
49
50 main(int argc, char *argv[])
51 {
52 int i, master, getflag, trans;
53 struct shmid_ds shmstat;
54
55 /* process names will be p[0-5]
56 p0 will be master
57 second char in name will used to derived index
58 into ACTIVITY table
59 */
60 if(argv[0][1] == '0'){
61 master = 1;
62 getflag = 0666 | IPC_CREAT;
63 }
64 else getflag = 0666;
65
66 activity_index = argv[0][1] - '0';
67
68 strcpy(pname,argv[0]);
69
70 setbuf(stdout, 0);
71
72 key = ftok("upd1_rdn.c", 'v');
73 shmid=shmget(key,NPROC * sizeof(struct ACTIVITY), getflag);
74 if(shmid == -1){
75 rpterror("shmget failed");
76 exit(3);
77 }
78 if((activity_ptr = shmat(shmid, 0, 0)) == (struct ACTIVITY *)-
1){
79 rpterror("shmat failed");
80 exit(4);
81 }
82
83 if((semid = semget(key,3,getflag)) == -1){
84 rpterror("semget failed");
85 exit(5);
86 }
87
88 srand(getpid());
89 for(i=0; i<NTRANSACTIONS; i++) {
90 trans = rand()%4;
91 /*Probability(UPDATE) == .25 and Probability(READ) == .75*/
92 if(trans == UPD)
93 upd_simulate();
94 else
95 read_simulate();
96 sleep(1);
97 }
98
99
100 if(master)
101 while(1){
102 shmctl(shmid, IPC_STAT, &shmstat);
103 if(shmstat.shm_nattch == 1){
104 print_usage();
105 semctl(semid, 0, IPC_RMID, 0);
106 shmdt(activity_ptr);
107 shmctl(shmid, IPC_RMID, 0);
108 break;
109 }
110 sleep(1);
111 }
112 else shmdt(activity_ptr);
113
114 exit(0);
115 }
116
117 static void upd_simulate(void)
118 {
119 struct sembuf sole_updater[4];
120 struct ACTIVITY *upd_ptr;
121
122 printf("%s wants to do an update\n", pname;)
123 semop(semid, &upd_desire, 1);
124
125 sole_updater[0] = wait_no_readers;
126 sole_updater[1] = upd_lock;
127 sole_updater[2] = read_start;
128 sole_updater[3] = in_progress_upd;
129 /* suspend till all current readers are finished */
130 semop(semid, sole_updater, 4);
131 /* Note: if multiple updaters are waiting - newest one
132 will do the upd_lock
133 */
134
135 /* increase this updater's activity count */
136 upd_ptr = activity_ptr + activity_index;
137 upd_ptr ->update_count++;
138 printf("%s u %2d start\n",pname, upd_ptr->update_count);
139 sleep(rand()%7);
140 printf("%s u %2d end\n",pname, upd_ptr->update_count);
141 sole_updater[0] = read_end;
142 sole_updater[1] = upd_unlock;
143 semop(semid, sole_updater, 2);
144 }
145
146 static void read_simulate(void)
147 {
148 struct sembuf one_of_n_readers[3];
149 struct ACTIVITY *read_ptr;
150
151 one_of_n_readers[0] = wait_no_upd_lock;
152 one_of_n_readers[1] = wait_no_upd_desire;
153 one_of_n_readers[2] = read_start;
154 semop(semid, one_of_n_readers, 3);
155 read_ptr = activity_ptr + activity_index;
156 read_ptr ->read_count++;
157 printf("%s r %2d start\n",pname, read_ptr->read_count);
158 sleep(rand()%25);
159 printf("%s r %2d end\n",pname, read_ptr->read_count);
160 semop(semid, &read_end, 1);
161 }
162
163 static void print_usage(void)
164 {
165 int p;
166
167 for(p=0; p<NPROC; p++, activity_ptr++)
168 printf("p%d: #read=%d #upd=%d\n",
169 p, activity_ptr->read_count,
170 activity_ptr->update_count);
171 }
172
173 static void rpterror(char *string)
174 {
175 char errline[50];
176
177 sprintf(errline,"%s %s", string, pname);
178 perror(errline);
179 }
÷ùúï÷:
$ ln upd1_rdn p0 # created IPC facilities
$ ln p0 p1
$ ln p0 p2
$ ln p0 p3
$ ln p0 p4
$ ln p0 p5
$ cat p_start
p0 &
sleep 1
for i in p1 p2 p3 p4 p5
do
$i &
done
$ p_start
p0 r 1 start
p2 r 1 start
p4 r 1 start
$ p5 wants to do an update
p0 r 1 end
p4 r 1 end
p2 r 1 end
p5 u 1 start
p5 u 1 end
.
.
.
p5 r 4 start
p3 r 4 start
p3 r 4 end
p5 r 4 end
p0: #read=4 #upd=1
p1: #read=5 #upd=0
p2: #read=5 #upd=0
p3: #read=4 #upd=1
p4: #read=5 #upd=0
p5: #read=4 #upd=1