0

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 :)

Zar
  • 5
  • 1
  • 7
  • 2
    I recommend you read [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) Also, `sign` will typically *never* be equal to `EOF`. – Some programmer dude Jan 02 '18 at 17:06
  • I have a guess about the nature of the problem, but it cannot be checked against the code fragments you have posted. If you want an answer then do edit your question to include a *bona fide* [mcve] that demonstrates the problem. – John Bollinger Jan 02 '18 at 17:30
  • Edited: minimal code and the problem is still the same – Zar Jan 02 '18 at 17:55
  • Please indent the code. The wall-to-wall unindented code is horrible to look at, and you need to make your code inviting to people so that they'll help you. Also, the logic in `end()` that is ` if(EXIT_FAILURE == 0) exit(0); exit(EXIT_FAILURE);` is weird; if `EXIT_FAILURE` is zero, you'll exit with the value of `EXIT_FAILURE`, otherwise you'll exit with the value of `EXIT_FAILURE`. Either you had in mind something like `errno` in the condition, or you should simply have `exit(EXIT_FAILURE);`. Note that testing `errno` here is not entirely reliable. – Jonathan Leffler Jan 03 '18 at 06:56

0 Answers0