精华内容
下载资源
问答
  • IO缓冲区(buffer)的原理及作用

    千次阅读 2019-03-11 16:42:51
    现在的外设控制器都有自己的缓冲池,如磁盘和网卡,通过缓冲IO的方式读取时,如BufferedInputStream里就有个buf块,CPU可把外设里的缓冲池available的字节块整块读入该buf内存。 以下是分别是利用缓冲区进行读写和...

    缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似于数据库的批量操作,这样大大提高高了数据的读写速率。

    现在的外设控制器都有自己的缓冲池,如磁盘和网卡,通过缓冲IO的方式读取时,如BufferedInputStream里就有个buf块,CPU可把外设里的缓冲池available的字节块整块读入该buf内存。

    以下是分别是利用缓冲区进行读写和复制操作的使用代码


    import java.io.*;
    //缓冲区为了提高流的操作效率,所以在创建缓冲区之前必须先有流对象
    public class Bufwritered {
    public static void main(String[] args){
    //创建一个字符写入流对象
    FileWriter fw;
    BufferedWriter bufw = null;
    try{
    fw = new FileWriter("buf.txt");
    bufw = new BufferedWriter(fw);
    bufw.write("abcde");
    bufw.newLine();//缓冲区提供的换行符
    }
    catch(IOException e){
    throw new RuntimeException("读写失败");
    }
    finally{
    if(bufw!=null)
    try{
    bufw.close();
    }
    catch(IOException e)
    {
    }
    }
    }
    }


    字符读取流缓冲区

    package com.itheima;
    /*
     * 字符读取流缓冲区
     */
    import java.io.*;
    public class Buffreader {
    public static void main(String[] args){
    FileReader fr;
    BufferedReader bufr = null;
    try{
    fr = new FileReader("buf.txt");
    bufr = new BufferedReader(fr);
    String line =null;
    while((line=bufr.readLine())!=null){
    System.out.println(line);
    }}
    catch(IOException e){
    throw new RuntimeException("读写失败");
    }
    finally{

    try{
    if(bufr!=null)
    bufr.close();
    }
    catch(IOException e){

    }
    }

    }
    }


    通过一个缓冲区复制一个文件

    package com.itheima;
    /*
     * 通过一个缓冲区复制一个文件
     */
    import java.io.*;
    public class copy {
    public static void main(String[] args){
    BufferedReader bufr = null;
    BufferedWriter bufw = null;
    try{
    bufr=new BufferedReader(new FileReader("buf.java"));
    bufw=new BufferedWriter(new FileWriter("buf.txt"));
    String line=null;
    if((line=bufr.readLine())!=null){
    bufw.write(line);
    bufw.newLine();
    bufw.flush();
    }
    }
    catch(IOException e){
    throw new RuntimeException("读写失败");

    }
    finally{
    try{
    if(bufr!=null)
    bufr.close();
    }
    catch(IOException e){
    throw new RuntimeException("关闭写失败");
    }
    try{
    if(bufw!=null)
    bufw.close();
    }
    catch(IOException e){
    throw new RuntimeException("关闭读失败");
    }
    }
    }
    }
    ---------------------

    原文:https://blog.csdn.net/cainiaoheng/article/details/46634719

    展开全文
  • IO缓冲区的原理和使用

    千次阅读 2015-06-25 11:50:57
    现在的外设控制器都有自己的缓冲池,如磁盘和网卡,通过缓冲IO的方式读取时,如BufferedInputStream里就有个buf块,CPU可把外设里的缓冲池available的字节块整块读入该buf内存。 以下是分别是利用缓冲区进行读写和...

    -----------android培训、java培训、java学习型技术博客、期待与您交流!------------ 

    关于android培训前java基础学习的心得笔记先

    第二篇:IO缓冲区的原理和使用

    缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似于数据库的批量操作,这样大大提高高了数据的读写速率。

    现在的外设控制器都有自己的缓冲池,如磁盘和网卡,通过缓冲IO的方式读取时,如BufferedInputStream里就有个buf块,CPU可把外设里的缓冲池available的字节块整块读入该buf内存。

    以下是分别是利用缓冲区进行读写和复制操作的使用代码


    import java.io.*;
    //缓冲区为了提高流的操作效率,所以在创建缓冲区之前必须先有流对象
    public class Bufwritered {
    public static void main(String[] args){
    //创建一个字符写入流对象
    FileWriter fw;
    BufferedWriter bufw = null;
    try{
    fw = new FileWriter("buf.txt");
    bufw = new BufferedWriter(fw);
    bufw.write("abcde");
    bufw.newLine();//缓冲区提供的换行符
    }
    catch(IOException e){
    throw new RuntimeException("读写失败");
    }
    finally{
    if(bufw!=null)
    try{
    bufw.close();
    }
    catch(IOException e)
    {
    }
    }
    }
    }


    字符读取流缓冲区

    package com.itheima;
    /*
     * 字符读取流缓冲区
     */
    import java.io.*;
    public class Buffreader {
    public static void main(String[] args){
    FileReader fr;
    BufferedReader bufr = null;
    try{
    fr = new FileReader("buf.txt");
    bufr = new BufferedReader(fr);
    String line =null;
    while((line=bufr.readLine())!=null){
    System.out.println(line);
    }}
    catch(IOException e){
    throw new RuntimeException("读写失败");
    }
    finally{

    try{
    if(bufr!=null)
    bufr.close();
    }
    catch(IOException e){

    }
    }

    }
    }


    通过一个缓冲区复制一个文件

    package com.itheima;
    /*
     * 通过一个缓冲区复制一个文件
     */
    import java.io.*;
    public class copy {
    public static void main(String[] args){
    BufferedReader bufr = null;
    BufferedWriter bufw = null;
    try{
    bufr=new BufferedReader(new FileReader("buf.java"));
    bufw=new BufferedWriter(new FileWriter("buf.txt"));
    String line=null;
    if((line=bufr.readLine())!=null){
    bufw.write(line);
    bufw.newLine();
    bufw.flush();
    }
    }
    catch(IOException e){
    throw new RuntimeException("读写失败");

    }
    finally{
    try{
    if(bufr!=null)
    bufr.close();
    }
    catch(IOException e){
    throw new RuntimeException("关闭写失败");
    }
    try{
    if(bufw!=null)
    bufw.close();
    }
    catch(IOException e){
    throw new RuntimeException("关闭读失败");
    }
    }
    }
    }

    展开全文
  • 当调用write写数据的时候,调用完成后write直接返回,但是磁盘是个慢速设备,操作系统会将数据保存在内核中的缓冲区中,并负责异步地将数据写至磁盘。当然如果此时系统宕机了则会丢失数据。w...

    Linux系统IO中write原型为  ssize_t write(int  filedes, const void * buff, size_t nbytes) ;

    当调用write写数据的时候,调用完成后write直接返回,但是磁盘是个慢速设备,操作系统会将数据保存在内核中的缓冲区中,并负责异步地将数据写至磁盘。当然如果此时系统宕机了则会丢失数据。write是系统调用,每次调用都会陷入内核,所以选取一个合适的块长度buffsize,并尽量减少它的调用可以优化效率。在ANSI C的标准IO中我们调用printf/fprintf/fputs等会以流的方式进行处理,我们只需要写入流中,而不用像write一样选择一个buffsize,因为标准IO库帮我们处理了很多细节,例如缓冲区分配,以优化长度执行IO等。这样的话就会减少wirte/read系统调用的数量,提高效率。但是与此同时会引入另外一个问题:数据拷贝,例如当使用函数fgets和fputs时,通常需要经过两次缓冲区:一次是标准IO缓冲区,还有一次是调用read和write的内核缓冲区。但是总的来说使用标准IO相对于系统IO来说接口简单,且效率相当。

    标准IO提供了三种类型的缓冲区:全缓存,行缓存和不带缓存,全缓存只有在缓冲区满时才会主动flush,通常用在对一个磁盘文件IO。行缓存在缓冲区中遇到换行符就会flush,还有一种情况是需要从标准输入输出得到输入数据时也会flush缓冲区,行缓存一般用在交互的终端中。不带缓存则相当于直接 write系统调用输出,标准出错流stderr通常是不带缓存的,这就使得出错信息可以尽快显示出来。除了默认的flush条件外,显式调用fflush函数和程序正常终止时也会flush缓冲区。我们可以使用setbuf/setvbuf来更改默认的缓冲区长度,参见APUE 5.4节。

    在使用标准IO的程序中,当我们将一个标准输出重新定向到一个文件时,会将行缓存变为全缓存,在某些情况下可能会导致一些非预期错误,比如调用printf(“*****\n”)时,当以交互方式运行该程序时,会正常输出。但是当将标准输出重新定向到一个文件时,缓冲区区变为全缓存,printf就不会正常输出,该行数据仍在缓冲区中。如果此时再fork一个子进程,数据空间被复制到子进程中时,该缓冲区数据也被复制到子进程中。接着在子进程中如果输出则会刷新之前在缓冲区的内容,产生一些非预期的输出。

    在网络编程中,应该直接使用系统IO,标准IO为提升性能而引入缓冲机制增加了网络应用程序的复杂性。并且,某种意义上说标准IO流是全双工的,能同时执行输入和输出,然而对流的限制和对套接字的限制,有时候会互相冲突。(参见CSAPP P611)

    某些高级的网络库中(比如说muduo库)在使用系统IO的基础上会创建自己的缓冲区,帮助用户屏蔽系统IO的某些不便,例如调用write发送大量数据的时候,发送缓冲区满时需要应用层等待,read接收数据的时候粘包和数据接受的缓慢。当增加应用层缓冲区后,由网络库处理这些实现细节,简化用户操作。

    Linux还提供了零拷贝技术来减少内存拷贝,进而提升效率,我们知道利用read/write从磁盘发送数据到网卡会经过四次拷贝操作:当应用程序需要访问某块数据的时候,操作系统内核会先检查这块数据是不是因为前一次对相同文件的访问而已经被存放在操作系统内核地址空间的缓冲区内,如果在内核缓冲区中找不到这块数据,Linux 操作系统内核会先将这块数据从磁盘读出来放到操作系统内核的缓冲区里。如果这个数据读取操作是由 DMA 完成的,那么在 DMA 进行数据读取的这一过程中,CPU 只需要进行缓冲区管理,以及创建和处理 DMA ,除此之外,CPU 不需要再做更多的事情,DMA 执行完数据读取操作之后,会通知操作系统做进一步的处理。Linux 操作系统会根据 read系统调用指定的应用程序地址空间的地址,把这块数据存放到请求这块数据的应用程序的地址空间中去,待用户对数据完成操作后,操作系统需要将数据再一次从用户应用程序地址空间的缓冲区拷贝到与网络堆栈相关的内核缓冲区中去,这个过程也是需要占用 CPU 的。数据拷贝操作结束以后,数据会被打包,然后发送到网络接口卡上去。从上面的描述可以看出,在这种传统的数据传输过程中,数据至少发生了四次拷贝操作,即便是使用了 DMA 来进行与硬件的通讯,CPU 仍然需要访问数据两次。

       (ps:记得之前看过一个面试题说是printf输出过程经过几次缓冲区,现在大家明白了吧!)

    使用零拷贝技术可以避免数据在系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区进行拷贝。有时候,应用程序在数据传输的过程中不需要对数据进行访问,传输的数据可以不用复制到用户应用区,直接通过内核发送到网卡就可以,这样可以提高性能,而此时就需要零拷贝技术。linux下可以用mmap,sendfile,splice实现零拷贝。












    本文转自xmgdc51CTO博客,原文链接: http://blog.51cto.com/12953214/1940500 ,如需转载请自行联系原作者




    展开全文
  • 内核态与用户态、系统调用与库函数、文件IO与标准IO缓冲区等概念介绍

    Linux提供了两套可以用于文件的IO接口

    • 文件IO: open、create、close、lseek、read、write、fcntl、ioctl等

    • 标准IO: FILE、fopen、fwrite、fread、等

    为了理解文件IO和标准IO的区别,可能要先理解下用户态与内核态,系统调用与库函数的概念

     

    用户态和内核态

    什么是用户态和内核态

    • 内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序

    • 用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

     

    区分用户态和内核态的作用

    • 为了限制不同程序的访问能力,防止它们随意获取其他程序或外围设备的数据

    • 限制用户态的访问能力,还可以防止外围设备的访问冲突

     

    用户态和内核态的切换

    程序都是工作在用户态,但是有时候程序需要访问一些受限的数据(如从硬盘读数据,从键盘获取输入等),这是就需要切换到内核态。切换的方式一般时调用系统调用。用户态通过系统调用通知内核态,需要访问哪些受限的数据,或操作哪些受限的设备。内核态就帮助用户态完成

     

    用户态和内核态小结

    简单的说,用户程序只能访问内存,而操作系统能访问所有数据。用户程序工作的模式即是用户态,当用户程序想要访问受限的数据时,就需要向操作系统发请求,让操作系统帮忙完成。 操作系统工作的模式即内核态

     

    库函数和系统调用

    库函数工作在用户态,系统调用工作在内核态

    所有的操作系统都会提供一些服务用以访问/操作设备等,操作系统会为这些服务提供接口。这些接口就是系统调用 。用户态程序通过调用系统调用可以切换到内核态,访问内存意外的数据,操作外围设备等

    不同的操作系统提供的系统调用会有所差异

    Unix为每个系统调用在标准C库中设置一个具有同样名字的函数 。 一般我们是称这些函数为系统调用。(如标准C库中有函数write(), write()函数直接使用write系统调用相应的内核服务)。 所以一般说write(),指的不是write()这个函数,而是系统调用write

    标准C库,或是其他库会定义一些函数,这些函数称之为库函数。很多库函数是跨平台的。虽然有些库函数最终会调用系统调用,但不少库函数会根据具体的操作系统选用响应的系统调用接口

    有些库函数仅仅是操作内存,不访问硬盘等外围设备的数据,因此最终并不会调用系统带哦用。即:并不是所有的库函数最终都要使用系统调用的, 如:strcpy、atoi等

     

    I/O的概念

    I/O:输入输出

    既然是输入输出,就要有输入输出设备(一般内存不算输入输出设备)。如硬盘、键盘、终端等都可以作为输入输出设备

    用户态是不能访问硬盘、键盘、终端这些外围(虚拟)设备的,因此需要切换到内核态。用户态和内核态的切换是会产生开销的

    举个例子,程序要从硬盘上的文件读取数据,其过程如下:

    1. 程序通过系统调用(如read)告诉操作系统想要读取某个硬盘文件的内容。

    2. 切换到内核态(这里需要从用户态向内核态传递,要读取的是哪个文件等信息)

    3. 系统调用(工作在内核态)读取文件内容。

    4. 切换到用户态(这个过程包含了把系统调用读取到的数据拷贝到用户态的过程)

    5. 程序得到数据

     

    文件I/O——不带缓冲的I/O

    文件IO相关的函数open、close、read、write等等

    这里我们主要以write()函数为例,介绍一些文件IO的特性

    文件IO是不带缓冲的,所谓不带缓冲,即每调用一次文件IO(如write),就进行一次用户态与内核态的切换

    调用一次write,就需要立即把数据从用户态拷贝到内核态

     

    标准I/O——带缓冲的I/O

    标准IO相关的函数主要有:fopen、fclose、fread、fwrite、fgetc等等

    标准IO是带缓冲的

    标准IO提供缓冲的目的是尽可能减少使用read和write调用的次数(也就是用户态和内核态切换的次数)

    所谓带缓冲,其实就是在调用fwrite的时候,先把数据放在缓冲区。不直接使用系统调用,切换到内核态。而是等到缓冲区满或是调用fflush等条件满足时,再一次性调用write,把数据拷贝到内核空间

     

    缓冲

    缓冲是标准IO库提供的,缓冲区存在于用户空间(不管是fread还是fwrite)。 对于fwrite,根据上面的例子很好理解。对于fread而言,就是在调用fread的时候,切换到内核态,内核态读取缓冲去能够接受的大小的数据(一般会多余此次fread期望的数据), 然后返回给fread函数。下次再调用fread的时候,可能只需要从缓冲区读取,而不需要再到内核空间拷贝了

    标准IO有三种缓冲类型:全缓冲行缓冲不带缓冲

     

    文件IO与标准IO的一些对比

    效率对比

    文件IO不带缓冲,因此每调用write,就需要做用户态和内核态的切换,把数据从用户态切换到内核态

    标准IO带缓冲,调用fwrite的时候,先把数据保存在缓冲区,等待缓冲区满或调用fflush等条件满足时,再调用write,一次性把多次fwrite的数据

    因此,从效率上看,带缓冲的IO作用户态与内核态切换的次数较少,效率比较高。没有特殊要求的话,一般应该选用fopen、fwrite系列带缓充的IO

     

    文件IO与标准IO的应用场景——多线程日志系统为例

    在多线程日志系统中,每个线程打开一个日志文件的描述符

    如果使用带缓冲的IO,最终可能导致日志的顺序发生错乱,可能影响阅读。因此如果对多线程的日志顺序有要求的话,可能需要使用不带缓冲的IO

    另一方面,在测试中发现,使用标准IO时,每次调用write的数据并不一定都是多次完整的fwrite的数据。可能会有一些fwrite的数据被分为两次write。举个例子,每次调用fwrite写100个字节的数据,而缓冲区为550个字节,那么第6次fwrite的数据可能就被截断分成两次write。(这是我在centOS7.2上的测试结论,目前不清楚是否可以配置在fwrite写缓冲之前先判断缓冲区剩余空间是否充足,不足时先调用write,再把完整的fwrite数据写入缓冲)。(就刚刚那个例子来说,就是不知道是否可以配置,在第6次fwrite写缓冲之前先write前面的500字节)

     

    本篇博客转载自博主:《轮子学长

    展开全文
  • 缓冲区填满时才调用IO操作对于一些耗时的操作例如对于一些外设(磁盘、网卡)等都采用全缓冲的方式来进行IO系统调用来提高效率。当程序调用flush()函数或者进行到return 时才开始执行IO调用。 行缓冲(重要、细节...
  • 转载请注明出处:jiq•钦's technical Blog 引言JDK1.4中引入了NIO,即New IO,目的在于提高IO速度。特别注意JavaNIO不完全是非阻塞式IO(No-Blocking IO),因为其中部分通道(如FileChannel)只能运行在阻塞模式下,...
  • 从抽象的角度看,也就是说,一个用户进程在内存中有自己的一个进程缓冲区,系统底层也有自己的一个内核缓冲区,read系统调用,就是将进程缓冲区中的数据复制到内核缓冲区中,而write系统调用则是将内核缓冲区中的...
  • 比如读缓冲时,如果没有缓冲区,CPU就总是在一次次的读,如果有了,可以一次性读取,这样节省时间。 这样的回答我不明白。这个CPU的节省又不是给我的这个程序节省的,大不了操作系统可以多用一些CPU干别的了。对于...
  • 缓冲区的三种模式

    千次阅读 2019-05-14 19:13:32
    缓冲区分三种mode 分别是_IOFBF全缓冲区是指缓冲区系统默认4k的方式设定的缓冲区大小 除非缓冲区满 或者调用fflush(stdout)才可以将标准输入的数据全部读取 如printf _IOLBF行缓冲区:是指当输入一行的时候 通过\n...
  • 我可以给你讲 IO、讲中断、讲缓冲区,但这不是研究网络时该关心的问题。 如果你纠结,要么去研究一下操作系统是如何处理网络 IO 的,要么去研究一下包是如何被网卡转换成电信号发送出去的,要么就仅仅把它当做电脑...
  • } } } 有无缓冲区的区别 不使用和使用缓冲区的区别,在比较大的文件会体现得比较明显 不设定缓冲区也不使用内置缓冲区 import java.io.*; public class IODemo3 { public static void main(String[] args) throws ...
  • 数据从内核缓冲区复制到用户缓冲区当中 这里以Java服务端为例,完成一次socket请求和响应,完整的流程如下: 客户端发出请求操作:服务器系统通过网卡读取到客户端的数据,将数据读取到内核缓冲区 服务器获取请求...
  • 非直接缓冲区(ByteBuffer): 在jvm中开辟数据空间(用户空间); 每次的io操作都会有内核空间缓存和jvm缓存之间的copy操作 以网络IO往外读为例:JVM用户内存 通过CPU拷贝->内核缓冲buffer 通过DMA拷贝->...
  • IO模型

    2019-11-06 19:02:45
    (一)分类 从载体上:网络IO和文件IO ...read系统调用,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。这个两个系统调用,都不负责数据在内核缓冲区和物...
  • IO

    2016-10-11 08:16:24
    //updating IO模型有阻塞IO、非阻塞IOIO复用、信号驱动IO和异步IO,POSIX标准:同步和异步IO。...读(外存到内存:将数据从网卡到系统空间; 从系统空间到用户空间)输入流,写(将数据从用户空间到系统空间;...
  • 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    万次阅读 多人点赞 2016-10-28 20:01:41
    5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO 看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度、环境不一样。所以,我们先说明基本的IO操作及环境。本文是在《UNIX网络编程 卷1:套接字联网API》...
  • IO相关

    2019-10-10 11:39:57
    IO tcp为提高性能,发送端会将需要发送的数据发送到缓冲区,等待缓冲区满了之后...应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。 进行mss(最大报文长度)大小...
  • 详解IO模型

    2020-11-06 16:36:16
    目录 一、IO基础原理 1、操作系统的IO ...应用程序调用操作系统的read、write接口,完成数据在应用程序的进程缓冲区和操作系统的内核缓冲区之间的交互。 操作系统设置数据缓冲区的目的,是为了...
  • java-IO

    2020-03-29 16:51:14
    1、 java IO读写的底层流程 用户程序进行IO的读写,基本上会用到系统调用read&write,read把数据从内核缓冲区复制到进程缓冲区,write...Linux通过网卡,读取客户断的请求数据,将数据读取到内核缓冲区。 (2)...
  • IO系列之五种IO模型

    2019-12-13 16:27:03
    内核会为每个I/O设备(硬盘,网卡)维护一个缓冲区,当内核缓冲区有数据则直接复制到进程空间,如果内核缓冲区中没有相应的数据则再到设备中读取,因为设备IO一般速度较慢,需要等待。 所以通常用户进程IO操作中,...
  • 磁盘IO和网络IO

    千次阅读 2019-09-13 15:24:52
    当应用程序调用read接口时,操作系统检查内核缓冲区中是否存在需要的数据,如果存在,就直接从内核缓存中直接返回,否则从磁盘中读取,然后缓存至操作系统的缓存中。 当应用程序调用write接口时,将数据直接从...
  • IO 理解加强

    2021-07-21 10:53:31
    1 网卡收到经过网线传来的网络数据,并将网络数据写到内存中(TCP/IP缓冲区)。 2 当网卡把数据写入到内存后,网卡向cpu发出一个中断信号,操作系统便能得知有新数据到来,再通过网卡中断程序去处理数据。 3 将内存...
  • 文件同样也不能直接交给用户进程,首先磁盘将文件放至内核缓冲区,然后内核告知用户进程请求的资源结果已准备好(耗时比较短) 内核缓冲区将文件拷贝一份至用户进程缓冲区,用户进程拿到文件 构建响应报文,通过...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,293
精华内容 6,517
关键字:

网卡io缓冲区