下面是过程a和b,这两者都是多线程的.
a叉子b和b立即执行一个新程序;a dups和freopens stderr到日志文件(a是defacto apache的httpd2.22)b继承了打开的stderr a.(我适应apache httpd的,b是我的程序),并b使用fprintf(stderr....)了日志记录a,b共享同一个文件进行日志记录a,b写日志我发现一些log msg是交错的,并且有一点log msg丢失了.
同一个文件中的两个编写者是否可以隐含地互相锁定?
更重要的问题是:如果我们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
Run Code Online (Sandbox Code Playgroud)
然后
B:apache它自己用这种方式记录:
......
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, ".........");
Run Code Online (Sandbox Code Playgroud)
C:为方便起见,我以这种方式登录:
fprintf(stderr,".....\n")
Run Code Online (Sandbox Code Playgroud)
我很确定apache和我使用相同的fd进行文件编写.
如果您使用单个FILE对象在打开的文件上执行输出,那么对它的整个fprintf调用FILE将是原子的,即FILE在fprintf调用期间保持锁定.由于a FILE是单个进程的地址空间的本地空间,因此只能在多线程应用程序中进行此设置.它不适用于多进程设置,其中几个不同的进程正在访问FILE引用相同底层打开文件的单独对象.即使您在fprintf这里使用,每个进程都有自己的进程FILE可以锁定和解锁,而其他进程看不到更改,因此写入最终会交错.有几种方法可以防止这种情况发生:
在共享内存中分配同步对象(例如,进程共享信号量或互斥锁),并使每个进程在写入文件之前获取锁(因此一次只能写入一个进程); 要么
使用文件系统级顾问锁定,例如fcntl锁或(非POSIX)BSD flock接口; 要么
而不是直接写入日志文件,写入另一个进程将提供给日志文件的管道.只要长度小于PIPE_BUF字节,保证(通过POSIX)对管道的写入是原子的.fprintf在这种情况下你不能使用(因为它可能执行多个底层写操作),但你可以使用后跟snprintf的PIPE_BUF-sized缓冲区write.