Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 多线程和多处理时fprintf的行为如何?_C_Linux_Printf - Fatal编程技术网

C 多线程和多处理时fprintf的行为如何?

C 多线程和多处理时fprintf的行为如何?,c,linux,printf,C,Linux,Printf,这里是进程a和b,它们都是多线程的 aforksb和b立即执行一个新程序 adups和freopens存储到日志文件中(a实际上是apache的httpd2.22) b从a继承打开的stderr。(我正在改编ApacheHTTPD,b是我的程序,b使用fprintf(stderr…)进行日志记录 因此,a,b共享同一文件进行日志记录 a,b没有写入日志的锁定机制 我发现一些日志消息是交错的,有一点日志消息丢失了 同一文件的两个写入程序是否可以隐式地相互锁定 更重要的问题是:如果我们只在一个多线程

这里是进程
a
b
,它们都是多线程的

  • a
    forks
    b
    b
    立即执行一个新程序
  • a
    dup
    s和
    freopen
    s存储到日志文件中(
    a
    实际上是apache的httpd2.22)
  • b
    a
    继承打开的stderr。(我正在改编ApacheHTTPD,
    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 it自助使用这种方式进行日志记录:

    ......
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, ".........");
    
    C:为了方便起见,我用以下方式登录:

    fprintf(stderr,".....\n")
    

    我确信apache和我使用相同的fd来编写文件。

    如果您使用单个
    文件
    对象来对打开的文件执行输出,那么对该
    文件
    的整个
    fprintf
    调用将是原子的,即在
    fprintf
    调用期间对
    文件
    保持锁定。由于
    文件
    是单个进程地址空间的本地文件,因此此设置仅适用于多线程应用程序;它不适用于多进程设置,其中多个不同进程正在访问引用同一基础打开文件的单独
    文件
    对象。尽管您在这里使用的是
    fprintf
    ,但每个进程都有自己的
    文件
    ,它可以锁定和解锁,而其他进程看不到更改,因此写入操作最终可能会交错进行。有几种方法可以防止这种情况发生:

  • 在共享内存中分配一个同步对象(例如进程共享信号量或互斥量),并使每个进程在写入文件之前获得锁(因此一次只能写入一个进程);或

  • 使用文件系统级建议锁定,例如
    fcntl
    锁定或(非POSIX)BSD
    flock
    接口;或

  • 不要直接写入日志文件,而是写入另一个进程将传入日志文件的管道。只要写入管道的长度小于
    pipe\u BUF
    字节,就保证(POSIX)写入管道是原子的。在这种情况下,您不能使用
    fprintf
    (因为它可能执行多个底层写入操作),但您可以使用
    snprintf
    管道大小的缓冲区,然后是
    写入


  • 如果使用单个
    文件
    对象对打开的文件执行输出,则对该
    文件
    的整个
    fprintf
    调用将是原子的,即在
    fprintf
    调用期间,锁定
    文件
    。由于
    文件
    是单个进程地址空间的本地文件,因此此设置仅适用于多线程应用程序;它不适用于多进程设置,其中多个不同进程正在访问引用同一基础打开文件的单独
    文件
    对象。尽管您在这里使用的是
    fprintf
    ,但每个进程都有自己的
    文件
    ,它可以锁定和解锁,而其他进程看不到更改,因此写入操作最终可能会交错进行。有几种方法可以防止这种情况发生:

  • 在共享内存中分配一个同步对象(例如进程共享信号量或互斥量),并使每个进程在写入文件之前获得锁(因此一次只能写入一个进程);或

  • 使用文件系统级建议锁定,例如
    fcntl
    锁定或(非POSIX)BSD
    flock
    接口;或

  • 不要直接写入日志文件,而是写入另一个进程将传入日志文件的管道。只要写入管道的长度小于
    pipe\u BUF
    字节,就保证(POSIX)写入管道是原子的。在这种情况下,您不能使用
    fprintf
    (因为它可能执行多个底层写入操作),但您可以使用
    snprintf
    管道大小的缓冲区,然后是
    写入


  • 如果你发布实际的代码,而不是代码的描述,那会更好。这是一个很长的程序,我的fprintf分散在这里和那里。我会在apache2中找到将stderr复制到error.log的代码,然后将它们发布到这里。对不起,我的分数是因为这个原因被扣掉的吗?如果你发布实际代码,而不是代码的描述,那会更好。这是一个非常长的程序,我的fprintf分散在这里和那里。我会在apache2中找到将stderr复制到error.log的代码,然后将它们发布到这里。对不起,我的分数是因为这个原因被扣掉的吗?一个管道只能有一端用于写入,另一端用于读取。因此,一个管道只能在两个进程之间使用。如果我设置了一个专用的日志进程,然后有两个以上的进程用于工作,这些工作过程中的每一个都必须创建一个管道,然后通过该管道将log msg传递给日志记录过程。因此,这些管道是相互独立的,即使没有POSIX的保证,这些管道中的内容也不会被其他工作过程交错。记录过程的责任是保证从许多管道接收到的MSG不会交错------是吗