В этой статье я опишу ещё один способ взаимодействия процессов.
Семафоры нужны чтобы предотвратить конфликты. Перед тем как воспользоваться доступом к ресурсу, процесс устанавливает семафор, чтобы занять место. Если семафор уже установлен другим процессом, текущий блокируется, пока ресурс не освободится.
Функции, которые мы будем использовать:
Использование семафоров
Функции, которые не описанны в этой статье, описаны в статье Использование общей памяти
Семафоры нужны чтобы предотвратить конфликты. Перед тем как воспользоваться доступом к ресурсу, процесс устанавливает семафор, чтобы занять место. Если семафор уже установлен другим процессом, текущий блокируется, пока ресурс не освободится.
Функции, которые мы будем использовать:
- 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 |
Функции, которые не описанны в этой статье, описаны в статье Использование общей памяти
Комментариев нет:
Отправить комментарий