我用C语言编写程序,将一些数据输出到标准输出。我使用了printf
但我需要将数据保存到文件中,因此我将其更改为fprintf
。问题是,使用fprintf,数据的顺序错误,无关紧要,如果输出是stdout或文件。
if(...) {
out = fopen(param.F, "w");
} else {
out = stdout;
}
// some code here
fprintf(out, "a");
// more code
fprintf(out, "b");
....
如果这样,输出总是不同的。有时它是
ACB
有时它是
驾驶室
等...我尝试了setbuf和fflush的各种组合,但没有一个帮助过。
编辑:重要的是要知道,我在程序中使用了一些fork()
,但正如我之前提到的,使用printf时没有问题。
这是我的输出:
1:理发师:检查
2:客户1:已创建
3:客户1:进入
5:理发师:准备好了
6:客户1:准备好了
4:客户2:已创建
7:理发师:完成了
8:理发师:检查
9:客户2:进入
10:客户1:服务
11:理发师:准备好了12:客户2:准备好了
13:理发师:完成了 14:理发师:检查15:客户2:服务
应该按号码排序。该计划的结构如下:
int main() {
pid = fork();
if(pid == 0) {
// barber printfs
} else if (pid > 0) {
// customer printfs
}
}
答案 0 :(得分:2)
(无法发表评论,必须回答......)
不,不是printf / fprintf缓冲区不同,如果你做fprintf(stdout,...)或printf(....),FILE *对象是相同的。
有几个进程正在写入同一个文件,并且由于没有同步和每个进程中的不同缓冲,输出都搞砸了。
答案 1 :(得分:1)
printf和fprintf将有不同的设备驱动程序缓冲。
正如你所说你正在使用fork,并根据输出,我推断代码类似于
在这种情况下,由于写入按随机顺序发生,因此会产生不同的顺序,具体取决于每个子进程的调度时间。
最简单的解决方案是将应用程序包装在shell脚本中,然后通过tee运行二进制文件 - 这样您登录到stdout的所有内容也会转到文件中。
如果您需要更复杂的解决方案,则需要在进程之间设置IPC机制,并在父进程中执行所有写操作。
一种方法是在fork之前将stdout设置为管道(来自socketpair),并从父进程中的管道读取(使用select()以避免阻塞),然后登录到屏幕/文件。在使用freopen之前你需要dup()stdout以避免丢失它。我可能错过了一些事情,因为我有一段时间没有这样做。