I have a project called "a consumer and a producer". I need to use semaphores and shared memory to read signs (one by one) from the file and put them to shared memory (in producer.c) and after read them and put in output file (in consumer.c). Files should be the same after the end of the programs.
Libraries and global variables (both files the same):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
key_t keySem;
key_t keySeg;
int segment;
char *address;
int semaphore;
int x;
pid_t w;
So I have in producers.c:
int main() {
srand(time(0));
if((keySeg = ftok(".", 'X')) == -1) end("error - creating a key!\n");
if((segment = shmget(keySeg, sizeof(char), 0777 | IPC_CREAT )) == -1)
end("error - creating a shared memory!\n");
address = shmat(segment,0,0);
if(*address == -1) end("error - getting an address\n");
if((keySem = ftok(".", 'Y')) == -1) end("error - creating a key\n");
if((semaphore = semget(keySem, 2, 0600 | IPC_CREAT )) == -1)
end("error - creating a semaphore!\n");
if((semctl(semaphore, 0, SETVAL, 1)) == -1) end("cant set a semaphore\n");
if((semctl(semaphore, 1, SETVAL, 0)) == -1) end("cant set a semaphore\n");
char sign;
FILE *file;
file = fopen("in", "r");
if(file == NULL) end("error - opening in file\n");
while(fscanf(file, "%c", &sign) != EOF){
semaphore_p(0);
*address = sign;
semaphore_v(1);
}
semaphore_p(0);
*address = EOF;
semaphore_v(1);
fclose(file);
shmdt(address);
exit(0);
}
and in consumer.c:
int main() {
if((keySeg = ftok(".", 'X')) == -1) end("Error - creating a key!\n");
if((segment = shmget(keySeg, 0, 0600 | IPC_CREAT)) == -1)
end("Error - get access to shared memory!\n");
address = shmat(segment,0,0);
if(*address == -1) end("Error - address!\n");
if((keySem = ftok(".", 'Y')) == -1) end("Error - semaphore key!\n");
if((semaphore = semget(keySem, 2, 0600 | IPC_CREAT)) == -1)
end("Error - get access to semaphores!\n");
if((semctl(semaphore, 0, SETVAL, 1)) == -1) end("cant set a semaphore\n");
if((semctl(semaphore, 1, SETVAL, 0)) == -1) end("cant set a semaphore\n");
char sign;
FILE *file;
file = fopen("out", "w");
if(file == NULL) end("error - opening out file\n");
while(sign != EOF) {
semaphore_p(1);
sign = *address;
fputc(sign, file);
printf("[CONSUMER] Sign: %c\n", sign);
semaphore_v(0);
}
fclose(file);
shmdt(address);
shmctl(segment, IPC_RMID, 0);
if((semctl(semaphore, 0, IPC_RMID)) == -1)
end("error - deleting semaphore\n");
exit(0);
}
And it's all working for the small files (below 500 chars), but if I put more chars in a file, a project stops after semaphore_v(0) (after reading a few hundred characters). Here is the result: Result
Here is how semaphore_p and semaphore_v functions look like.
static void semaphore_p(int x) {
struct sembuf bufor_sem;
bufor_sem.sem_num=x;
bufor_sem.sem_op=-1;
bufor_sem.sem_flg=0;
while((semop(semaphore, &bufor_sem, 1)) == -1) {
if (errno == ERANGE) {
int a = semctl(semaphore, x, GETVAL);
semctl(semaphore, x, SETVAL, a);
} else if(errno == 4) {
//semaphore_p(x);
} else {
end("ERROR!\n");
}
}
printf("[CONSUMER] Semaphore %d has been closed.\n", x);
}
static void semaphore_v(int x) {
struct sembuf bufor_sem;
bufor_sem.sem_num=x;
bufor_sem.sem_op=1;
bufor_sem.sem_flg=0;
while((semop(semaphore, &bufor_sem, 1)) == -1) {
if (errno == ERANGE) {
int a = semctl(semaphore, x, GETVAL);
semctl(semaphore, x, SETVAL, a);
} else if(errno == 4) {
//semaphore_p(x);
} else {
end("ERROR!\n");
}
}
printf("[CONSUMER] Semafor %d has been opened.\n", x);
}
And end function
void end(char text[]) {
perror(text);
if(EXIT_FAILURE == 0) exit(0);
exit(EXIT_FAILURE);
}
I've read something about ERANGE errno, but the program doesn't throw any errors. What is the reason for the pause? Do semaphore have some kind of vitality? How can I ignore it?
Thank you in advance for your help :)