浅析缓冲区

1.缓冲区的分类

1.用户程序缓冲区;
2.C标准I/O缓冲区
3.内核缓冲区.

2.缓冲区存在的意义

      应用缓冲技术能很明显的提高系统效率。内核与外围设备的数据交换,内核与用户空间的数据交换都是比较费时的,使用缓冲区就是
为了优化这些费时的操作。其实核心到用户空间的操作本身是不buffer的,是由I/O库用buffer来优化了这个操作。比如read本来从内核
读取数据时是比较费时的,所以一次取出一块,以避免多次陷入内核。
      应用内核缓冲区的 主要思想就是一次读入大量的数据放在缓冲区,需要的时候从缓冲区取得数据。
      管理员模式和用户模式之间的切换需要消耗时间,但相比之下,磁盘的I/O操作消耗的时间更多,为了提高效率,内核也使用缓冲区
技术来提高对磁盘的访问速度。磁盘是数据块的集合,内核会对磁盘上的数据块做缓冲。内核将磁盘上的数据块复制到内核缓冲区中,当一
个用户空间中的进程要从磁盘上读数据时,内核一般不直接读磁盘,而 是将内核缓冲区中的数据复制到进程的缓冲区中。当进程所要求的
数据块不在内核缓冲区时,内核会把相应的数据块加入到请求队列,然后把该进程挂起,接着为其 他进程服务。一段时间之后(其实很短
的时间),内核把相应的数据块从磁盘读到内核缓冲区,然后再把数据复制到进程的缓冲区中,最后唤醒被挂起的进程。
      注:理解内核缓冲区技术的原理有助于更好的掌握系统调用read&write,read把数据从内核缓冲区复制到进程缓冲区,write把数
据从进程缓冲区复制到内核缓冲区,它们不等价于数据在内核缓冲区和磁盘之间的交换。
      从理论上讲,内核可以在任何时候写磁盘,但并不是所有的write操作都会导致内核的写动作。内核会把要写的数据暂时存在缓冲
区中,积累到一定数量后再一次写入。有时会导致意外情况,比如断电,内核还来不及把内核缓冲区中的数据写道磁盘上,这些更新的数
据就会丢失。
      应用内核缓冲技术导致的结果是:提高了磁盘的I/O效率;优化了磁盘的写操作;需要及时的将缓冲数据写到磁盘。

 

3.用户程序缓冲区

    在函数栈上分配的如char buf[10];之类的缓冲区, strcpy(buf, str);  str 所指向的字符串有可能超过10个字符而导致写越界,
这种写越界可能当时不出错, 而在函数返回时出现段错误,原因是写越界覆盖了保存在栈帧上的返回地址, 函数返回时跳转到非法地址,因而出错。
像buf 这种由调用者分配并传给函数读或写的一段内存通 常称为缓冲区(Buffer),缓冲区写越界的错误称为缓冲区溢出(Buffer Overflow)。
如果只是出 现段错误那还不算严重,更严重的是缓冲区溢出Bug经常被恶意用户利用,使函数返回时跳转到一 个事先设好的地址,执行事先设好
的指令,如果设计得巧妙甚至可以启动一个Shell,然后随心所欲 执行任何命令,可想而知,如果一个用root权限执行的程序存在这样的Bug,被
攻陷了,后果将很严重。

4.C标准I/O缓冲区

    UNIX的传统 是Everything is a file,键盘、显示器、串口、磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也
可以像普通文件(保存在磁盘上的文件)一样打开、读、写和关闭,使用的函数接口是相同的。用户程序调用C标准I/O库函数读写普通文件或设备,
而这些库函数要通过系统调用把读写请求传给内核 ,最终由内核驱动磁盘或设备完成I/O操作。C标准库为每个打开的文件分配一个I/O缓冲区以
加速读写操作,通过文件的FILE 结构体可以找到这个缓冲区,用户调用读写函数大多数时候都在I/O缓冲区中读写,只有少数时候需要把读写请求传
给内核。以fgetc / fputc 为例,当用户程序第一次调用fgetc 读一个字节时,fgetc 函数可能通过系统调用 进入内核读1K字节到I/O缓冲区中,
然后返回I/O缓冲区中的第一个字节给用户,把读写位置指 向I/O缓冲区中的第二个字符,以后用户再调fgetc ,就直接从I/O缓冲区中读取,而不需
要进内核 了,当用户把这1K字节都读完之后,再次调用fgetc 时,fgetc 函数会再次进入内核读1K字节 到I/O缓冲区中。在这个场景中用户程序、
C标准库和内核之间的关系就像在“Memory Hierarchy”中 CPU、Cache和内存之间的关系一样,C标准库之所以会从内核预读一些数据放 在I/O
缓冲区中,是希望用户程序随后要用到这些数据,C标准库的I/O缓冲区也在用户空间,直接 从用户空间读取数据比进内核读数据要快得多。另一
方面,用户程序调用fputc 通常只是写到I/O缓 冲区中,这样fputc 函数可以很快地返回,如果I/O缓冲区写满了,fputc 就通过系统调用把
I/O缓冲 区中的数据传给内核,内核最终把数据写回磁盘或设备。有时候用户程序希望把I/O缓冲区中的数据立刻 传给内核,让内核写回设备或
磁盘,这称为Flush操作,对应的库函数是fflush,fclose函数在关闭文件 之前也会做Flush操作。

 

5.内核缓冲区 

内核缓冲区分类:
1.终端缓冲区;
2.FIFO和UNIX Domain Socket缓冲区

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值