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