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);
}
我正在 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);
}