c - 生产者-消费者问题的无限循环

标签 c fork producer-consumer

我试图更好地理解 c 编程中的 fork() 和并发性。我是一个新手,我很难理解其中的逻辑。我尝试使用 fork() 制作一个简单的生产者-消费者程序。基本上,一个 Producer() 函数应该从 stdin 中获取一个字符,并将其写入文件。与此同时,第二个进程运行消费者代码,该代码应该读取文件中的最后一个字符并将其回显到屏幕上。 Producer() 和consumer() 函数本身运行良好,即它们正在执行各自应该执行的操作,但问题在于并发性。这是我的代码:

#include<stdio.h>
#include <stdlib.h>
#include <unistd.h>

FILE* fp;
//char c;

void producer(){
        char c=' ';
        while(c!='x'){
                puts("enter a char");
                c = getchar();

                while((fp = fopen("shared.txt", "at"))==NULL); //while the file is in use by another program

                fputc(c,fp);

                if(c!='\n')puts("file written to successfully");
                fclose(fp);
        }
        return;
}

char readChar(){
        char c;
        while((fp = fopen("shared.txt", "rt"))==NULL);
        fseek(fp, -1, SEEK_END);
        c = fgetc(fp);
        fclose(fp);
        return c;
}

void consumer(){
        char c;
        do{
                c = readChar();
                printf("This is the latest character supplied: %c\n", c);
        }while(c!='x');

}

int main(){
        int pid = fork(); //now we fork processes

        if(pid ==0 ){
                producer();  //the child process should run and create some text in the file
        }else{
                wait(); consumer(); 
        }
}

我尝试在各自分支中调用 Producer() consumer() 之后添加等待语句,但基本上无论如何,程序都无法执行我想要的是 。如果在 main () 中我有

int main(){
        int pid = fork(); //now we fork processes

        if(pid ==0 ){
                producer();   //the child process should run and create some text in the file
        }else{
                consumer(); 
        }
}

我陷入了无限循环。在一个或两个分支中的函数调用之后添加 wait(); 没有帮助,因为无限循环发生在控制传递给任一 wait() 之前。

如果我尝试这个:

int main(){
        int pid = fork(); //now we fork processes

        if(pid ==0 ){
                producer();   //the child process should run and create some text in the file
        }else{
               wait(); consumer(); 
        }
}

我可以从 stdin 输入文本,直到输入 'x',但随后正如预期的那样,消费者仅读取写入文件的最后一个字符。

有没有办法让它与等待语句一起使用?

最佳答案

the problem is in the concurrency

我想说问题在于(缺乏)同步。在生产者/消费者安排中,生产者通常有一种方法向消费者发出信号,表明有新项目可供消费,而消费者在尝试消费之前会等待该信号。详细信息与此有所不同,但它们通常还包括生产者向消费者发出信号,表示不会再有更多商品的方式。

您的消费者不会等待任何显式信号,并且不会使用可用的数据(文件长度)来确定新项目可用。另一方面,它不努力在消费的元素中保持自己的位置,因此如果生产者领先于它,它很容易错过元素。此外,消费者忙循环,执行昂贵的 I/O 操作,这是一种非常昂贵的方法。

Is there a way to get this to work with wait statements?

仅当您希望生产者在消费者消费任何东西之前运行完成。这就是 wait() 的作用:它等待另一个进程终止。在这种情况下,您可能希望消费者从头开始逐个字符地读取文件,而不是直接跳到末尾。

如果您希望生产者和消费者同时取得进展,那么最简单的方法是利用系统已经提供给您的设施,使用 FIFO 或管道而不是常规文件。然后,生产者可以一个接一个字符地写入,而消费者可以一个接一个字符地读取,而不需要任何重新打开和重新定位的废话。

如果您必须使用常规文件来执行此操作,那么您可以使用一对信号量或互斥体+条件变量来使生产者和消费者轮流。或者,消费者可以通过多种方式监视文件以检测文件何时发生更改(stat/fstatinotify 等)为了避免不必要地尝试读取它,您可以将其与它跟踪其在该文件中的位置结合起来,以免重新读取它已经消耗的数据。理想情况下,两个程序都不会多次打开文件,但生产者可能需要在每次写入后fflush

关于c - 生产者-消费者问题的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55923283/

相关文章:

char ** 数组 c 文件输入 pgm

c - 函数原型(prototype)中的函数声明(需要帮助)

c - C Pipe 中的 Unix Shell 问题

在 C 中通过 fork() 创建子进程

c# - 批量处理ConcurrentBag中的所有项目

c - 这两种代码有什么区别?我不知道,即使他们输出不同的值

c++ - 如何使 boost asio 前叉安全

java - 生产者消费者没有给出期望的结果

c++ - boost::strand 生产者/消费者有意义吗?

c - 为什么在 C 中使用错误的格式说明符会使我的程序在 Windows 7 上崩溃?