免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: ypxing
打印 上一主题 下一主题

[原创]标准I/O(buffered I/O)浅析 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-08-29 09:17 |只看该作者
用上面的说明解释蓝色键盘在CU的一篇帖子:

标题:高级测试,这段代码的输出是什么?
http://bbs.chinaunix.net/viewthread.php?tid=244249

请写出下面代码的输出,并说明为什么?


  1. #include <stdio.h>

  2. int main()
  3. {

  4.   printf("Hello");

  5.   fork();

  6.   return 0;

  7. }
复制代码



其实,这个问题只要了解三个方面的知识,就很好解释了
1. printf是基于标准I/O的,
字符串"Hello"被送到内核之前,是会放到标准I/O的缓冲区的,
而这个缓冲区是位于用户进程空间的.
2. fork()语句会把用户进程空间完整的复制一遍,生成子进程
的用户进程空间,这期中当然包括标准I/O的缓冲区,以及指向该
缓冲区的_IO_write_base, _IO_write_prt等指针.
3. 因为printf是向标准输出输出字符串,所以它用的是行缓冲.
行缓冲被flush的条件是:
(a) 一行结束(比如后面有"\n"),或者
(b) 缓冲区已满,或者
(c) 需要从内核读取数据
上面3个条件都不满足,所以在调用fork的时候,缓冲区并未被flush,
所以被一并拷给了子进程.

所以,上面的程序的输出会是父进程和子进程分别输出一次Hello

一旦将printf("Hello");换成printf("Hello\n");效果就不一样了
因为有了"\n",在fork之前,标准I/O的缓冲区就以及被flush了.

下面的代码打印了fork之后,缓冲区的内容


  1. #include <stdio.h>

  2. int main()
  3. {

  4.   printf("Hello");

  5.   fork();

  6.   printf("%d", stdout->_IO_write_ptr - stdout->_IO_write_base);
  7.   printf("%s", stdout->_IO_write_base);
  8.   return 0;

  9. }
复制代码

论坛徽章:
0
12 [报告]
发表于 2007-08-29 14:14 |只看该作者
ypxing真辛苦,赞一个,向你学习

论坛徽章:
0
13 [报告]
发表于 2007-08-29 17:35 |只看该作者
谢谢, 谢谢

原帖由 Sorehead 于 2007-8-29 14:14 发表
ypxing真辛苦,赞一个,向你学习

论坛徽章:
0
14 [报告]
发表于 2008-01-16 10:55 |只看该作者
先谢谢 再细看~~

论坛徽章:
0
15 [报告]
发表于 2008-01-19 15:37 |只看该作者
写的真不错,向你致敬!

论坛徽章:
0
16 [报告]
发表于 2008-01-22 16:57 |只看该作者
好帖!

不知有没有办法设置标准I/O里面那个缓冲区的大小呢?

论坛徽章:
0
17 [报告]
发表于 2008-01-22 21:37 |只看该作者
辛苦了

论坛徽章:
0
18 [报告]
发表于 2008-01-22 21:37 |只看该作者
原帖由 wcw 于 2008-1-22 16:57 发表
好帖!

不知有没有办法设置标准I/O里面那个缓冲区的大小呢?

man setvbuf

论坛徽章:
0
19 [报告]
发表于 2011-03-14 18:16 |只看该作者
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(void)
{
        char buf[3];
        FILE *myfile;
        myfile = fopen("test.txt", "r+");
        char *cur;
        char *cur1;

        printf("test.txt's fd = %d\n", myfile->_fileno);
        printf("offset = %d\n", lseek(myfile->_fileno, 0, SEEK_CUR));
        printf("**************\n");
        fgets(buf, 3, myfile);
        printf("offset = %d\n", lseek(myfile->_fileno, 0, SEEK_CUR));
        printf("read buffer base  %p\n", myfile->_IO_read_base);
        printf("read buffer end %p\n", myfile->_IO_read_end);
        printf("read buffer ptr %p\n", myfile->_IO_read_ptr);
        printf("write buffer base  %p\n", myfile->_IO_write_base);
        printf("write buffer end %p\n", myfile->_IO_write_end);
        cur = myfile->_IO_read_base;
        while(cur < myfile->_IO_read_end)
        {
                printf("%c", *cur);
                cur++;
        }
        printf("**************\n");
        fputs("1", myfile);
        printf("offset = %d\n", lseek(myfile->_fileno, 0, SEEK_CUR));
        printf("read buffer base  %p\n", myfile->_IO_read_base);
        printf("read buffer end %p\n", myfile->_IO_read_end);
        printf("read buffer ptr %p\n", myfile->_IO_read_ptr);
        printf("write buffer base  %p\n", myfile->_IO_write_base);
        printf("write buffer ptr %p\n", myfile->_IO_write_ptr);
        cur1 = myfile->_IO_write_base;
        while(cur1 < myfile->_IO_write_ptr)
        {
                printf("%c", *cur1);
                cur1++;
        }
        printf("**************\n");
        fgets(buf, 3, myfile);
        printf("offset = %d\n", lseek(myfile->_fileno, 0, SEEK_CUR));
        //while(1);
        printf("read buffer base  %p\n", myfile->_IO_read_base);
        printf("read buffer end %p\n", myfile->_IO_read_end);
        printf("read buffer ptr %p\n", myfile->_IO_read_ptr);
        printf("write buffer base  %p\n", myfile->_IO_write_base);
        printf("write buffer ptr %p\n", myfile->_IO_write_ptr);
        cur = myfile->_IO_read_base;
        while(cur < myfile->_IO_read_end)
        {
                printf("%c", *cur);
                cur++;
        }
        printf("**************\n");

        return 0;
}
***************************************************************************************************************************
test.txt的内容为
abcdefg

***************************************************************************************************************************
root@localhost#./test
test.txt's fd = 3
offset = 0
**************
offset = 8
read buffer base  0xb7fb3000
read buffer end 0xb7fb3008
read buffer ptr 0xb7fb3002
write buffer base  0xb7fb3000
write buffer end 0xb7fb3000
abcdefg
**************
offset = 8
read buffer base  0xb7fb3008
read buffer end 0xb7fb3008
read buffer ptr 0xb7fb3008
write buffer base  0xb7fb3002
write buffer ptr 0xb7fb3003
1**************
offset = 8
read buffer base  0xb7fb3000
read buffer end 0xb7fb3005
read buffer ptr 0xb7fb3002
write buffer base  0xb7fb3000
write buffer ptr 0xb7fb3000
defg
**************


***************************************************************************************************************************
test.txt的内容为
ab1defg

***************************************************************************************************************************
问题:
1对于以可读可写方式打开的文件,输入和输出使用的相同的缓冲区。fgets之后进行fputs,为什么_IO_write_base被设为_IO_read_ptr原先的值。
2.offset = 8,fputs是如何将1写到c的位置上的。文件表里好像只有offset一个控制偏移的变量。

论坛徽章:
0
20 [报告]
发表于 2011-03-14 18:17 |只看该作者
++++++++++++++++++++++++++++++++++++++++++
test.txt的内容为
abc
123
+++++++++++++++++++++++++++++++++++++++++++
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(void)
{
        char buf[30];
        char buf2[3];
        FILE *myfile;
        myfile = fopen("test.txt", "r");
        char *cur;
        setvbuf(myfile, buf, _IOLBF, 30);
        fgets(buf2, 3, myfile);
        printf("read buffer base  %p\n", myfile->_IO_read_base);
        printf("read buffer end %p\n", myfile->_IO_read_end);       
        printf("read buffer ptr %p\n", myfile->_IO_read_ptr);
        cur = myfile->_IO_read_base;
        while(cur < myfile->_IO_read_end)
        {
                printf("%c", *cur);
                cur++;
        }
}
+++++++++++++++++++++++++++++++++++++++++++
输出为
read buffer base  0xbfaf9f7e
read buffer end 0xbfaf9f86
read buffer ptr 0xbfaf9f80
abc
123
+++++++++++++++++++++++++++++++++++++++++++
问题
我已经将myfile设为行缓冲,为什么读的时候仍旧读出了全部内容,而非一行。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP