[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
Разделяемая память - Родительский процесс
13-16 Структура показывает, что доступно 15 мест.
29 Пользовательская функция, которая создает, присоединяет и
инициализирует разделяемый сегмент памяти информацией о
классе.
30 Пользовательская функция, создающая набор семафоров и
инициализирующая эти семафоры значением 1.
РАЗДЕЛЯЕМАЯ ПАМЯТЬ - РОДИТЕЛЬСКИЙ ПРОЦЕСС
1 #include"registration.h"
2 #include<string.h>
3 #include<unistd.h>
4 #include<stdlib.h>
5 #include<sys/types.h>
6 #include<sys/ipc.h>
7 #include<sys/sem.h>
8 #include<sys/shm.h>
9 #include<stdio.h>
10 #include<memory.h>
11 #include<wait.h>
12 static struct CLASS class = {
13 "1001",
14 "120186",
15 "C Language for Programmers"
16 };
17 #define NCHILD 3
18 static pid_t child[NCHILD];
19 static char*shm_ptr;
20 static intsemid, shmid;
21 static charascsemid[10], ascshmid[10];
22 static char pname[14];
23 static void rpterror(char *),shm_init(void),
24 sem_init(void), wait_and_wrap_up(void);
25 main(int argc, char *argv[])
26 {
27 int i;
28 strcpy(pname,argv[0]);
29 shm_init();
30 sem_init();
36-49 Создает три подпроцесса-продавца (shmc[0-2]).
50 Пользовательская функция ждет, когда продавцы продадут все
места, а затем удаляет сегмент разделяемой памяти и
семафоры.
54 Создает сегмент разделяемой памяти, размера, достаточного
чтобы хранить информацию о классе. Поскольку в качестве
ключа задается IPC_PRIVATE, идентификатор разделяемой памяти
должен быть передан подпроцессам либо как аргумент командной
строки, либо как переменная среды. Только процессы с
эффективным пользовательским идентификатором хозяина могут
использовать его для чтения и записи.
59 Отображает разделяемый сегмент в виртуальное пространство
данных процесса, предоставив системе выбор адреса
присоединения. Сегмент присоединяется с правом записи (без
флага SHM_RDONLY).
64 Копирует информацию о классе в разделяемый сегмент.
65 Создает ASCII представление для значения shmid.
Замечание: Альтернативой ключу IPC_PRIVATE может быть использование
родительским процессом своего идентификатора процесса в качестве
ключа. Затем подпроцессы смогут получить ключ вызовом getppid(3C).
36 for(i=0; i<NCHILD; i++){
37 child[i] = fork();
38 switch(child[i]){
39 case -1:
40 rpterror("fork-failure");
41 exit(1);
42 case 0:
43 sprintf(pname,"shmc%d",i+1);
44 execl("shmc", pname, ascshmid,
45 ascsemid, (char*)0);
46 perror("execl failed");
47 exit(2);
48 }
49 }
50 wait_and_wrap_up();
51}
52static void shm_init(void)
53{
54 shmid=shmget(IPC_PRIVATE,sizeof(class),0600|I
55 if(shmid == -1){
56 perror("shmget failed");
57 exit(3);
58 }
59 shm_ptr = shmat(shmid, 0, 0);
60 if(shm_ptr == (char *)-1){
61 perror("shmat failed");
62 exit(4);
63 }
64 memcpy(shm_ptr,&class,sizeof(class));
65 sprintf(ascshmid, "%d", shmid);
66}
69-80 Создает семафор, инициализирует его в 1 и создает
ASCII-представление для его идентификатора.
83-90 Ждет, когда все продавцы обнаружат, что больше нет
доступных мест.
93 Отсоединяет разделяемый сегмент.
94-95 Удаляет разделяемый сегмент и семафор.
Файл: shmp.c
69 static void sem_init(void)
70 {
71 if((semid=semget(IPC_PRIVATE,1,0600|IPC_CREAT))==-1) {
72 perror("semget failed");
73 exit(5);
74 }
75 if((semctl(semid,0,SETVAL,1)) == -1){
76 printf("parent: semctl, SETVAL failed\n");
77 exit(6);
78 }
79 sprintf(ascsemid, "%d", semid);
80 }
81 static void wait_and_wrap_up(void)
82 {
83 pid_t wait_rtn; int w, ch_active = NCHILD;
84 while( ch_active > 0 ){
85 wait_rtn = wait( (int *)0 );
86 for(w=0; w<NCHILD; w++)
87 if(child[w]==wait_rtn){
88 ch_active--;
89 break;
90 }
91 }
92 printf("Parent removing shm and sem\n");
93 shmdt(shm_ptr);
94 shmctl(shmid, IPC_RMID, NULL);
95 semctl(semid, 0, IPC_RMID, 0);
96 exit(0);
97 }
98 static void rpterror(char *string)
99 {
100 char errline[50];
101 sprintf(errline,"%s %s", string, pname);
102 perror(errline);
103 }