重定向对格式化IO(printf)行缓冲的影响
来源:互联网 发布:我的世界js物品攻击力 编辑:程序博客网 时间:2024/04/30 03:19
今天在看APUE3进程章节的fork函数的时候,有一个例程中使用了格式化IO函数(printf),在输出到终端的时候只输出一次,但重定向到某个文件时,却由于子进程及缓冲更改的关系输出了两次。具体代码如下:
#include "apue.h"int globvar = 6; /* external variable in initialized data */char buf[] = "a write to stdout\n";int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) err_sys("write error"); printf("before fork\n"); /* we don't flush stdout */ if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { /* child */ globvar++; /* modify variables */ var++; } else { sleep(2); /* parent */ } printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); exit(0);}
输出如下:
sahpah:~/apue.3e/proc$ ./fork1
a write to stdout
before fork
pid = 14761, glob = 7, var = 89
pid = 14760, glob = 6, var = 88
sahpah:~/apue.3e/proc$ ./fork1 > h
sahpah:~/apue.3e/proc$ cat h
a write to stdout
before fork
pid = 15649, glob = 7, var = 89
before fork
pid = 15648, glob = 6, var = 88
这是由于在Linux下,默认符合如下缓冲特征:
- 当且仅当标准输入和标准输出并不指向交互式设备时,它们才是全缓冲的。
- 标准错误决不会是全缓冲的。
因此,在标准输出直接输出到终端时,它是行缓冲的,由换行符冲洗。
所以,在fork之前第一个个printf函数由换行符将缓冲区冲洗完,仅打印一次“before fork”。
printf("before fork\n");
当使用“./fork1 > h”重定向到h文件时,使用的是全缓冲,fork前的printf缓冲区中的数据并不会被冲洗,而fork出来的子进程获得了父进程数据空间、堆和栈的副本,所以子进程也继承了父进程缓冲区中的数据,即父进程和子进程都有了该行的缓冲区,随后第二个printf将数据追加到该缓冲区中,exit函数在退出前将各自的缓冲区进行冲洗,于是打印了两次“before fork”。
修改方法:
1.在第一个printf后使用fflush函数强制对标准输出流进行冲洗:
#include "apue.h"int globvar = 6; /* external variable in initialized data */char buf[] = "a write to stdout\n";int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) err_sys("write error"); printf("before fork\n"); /* we don't flush stdout */ fflush(stdout); //force flush if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { /* child */ globvar++; /* modify variables */ var++; } else { sleep(2); /* parent */ } printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); exit(0);}
进行强制冲洗后输出如下:
sahpah:~/apue.3e/proc$ ./fork1
a write to stdout
before fork
pid = 14761, glob = 7, var = 89
pid = 14760, glob = 6, var = 88
sahpah:~/apue.3e/proc$ ./fork1 > h
sahpah:~/apue.3e/proc$ cat h
a write to stdout
before fork
pid = 15649, glob = 7, var = 89
pid = 15648, glob = 6, var = 88
a write to stdout
before fork
pid = 14761, glob = 7, var = 89
pid = 14760, glob = 6, var = 88
sahpah:~/apue.3e/proc$ ./fork1 > h
sahpah:~/apue.3e/proc$ cat h
a write to stdout
before fork
pid = 15649, glob = 7, var = 89
pid = 15648, glob = 6, var = 88
2.使用setvbuf设置标准输出流的缓冲类型:
#include "apue.h"int globvar = 6; /* external variable in initialized data */char buf[] = "a write to stdout\n";int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; setvbuf(stdout, NULL, _IOLBF, 0);//set buffer if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) err_sys("write error"); printf("before fork\n"); /* we don't flush stdout */ if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid == 0) { /* child */ globvar++; /* modify variables */ var++; } else { sleep(2); /* parent */ } printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); exit(0);}
setvbuf将stdout流类型重设置为行缓冲,但其缓冲区由我们指定,此处指向NULL,则标准IO库自动为该流分配适当长度的缓冲区。当数据超过缓冲区长度时,缓冲区则被冲洗,而此处缓冲区长度设置为0,故每个接收的数据都立即被冲洗。
输出如下:
sahpah:~/apue.3e/proc$ ./fork1
a write to stdout
before fork
pid = 43680, glob = 7, var = 89
pid = 43679, glob = 6, var = 88
sahpah:~/apue.3e/proc$ ./fork1 > h
sahpah:~/apue.3e/proc$ cat h
a write to stdout
before fork
pid = 43682, glob = 7, var = 89
pid = 43681, glob = 6, var = 88
a write to stdout
before fork
pid = 43680, glob = 7, var = 89
pid = 43679, glob = 6, var = 88
sahpah:~/apue.3e/proc$ ./fork1 > h
sahpah:~/apue.3e/proc$ cat h
a write to stdout
before fork
pid = 43682, glob = 7, var = 89
pid = 43681, glob = 6, var = 88
0 0
- 重定向对格式化IO(printf)行缓冲的影响
- IO缓冲对fork的影响
- STM32 printf的重定向
- stm32的printf重定向
- linux下fork()函数在行缓冲和全缓冲情况下对IO的影响
- 标准IO重定向到文件非交互式设备时的缓冲策略
- 重定向输出遇到的缓冲问题
- 重定向输出遇到的缓冲问题 .
- windows下printf重定向的实现
- windows下printf重定向的实现
- printf的重定向与恢复
- printf 的串口输入重定向
- printf重定向后的Log机制
- STM32的printf函数重定向
- STM32的printf函数重定向
- 自动转向技术(Auto-Redirecting)及301重定向对SEO的影响 实现方法(整理修改)
- STM32 printf重定向
- cin/printf 重定向
- 录像程序
- 【14/9/11】Set集合
- Ranorex 5.1发布,支持移动Web测试
- erlang试题
- 面试题17 合并两个排序的链表
- 重定向对格式化IO(printf)行缓冲的影响
- IIS7配置PHP环境图文教程(fastcgi快速最新版)
- 栈和递归之Hanoi塔
- Android 模拟器genymotion安装,eclipse 插件
- xor异或逻辑操作(辅助完成图形的叠加)
- 实践:Mysql 5.5.15升级到Mysql5.6.19
- top ten vps
- 推荐一个directui介绍的文章
- C语言几个经典的算法