-2

I'm looking for help with synchronization problem in Linux. I'm newbie, and I think I don't really understand how to use semaphores to synchronize. My task is to sync two processes that access a file - one reads from fifo from another process, writes to this file, then another reads. I know that my code lacks synchronization, but i have no clue how to do this.

Code:

sem_t writer, reader;
    void readFromFifoSendToFile(void) {
         sem_init(&writer, 1, 1);
         FILE *fp;
         char buffer[100];
         FILE *file;
         file = fopen("file", "w+");
         fclose(file);

         while(1) {
                  sem_wait(&writer);
                  fp = fopen("fifo", "r");
                  fscanf(fp, "%s", buffer);
                  fclose(fp);
                  file = fopen("file", "a+");
                  fputs(buffer, file);
                  fclose(file);
                  sem_post(&writer);
         }
    }

    void readFromFileAndPrint(void) {
         sem_init(&reader, 1, 1);
         FILE *fp;
         char buffer[100];
         int counter = 0;

         while(1) {
                  sem_wait(&reader);
                  counter++;
                  if(counter == 1) {
                      sem_wait(&writer);
                  sem_post(&reader);
                  fp = fopen("file", "r");
                  fscanf(fp, "%s", buffer);
                  fclose(fp);
                  printf("%s", buffer);
                  sem_wait(&reader);
                  if(counter == 0) {
                      sem_post(&writer);
                  }
                  sem_post(&reader);
         }
    }
voidmat
  • 113
  • 3
  • 12
  • Do you have to use semaphores or could you use [named pipess](http://www.linuxjournal.com/article/2156) ? – Soren Jan 20 '17 at 10:53
  • 1
    Is this a school assignment? Did you miss the lecture about synchronization? There's nothing in your course literature? Have you tried searching for it (there are thousands of examples and tutorials all over the 'net)? – Some programmer dude Jan 20 '17 at 10:54
  • @Soren I dont have to use semaphores, but i need to use file. I tried looking for answer, but i don't get that concepts. I'm Java guy, haven't used these Linux traits. Yes, that is school assignment. – voidmat Jan 20 '17 at 10:57
  • Files are already (kind of) synchronized by the OS. What sort of consistency guarantee do you need? What actual problem do you observe when doing this without explicit synchronization? – Useless Jan 20 '17 at 11:21
  • @Useless without explicit synchronization i experience problems with printing data to stdout. in file everything is fine, but there are no spaces (%20), but i think that's problem of scanf which doesn't read white spaces. data flow is: stdin --> pid1 --> FIFO --> pid2 (translate to hex) --> FILE --> pid3 --> stdout would be really glad if someone help :) – voidmat Jan 20 '17 at 11:32
  • i added my approach on synchronizing it. That's solution from my lectures, but it doesn't seem to work (processes don't answer for signals), and it doesn't print anything to stdout as well. – voidmat Jan 20 '17 at 11:42

1 Answers1

4

Your main problem appears to be related to the concept of how a semaphore works. Semaphores are best viewed as a signal between a producer and consumer. When the producer have done something they post a signal on the semaphore, and the consumer will wait on the semaphore until the producer post a signal.

So in your case, there should only be one semaphore between the consumer and the producer -- they should share this semaphore for their synchronization. Also, the semaphore should start at the value zero since nothing have been produced yet. Every time the producer post to the semaphore the value will increase by one, the consumer when it waits on the semaphore will sleep if the value is zero, until such a time when the producer post and the value increases and becomes one. If the producer is much faster than the consumer the value of the semaphore can go up and be more than one which is fine, as long as the consumer is consuming the output in the same size of units as the producer produces them.

So a working example here, but without any error handling -- adding error handling is beyond the scope of this -- I have used threads but you can do the same with processes as long as you can share the semaphore between them

#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

sem_t thereBeData;

void* readFromFifoSendToFile(void*) {

    FILE *fp = stdin;
    char buffer[100];
    FILE *file;

    file = fopen("file", "a+");

    while(1) {
       fscanf(fp, "%s", buffer);

       fprintf(file,"%s\n",buffer);
       fflush(file);

       sem_post(&thereBeData); // signal the consumer
    }
}

void* readFromFileAndPrint(void*) {
    FILE *fp = 0;
    char buffer[100];
    int counter = 0;

    while(1) {
       sem_wait(&thereBeData); // Waiting for the producer

       if (!fp) fp = fopen("file", "r");
       fscanf(fp, "%s", buffer);

       printf("%s\n", buffer);
    }    
}


int main(void)
{
    pthread_attr_t attr;
    pthread_t thread1;
    pthread_t thread2;

    sem_init(&thereBeData, 0,0);
    pthread_attr_init(&attr);    
    pthread_create(&thread1, &attr, readFromFifoSendToFile, (void*)0);
    pthread_create(&thread2, &attr, readFromFileAndPrint, (void*)0);

    sleep(10);
}
Soren
  • 14,402
  • 4
  • 41
  • 67