• unbuffered low level IO 和 bufferd IO


      在常见的IO函数中有这样的一些系列,open, read, write, lseek及close。这些IO函数经常被称为不带缓冲的I/O(unbuffered I/O),不带缓冲的是什么意思呢?术语不带缓冲指的是每个read和write都调用了内核的一个系统调用。这些函数在调用的时候系统调用直接进行了磁盘文件的写入操作。那么你会发现如果我的程序出现这样的需求,有很多个连续的对同一个文件进行I/O的操作,你的程序将会不断地进行磁盘操作,这将会是一件很可怕的事情,程序运行的会异常的慢,怎么解决呢?很简单,缓冲呗,我想缓冲这个名词在计算机的世界里你不陌生吧?

      所谓的缓冲是指在你对文件进行读取或者改写的时候,系统会为你申请一块内存空间,之后的所有操作都是在此内存空间上面进行操作,当你对该文件的操作结束的时候,或者关闭该文件的句柄的时候,或者你有意刷新缓冲区的时候,系统会将缓冲区的内容一并写至磁盘。这样对比一下之前的unbufferd I/O,磁盘操作相比内存操作要慢得多(你应该知道吧?),所以也称之为高级I/O。那么你可能会问,带缓冲的IO API有哪些呢?罗列一下常见的大概有这些:fopen, fread, fwrite, fclose。这些是标准I/O,也就是在<stdio.h>中声明的API,而上面的那些open...这些是在<unistd.h>下声明的。这下你应该知道STDIN和STDIN_FILENO的区别了吧。层次不一样嘛,一个是unbuffered的,一个是buffered的。(低级与高级的)由于不带缓冲的I/O函数已经不是ISO C的组成部分,所以不建议使用该类函数。

      下面是一个有意思的程序,用于测试缓冲I/O和非缓冲I/O的函数区别的。

    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    int main(){
    	int a=8;
    	int b=1;
    	char p_str[]={"write to stdout\n"};
    	pid_t pid;
    	write(STDOUT_FILENO,p_str,sizeof(p_str)-1);
           printf("before fork!\n");
    //	fflush(stdout);	
    	if(pid=fork()==0){
    		a++;
    		b++;
    	}else{
    		sleep(2);	
    	}
    	printf("pid %d :a = %d; b = %d\n",getpid(),a,b);
    	return 0;
    }
    

    在本机器上直接编译运行

    输出如下:

    write to stdout

    before fork!

    pid 22040: a=9;b=2

    pid 22039: a=9;b=1

    如果我将程序的输出重定向到另一个临时文件的话,结果的输入又将如下:

    write to stdout

    before fork!

    pid 22045: a=9;b=2

    before fork!

    pid 22044: a=8;b=1

    解释如下:

    1 write是unbuffered,所以在执行fork时,已经输出到stdout中了。

    直接执行时,stdout和interactive terminal相连接,所以是line buffered。Printf执行后,就被输出到stdout中了。因为字符串以换行符结束。

    输出重定向执行时,stdout被重定向为文件temp.out。所以是fully bufferedPrintf执行后,并没有输出到stdout中。后面执行了fork,输出缓冲区也被拷贝到了child中。在parentchild中,再执行printf时,实际是向输出缓冲区追加内容。当parentchild结束时,输出缓冲区的内容被flush

    至于如何将测试二的输出和测试一的结果一样,我想你应该能够想的到。

    这让我想起来陈皓老师的一篇文章大家可以参考一下,一道面试题哟。http://coolshell.cn/articles/7965.html

  • 相关阅读:
    Windows搭建SkyWalking8.3环境进行JAVA应用性能监控及入门示例(使用Mysql持久化)
    使用JMeter进行压力测试
    IDEA2020.1使用LeetCode插件运行并调试本地样例
    centos7使用Minikube“快速搭建“出Kubernetes本地实验环境(踩坑集锦及解决方案)
    事务的隔离级别与所带来的问题
    深入理解HashMap第一篇
    LoadRunner 与浏览器兼容性
    互联网产品接入支付功能如何测试?
    基于AMF协议的Flex应用程序的性能测试
    centos+mono+nginx+jexus 搭建linux下c#运行环境测试
  • 原文地址:https://www.cnblogs.com/fxplove/p/2678108.html
Copyright © 2020-2023  润新知