Я пытаюсь создать решение для проблемы перехода через реку из «Маленькой книги семафоров» (глава 5, раздел 7, стр. 148), я использую виртуальную машину Ubuntu на моем ПК.
Проблема в том, что созданные мной семафоры не меняют значений, все они остаются на 0, я использую четыре файла.
Что я делаю, запускаю буфер, а затем создаю два хакерских процесса изатем два крепостных процесса, дело в том, что сообщение «Boarding X» печатается до того, как лодка заполнена (как минимум, четыре пассажира), и когда я печатаю значения семафора, все они находятся в заголовке 0.
.h, где я объявляю идентификаторы и операции семафоров:
#ifndef SEMAFOROS_H
#define SEMAFOROS_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define BARRIER 10
#define MUTEX 11
#define SERFQUEUE 12
#define HACKERQUEUE 13
struct buffer {
int hackers;
int serfs;
};
int sem_wait(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = -val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int sem_signal(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int mutex_wait(int semid, int sem_num) {
return sem_wait(semid, sem_num, 1);
}
int mutex_signal(int semid, int sem_num) {
return sem_signal(semid, sem_num, 1);
}
#endif
buffer.c, где я создаю семафоры:
#include "header.h"
int main(int argc, char* argv[])
{
int semid, shmid, i;
key_t key;
if (argc != 1) {
printf("usage: %s\n", argv[0]);
return -1;
}
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(argv[0]);
return -1;
}
if ( (semid = semget(key, 4, 0666 | IPC_CREAT)) < 0 ) {
perror(argv[0]);
return -1;
}
semctl(semid, BARRIER, SETVAL, 4);
semctl(semid, MUTEX, SETVAL, 1);
semctl(semid, SERFQUEUE, SETVAL, 0);
semctl(semid, HACKERQUEUE, SETVAL, 0);
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
if ( (shmid = shmget(key, sizeof(struct buffer), 0666 | IPC_CREAT)) < 0) {
semctl(semid, 0, IPC_RMID, 0);
perror("shmget");
return -1;
}
struct buffer *b = (struct buffer *) shmat(shmid, (void *) 0, 0);
b->hackers = 0;
b->serfs = 0;
shmdt(b);
return 0;
}
hackers.c, код для хакеров:
#include "header.h"
#include <time.h>
void a_hacker(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->hackers += 1;
if (b->hackers == 4) {
sem_signal(semid, HACKERQUEUE, 4);
b->hackers = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->hackers = 0;
b->serfs -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, HACKERQUEUE, 1);
printf("Boarding a hacker\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_hackers = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_hackers = atoi(argv[1]);
if (amount_hackers < 1) {
printf("%s: The amount_of_hackers must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_hackers; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_hacker(argv[0]);
} else {
}
}
return 0;
}
serfs.c, код для крепостных:
#include "header.h"
#include <time.h>
void a_serf(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->serfs += 1;
if (b->serfs == 4) {
sem_signal(semid, SERFQUEUE, 4);
b->serfs = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->serfs = 0;
b->hackers -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, SERFQUEUE, 1);
printf("Boarding a serf\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_serfs = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_serfs = atoi(argv[1]);
if (amount_serfs < 1) {
printf("%s: The amount_of_serfs must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_serfs; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_serf(argv[0]);
} else {
}
}
return 0;
}
Может кто-нибудь помочь мне?