这是进程ab,它们都是多线程的。

  • a fork bb立即执行一个新程序;
  • a dupfreopen的stderr到日志文件(a是事实上的apache的httpd2.22)
  • ba继承了打开的stderr。 (我正在修改apache httpd,b是我的程序),b使用fprintf(stderr....)记录
  • ,因此ab共享同一文件以记录
  • 没有针对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/

    10-12 05:55