Linux 信号量

Linux semaphores

我正在 Linux 寻求有关同步问题的帮助。我是新手,我想我不太了解如何使用信号量进行同步。我的任务是同步两个访问文件的进程——一个从另一个进程的 fifo 读取,写入这个文件,然后另一个读取。我知道我的代码缺少同步,但我不知道该怎么做。

代码:

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);
         }
    }

您的主要问题似乎与信号量的工作原理有关。最好将信号量视为生产者和消费者之间的信号。当生产者完成某事时,他们 post 信号量上的信号,消费者将等待信号量,直到生产者 post 信号量。

所以在您的情况下,消费者和生产者之间应该只有一个信号量——他们应该共享这个信号量以进行同步。此外,信号量应从零值开始,因为尚未产生任何信号量。生产者post每次给信号量值都会加1,等待信号量的消费者如果值为0就会休眠,直到生产者post和这个值增加并成为一个。如果生产者比消费者快得多,信号量的值可以上升并大于 1,这很好,只要消费者消耗与生产者生产它们相同大小的单位的输出。

这里是一个工作示例,但没有任何错误处理——添加错误处理超出了本文的范围——我使用了线程,但你也可以使用只要你可以在它们之间共享信号量就可以处理进程

#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);
}