/* Программа 2 для
иллюстрации работы с разделяемой памятью*/
/* Мы организуем
разделяемую память для массива из 3-х целых
чисел. Первый элемент массива является
счетчиком числа запусков программы 1, второй элемент массива -
счетчиком числа запусков программы
2, т. е.
данной программы, третий элемент массива - счетчиком
числа запусков обеих программ */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
int main()
{
int shmid; /* IPC дескриптор для области разделяемой памяти */
int new = 1; /* Флаг необходимости инициализации элементов массива */
char pathname[] = "06-1a.c"; /* Имя файла, использующееся для генерации ключа. Файл с таким именем должен существовать в текущей директории */
key_t key; /* IPC ключ */
/* Генерируем IPC ключ из имени файла 06-1a.c в
текущей директории и номера экземпляра
области разделяемой памяти 0 */
if((key = ftok(pathname,0)) < 0){
exit(-1);
/* Пытаемся эксклюзивно создать
разделяемую память для сгенерированного
ключа, т.е. если для этого ключа она уже
существует системный вызов вернет
отрицательное значение. Размер памяти
определяем как размер массива из 3-х целых
переменных, права доступа 0666 - чтение и
запись разрешены для всех */
if((shmid = shmget(key, 3*sizeof(int), 0666|IPC_CREAT|IPC_EXCL)) < 0){
/* В случае возникновения ошибки пытаемся
определить: возникла ли она из-за того, что
сегмент разделяемой памяти уже
существует или по другой причине */
printf("Can\'t create shared memory\n");
exit(-1);
/* Если из-за того, что разделяемая
память уже существует пытаемся
получить ее IPC дескриптор и, в случае
удачи, сбрасываем флаг
необходимости инициализации
элементов массива */
if((shmid = shmget(key, 3*sizeof(int), 0)) < 0){
exit(-1);
new = 0;
/* Пытаемся отобразить разделяемую память в адресное пространство текущего процесса.
Обратите внимание на то, что для правильного сравнения мы явно преобразовываем
значение -1 к указателю на целое. */
if((array = (int *)shmat(shmid, NULL, 0)) == (int *)(-1)){
exit(-1);
/* В зависимости от значения флага new либо инициализируем массив, либо увеличиваем соответствующие счетчики */
if(new){
array[1] = 1;
array[2] = 1;
array[2] += 1;
/* Печатаем новые значения счетчиков, удаляем разделяемую память из адресного пространства текущего процесса и завершаем работу */
printf("Program 1 was spawn %d times, program 2 - %d times, total - %d times\n",
array[0], array[1], array[2]);
if(shmdt(array) < 0){
exit(-1);
return 0;