[<<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