我正在寻找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);
}
}
答案 0 :(得分:2)
您的主要问题似乎与信号量如何工作的概念有关。信号量最好被视为生产者和消费者之间的信号。当制作人做了一些事情时,他们会在信号量上发布信号,消费者会等待信号量,直到制作人发出信号。
因此,在您的情况下,消费者和生产者之间应该只有一个信号量 - 他们应该共享此信号量以进行同步。此外,信号量应从零开始,因为尚未生成任何内容。每次生产者发布到信号量时,值将增加1,当消费者等待信号量时,消费者将在值为零时休眠,直到生产者帖子和值增加并变为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);
}