В этой статье я опишу ещё один способ взаимодействия процессов.
Семафоры нужны чтобы предотвратить конфликты. Перед тем как воспользоваться доступом к ресурсу, процесс устанавливает семафор, чтобы занять место. Если семафор уже установлен другим процессом, текущий блокируется, пока ресурс не освободится.
Функции, которые мы будем использовать:
Использование семафоров
Функции, которые не описанны в этой статье, описаны в статье Использование общей памяти
Семафоры нужны чтобы предотвратить конфликты. Перед тем как воспользоваться доступом к ресурсу, процесс устанавливает семафор, чтобы занять место. Если семафор уже установлен другим процессом, текущий блокируется, пока ресурс не освободится.
Функции, которые мы будем использовать:
- int semget(key_t KEY, int SEMS, int FLAGS);
- int semop(int ID, struct sembuf* SB, size_t SIZE);
struct sembuf {
unsigned short int sem_num; /* номер семафора */
short int sem_op; /* равен -1 если процесс собирается использовать ресурс, 1 - если ресурс свободен */
short int sem_flg; /* флаги для операции над семафорами */
};
- int semctl(int ID, int SNUM, int COMMAND, union semnum sem_arg);
union semnum {
int val;
struct semid_ds* buf;
unsigned short* array;
};
Использование семафоров
/* Файл owner.c - запись данных в память */
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHMEM_SIZE 4096
#define SH_MESSAGE "test\n"
#define SEM_KEY 2012
#define SHM_KEY 2012
union semnum {
int val;
struct semid_ds * buf;
unsigned short * array;
} sem_arg;
int
main(void)
{
int shm_id, sem_id;
char * shm_buf;
int shm_size;
struct shmid_ds ds;
struct sembuf sb[1];
unsigned short sem_vals[1];
shm_id = shmget(SHM_KEY, SHMEM_SIZE,
IPC_CREAT | IPC_EXCL | 0600);
if(shm_id == -1)
{
fprintf(stderr, "shmget()\n");
return 1;
}
sem_id = semget(SEM_KEY, 1,
0600 | IPC_CREAT | IPC_EXCL);
if(sem_id == -1)
{
fprintf(stderr, "semget()\n");
return 1;
}
printf("Semaphore: %d\n", sem_id);
sem_vals[0] = 1;
sem_arg.array = sem_vals;
if(semctl (sem_id, 0, SETALL, sem_arg) == -1)
{
fprintf(stderr, "semctl() error\n");
return 1;
}
shm_buf = (char *) shmat(shm_id, NULL, 0);
if (shm_buf == (char *) -1)
{
fprintf(stderr, "shmat() error\n");
return 1;
}
shmctl(shm_id, IPC_STAT, &ds);
shm_size = ds.shm_segsz;
if(shm_size < strlen(SH_MESSAGE))
{
fprintf(stderr, "error: segsize=%d\n", shm_size);
return 1;
}
strcpy(shm_buf, SH_MESSAGE);
printf("ID: %d\n", shm_id);
sb[0].sem_num = 0;
sb[0].sem_flg = SEM_UNDO;
sb[0].sem_op = -1;
semop(sem_id, sb, 1);
sb[0].sem_op = -1;
semop(sem_id, sb, 1);
semctl(sem_id, 1, IPC_RMID, sem_arg);
shmdt(shm_buf);
shmctl(shm_id, IPC_RMID, NULL);
return 0;
}
/* Файл user.c - чтение данных из памяти */
#include <sys/shm.h>
#include <stdio.h>
#include <sys/sem.h>
#define SEM_KEY 2012
#define SHM_KEY 2012
int
main(int argc, char ** argv)
{
int shm_id, sem_id;
char * shm_buf;
struct sembuf sb[1];
shm_id = shmget(SHM_KEY, 1, 0600);
if(shm_id == -1)
{
fprintf(stderr, "shmget() error\n");
return 1;
}
sem_id = semget(SEM_KEY, 1, 0600);
if(sem_id == -1)
{
fprintf(stderr, "semget() error\n");
return 1;
}
shm_buf = (char *) shmat(shm_id, 0, 0);
if(shm_buf == (char *) -1)
{
fprintf(stderr, "shmat() error\n");
return 1;
}
printf("Message: %s\n", shm_buf);
sb[0].sem_num = 0;
sb[0].sem_flg = SEM_UNDO;
sb[0].sem_op = 1;
semop(sem_id, sb, 1);
shmdt(shm_buf);
return 0;
}
![]() |
| Семафоры - owner |
![]() |
| Семафоры - user |
Функции, которые не описанны в этой статье, описаны в статье Использование общей памяти


Комментариев нет:
Отправить комментарий