linux系统下的Buffer

本文深入探讨了Linux系统中的缓存机制,包括non-buffering、line-buffering和full-buffering三种类型,并通过具体示例展示了不同缓存机制下数据写入的行为差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

write, fwrite,printf等它们都会与buffer有关,有时向日志中写data,第二天发现data没有保存完整,出现这个问题,都是buffering的问题,下面从linux系统来分析buffering。

buffering种类

  • non-buffering
    无缓存,写入数据立即写入
  • line-buffering
    遇到newline,即换行符时写入
  • full-buffering
    buffer没有写满,或没有强制,都不会立即写入的

栗子(line-buffering)

 25 int globvar = 6;
 26 char buf[] = " a write to stdout\n";
262     int var;
263     pid_t pid;
264      int main() {
265     var = 88;
266     if (write(STDOUT_FILENO, buf, strlen(buf)) != strlen(buf)) {                                               
268         printf("write error\n");
269         exit(1);
270     }
271     printf("before fork\n");
272      
273     if ((pid = fork()) < 0){
274         printf("fork error\n");
275         exit(2);
276     } else if (pid == 0) {
277         globvar++;
278         var++;
279     }else {
280         sleep(2);
281     }
282     printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
283     exit(0);
}

交互执行:
jack@jxes-VirtualBox:~/samba_share/apue$ gcc test.c
jack@jxes-VirtualBox:~/samba_share/apue$ ./a.out 
 a write to stdout
before fork
pid = 24650, glob = 7, var = 89
pid = 24649, glob = 6, var = 88

重定位:
jack@jxes-VirtualBox:~/samba_share/apue$ ./a.out > tm.txt
jack@jxes-VirtualBox:~/samba_share/apue$ ls
a.out  apue.3e  apue.h  in.txt  test.c  testjmp.c  tm.txt
jack@jxes-VirtualBox:~/samba_share/apue$ cat tm.txt 
 a write to stdout
before fork
pid = 24658, glob = 7, var = 89
before fork
pid = 24657, glob = 6, var = 88

上面栗子中,如果将执行结果redirect到文件中,before fork会被输出两次。这就是因为在fork之前,printf到buffer里的内容交没有立即写入,因为此时被重定向到文件中去了,而不是标准输出stdout,所以这时,before fork还在memory中,当执行fork时会把parent的data space中的内容copy给child process,自然也就连同存在里面的before fork一些被copy给child process了,这也就是在parent和child process中都会被输出的原因。

而直接以交互方式输出时,由于第一种方式是直接输出到stdout,是line-buffering方式,即遇到换行符”\n”时,内容就被写入,如果没有”\n”,情况就会与重定向一致,修改下代码如下:

.......
271     printf("before fork"); //去掉\n
272      
273     if ((pid = fork()) < 0){

........

jack@jxes-VirtualBox:~/samba_share/apue$ gcc test.c
jack@jxes-VirtualBox:~/samba_share/apue$ ./a.out 
 a write to stdout
before forkpid = 24925, glob = 7, var = 89
before forkpid = 24924, glob = 6, var = 88

切记

平时在写文件时,一定要记得把内容写入,比如写文件时,通常用fflush。
另外,分配内存空间时主要区分上面三种类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JXES智能生态系统

如文章对你有用,请作者喝个咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值