You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fork进程代码重定向输出时重复打印内容的问题求解

解决父子进程中printf输出重定向重复的问题

问题场景

我编写了一段基于mmap实现父子进程共享内存的C代码:

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>


int main(){
    int sum = 6;
    int *p = (int*) mmap(NULL, sizeof (int) , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *p = 7;
    printf("filled %d in memory\n", *p);
    int pID = fork();
    if (pID == 0){
        printf(" found %d\n", *p);
        printf(" sum inside %d\n",sum + (*p));
        exit(0);
    }
    else if (pID> 0){
        wait(NULL);
        printf("sum %d\n",sum+ *p);
        printf("exit\n");
        exit(0);
    }
    return 0;
}

直接在终端运行时输出正常:

filled 7 in memory
 found 7
 sum inside 13
sum 13
exit

但执行./a.out > output.txt将输出重定向到文件时,filled 7 in memory会被重复打印,文件内容如下:

filled 7 in memory
 found 7
 sum inside 13
filled 7 in memory //**printed twice
sum 13
exit

问题原因

这是标准输出的缓冲机制差异导致的:

  • 当标准输出指向终端时,默认是行缓冲模式,printf中的换行符会触发缓冲区立即刷新,内容直接输出到终端。
  • 当标准输出被重定向到文件时,默认是全缓冲模式,printf的内容会先暂存在缓冲区中,还没来得及写入文件就执行了fork()。此时子进程会完整复制父进程的地址空间,包括未刷新的输出缓冲区。
  • 后续父子进程退出时,都会各自刷新缓冲区,导致同一句内容被打印两次。

解决方法

方法1:fork前手动刷新缓冲区

在调用fork()之前,执行fflush(stdout)强制刷新标准输出缓冲区,确保内容已经写入文件,避免被子进程复制:

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>


int main(){
    int sum = 6;
    int *p = (int*) mmap(NULL, sizeof (int) , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *p = 7;
    printf("filled %d in memory\n", *p);
    fflush(stdout); // 强制刷新缓冲区
    int pID = fork();
    if (pID == 0){
        printf(" found %d\n", *p);
        printf(" sum inside %d\n",sum + (*p));
        exit(0);
    }
    else if (pID> 0){
        wait(NULL);
        printf("sum %d\n",sum+ *p);
        printf("exit\n");
        exit(0);
    }
    return 0;
}

方法2:禁用标准输出缓冲

在程序开头调用setvbuf(stdout, NULL, _IONBF, 0),将标准输出设置为无缓冲模式,这样每次printf都会直接输出内容,不会暂存到缓冲区:

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>


int main(){
    setvbuf(stdout, NULL, _IONBF, 0); // 设置无缓冲
    int sum = 6;
    int *p = (int*) mmap(NULL, sizeof (int) , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *p = 7;
    printf("filled %d in memory\n", *p);
    int pID = fork();
    if (pID == 0){
        printf(" found %d\n", *p);
        printf(" sum inside %d\n",sum + (*p));
        exit(0);
    }
    else if (pID> 0){
        wait(NULL);
        printf("sum %d\n",sum+ *p);
        printf("exit\n");
        exit(0);
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者fatihbulbul1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:45:55