如何在 Linux 上使用标准 I/O 函数在多个进程中写入文件?
Posted
技术标签:
【中文标题】如何在 Linux 上使用标准 I/O 函数在多个进程中写入文件?【英文标题】:How to write a file in multiple processes using standard I/O functions on Linux? 【发布时间】:2013-04-15 15:22:43 【问题描述】:我正在开发一项功能,该功能需要在多个进程中编写单个日志文件(由其路径标识)。以前,每个进程都会调用printf
在终端(标准输出)上流式传输日志。现在我需要将输出目标更改为文件。所以我尝试使用freopen
将标准输出重定向到每个进程中的文件。
freopen(file_path, "a", stdout); //
但似乎效果不佳。缺少一些日志。 实现这一目标的常见做法是什么?
顺便说一句,在我们的要求中,应该允许用户在文件和标准输出之间切换日志记录目标,因此当切换回终端时,第一个参数“file_path”可以是 tty。可以拨打freopen(tty, "a", stdout)
吗?
【问题讨论】:
使用syslog()
api怎么样?
我们将此 API 用于其他日志类型..
然后实现自己的syslog;这很简单。 Easy 进程通过套接字对将字符串写入日志/主进程,该进程选择并读取字符串,依次将每个字符串写入日志。在主进程中调整设置会同时重定向所有子进程的日志记录。希望您已经有了一些 I/O 包装器。
只需使用包装脚本启动您的程序,该脚本将所有输出通过管道传输到文件:$ program >logfile 2>errorfile
用户希望看到它的内容来自tail -f logfile
帮助。
如果同时访问该文件,请记住需要锁定它以不混淆不同的日志条目,并遵循此需要,潜在的性能问题。
【参考方案1】:
你有很多选择:
1) 最简单的方法是让每个进程简单地独立写入同一个日志。当然,问题是如果任何两个进程同时写入不同的消息,文件就会被打乱。
2) 您可以改为让进程将消息发送到一个“主记录器”,然后它会按照收到的顺序一次输出一条消息。 “主记录器”可能使用套接字。如果所有进程都在同一台主机上,您可能会改用消息队列或命名管道。
3) 更简单的是,您可以使用系统范围的信号量来确保一次只写入一条消息。
4) 另一种方法是使用开源记录器,例如 log4j 或 syslog-ng
【讨论】:
【参考方案2】:在 O_APPEND 模式下写入将执行您想要的操作 as long as they are less than PIPE_BUF bytes,这通常有足够的空间(大约 4k)。
因此,将新的 freopen()ed 文件设置为行缓冲(下面的_IOLBF),然后确保您的写入包含换行符以刷新缓冲区:
freopen(file_path, "a", stdout);
setvbuf(stdout, (char *)NULL, _IOLBF, 0); // a.k.a. setlinebuf(stdout) under BSD
...
printf("Some log line\n"); // Note the newline!
【讨论】:
请注意,这取决于所讨论的文件系统是否正确支持 O_APPEND 模式,而某些文件系统(例如某些版本的 NFS)不支持。理想情况下,在这种情况下,打开应该会失败,但通常会成功,同时写入会导致损坏。 或直接拨打fflush()
。【参考方案3】:
使用fprintf
将您的输出传送到称为输出的文件句柄。由于文件句柄只是指针,只需设置output = stdout
或output = yourFile
。然后每个fprintf(output, "sometext")
最终都会走到当前设置该句柄的任何地方。您甚至可以拥有一个根据用户输入动态重定向输出的功能。
【讨论】:
以上是关于如何在 Linux 上使用标准 I/O 函数在多个进程中写入文件?的主要内容,如果未能解决你的问题,请参考以下文章