这是进程a
和b
,它们都是多线程的。
a
fork b
和b
立即执行一个新程序; a
dup
和freopen
的stderr到日志文件(a
是事实上的apache的httpd2.22)b
从a
继承了打开的stderr。 (我正在修改apache httpd,b
是我的程序),b
使用fprintf(stderr....)
记录a
和b
共享同一文件以记录a
的锁定机制,b
写入日志我发现某些日志消息正在交织,有些日志消息丢失了。
两位作家可以同一个文件隐式地互相锁定吗?
更为重要的问题是:如果我们仅在一个多线程进程中使用
fprintf
,那么fprintf
是线程安全的,也就是说,一个fprintf
调用不会干预另一个线程中的另一个fprintf
调用吗?很多文章都这样说,但是要确保自己不容易,所以我在这里寻求帮助。答:复制fd的代码如下:
......
rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);//dup the stderr to the logfile
apr_file_close(s_main->error_log);//here ,2 fd point to the same file description,so close one of
然后
B:apache自己使用这种方式进行日志记录:
......
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, ".........");
C:为方便起见,我以这种方式登录:
fprintf(stderr,".....\n")
我很确定apache和我使用相同的fd进行文件写入。
最佳答案
如果您使用单个FILE
对象在打开的文件上执行输出,则对该fprintf
的整个FILE
调用将是原子的,即在FILE
调用期间对fprintf
持有锁定。由于FILE
在单个进程的地址空间中是本地的,因此只能在多线程应用程序中进行此设置。它不适用于多进程设置,在多进程设置中,几个不同的进程正在访问引用同一个基础打开文件的单独FILE
对象。即使您在此处使用fprintf
,每个进程都有其自己的FILE
,可以锁定和解锁这些进程而其他进程看不到更改,因此写操作最终可能会交错。有几种方法可以防止这种情况的发生:
fcntl
锁或(非POSIX)BSD flock
接口(interface);或PIPE_BUF
字节长,就保证(通过POSIX)对管道的写入是原子的。在这种情况下,您不能使用fprintf
(因为它可能执行多个基础写操作),但是您可以在snprintf
大小的缓冲区中使用PIPE_BUF
,然后再使用write
。 关于c - 多线程多处理时fprintf的行为如何?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11664434/