by cszhao1980

同块设备一样,对字符设备的输入输出也是通过缓冲区来进行的。使用缓冲区有个额外

的好处,即以缓冲区为界,函数可分为高低两个层次。低层函数负责与实际设备交互,

而高层函数只与缓冲区打交道,只对缓冲区存取数据,这样可以蔽掉掉底层的许多细节。

对于字符缓冲区,有两个最重要结构,即cblock和clist。前者是缓冲区本身,后者则用作

字符链表(队列)的头结点。莱昂在第23章中详细介绍了这两个struct,并对字符链表的

增删操作作了详细的分析,请您务必仔细阅读第23章的说明。

系统共有NCLIST个缓冲区资源:

8146: struct cblock cfree[NCLIST]

空闲的缓冲区都被链接在cfreelist链表中。

Cinit函数使用头插法建立cfreelist链表,该函数比较令人费解的是第8240行的for循环——该条

语句的作用是,使每个实际使用的缓冲区的起始地址都能够被8整除。莱昂其实已经说明了这

样做的原因,即这样设置之后,可以通过地址模除8的方式来判断clist的头尾指针是否移出了

一个缓冲区边界。

getc和putc函数分别用来从缓冲区链表中get和put char。奇怪的是,unix v6选择使用汇编来实现

这两个函数——也许是出于性能的考虑吧。

getc函数有一个参数,即缓冲区链表的头结点地址。

(1)第936行将first ptr放入r2;

(2) 937行:如果头结点的first ptr为NULL(表示缓冲区已空),则跳到Label 9,返回-1;

(3) 938行:取first ptr指向的一个byte,放入r0(作为返回值);

注意,这里使用的movb指令以byte为单位进行操作,r2会后移1个byte,而不是word。

(4) 940行:将first ptr后移一个byte。

接下来的处理分为3种情况:

i.缓冲区链表已空;

此时,无需后续处理,直接从Label“3:”处返回即可。

ii.first ptr移出了当前缓冲区边界;

iii.first ptr仍在当前缓冲区内;

这两种情况需要后续处理,即调整first ptr,并释放用完的缓冲区。

putc函数有两个参数:

(1)         要放入缓冲区链表的char;

(2)         缓冲区链表头结点地址。

同getc不同,该函数在当前缓冲区链表满时,需要申请空闲缓冲区——当无空闲缓冲区可

用时,操作会失败,会通过Label 9返回非0数据。函数有几个重要的判断:

(1)         976: 当前缓冲链表是否为空(只有头结点);

(2)         978: 系统中是否还有空闲缓冲区;

(3)         984: 当前缓冲区是否已经写满

【注】:从putc函数可知,clist的last ptr指向的其实并不是缓冲链表内最后一个char,而是该

char的下一个byte。如果没有跨越缓冲区边界,则此byte可用于存放下一个char,否则,表示

缓冲链表已满,需要新申请一个缓冲区。

博客地址:http://blog.csdn.net/cszhao1980

博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

(莱昂氏unix源代码分析导读-49) 字符缓冲区相关推荐

  1. (莱昂氏unix源代码分析导读-1) 引子

                                                                                   那一年不知怎样,此书忽在世间出现,天下学武 ...

  2. (莱昂氏unix源代码分析导读-46)权限、管道

                                    by cszhao1980  1.    文件与权限控制 进程u结构中,身份相关的信息有: 0420: char u_uid; /* e ...

  3. (莱昂氏unix源代码分析导读-19)再谈进程swtch

    我们已经涉及到了部分进程切换的概念,在本章中,我们会从更一般的意义上考察进程切换的行为. 首先,进程切换(也称作context switch)一定是在内核中完成的. 比如,以下为发生进程切换的最常见的 ...

  4. (莱昂氏unix源代码分析导读-47) exec

    by cszhao1980 现在,我们已经储备了足够的知识,该吹响向EXEC sys call冲锋的号角了. exec是系统中最重要也是最复杂的系统调用之一,它的作用是执行指定的"可执行文件 ...

  5. 读《莱昂氏UNIX源代码分析》

    在unix早期的代码中,schedule和swap两个核心任务都是由0号进程来负责的,这个朴实的设计就是unix系统最最原始的设计,因为unix在开始设计的时候十分清楚进程应该做什么不应该做什么,应该 ...

  6. nux 平台的 libpcap 源代码分析

    nux 平台的 libpcap 源代码分析 施聪 (javer@163.com), 高级程序员.网络设计师 简介: libpcap 是 unix/linux 平台下的网络数据包捕获函数包,大多数网络监 ...

  7. struts2请求过程源代码分析

    struts2请求过程源代码分析 Struts2是Struts社区和WebWork社区的共同成果.我们甚至能够说,Struts2是WebWork的升级版.他採用的正是WebWork的核心,所以.Str ...

  8. linux VFS概述以及内核源代码分析

    linux VFS概述以及内核源代码分析 一.   概述 Linux能够支持各种不同的文件系统是通过VFS实现的,由于不同的物理文件系统具有不同的组织结构和不同的处理方式,为了能够处理各种不同的物理文 ...

  9. 如何看懂源代码--(分析源代码方法) 1

    如何看懂源代码--(分析源代码方法)  -- 转载 作者: fandyst 出处: http://www.cnblogs.com/todototry/ 原文: https://www.cnblogs. ...

  10. Mysql源代码分析系列

    Mysql源代码分析系列(2): 源代码结构 Mysql源代码主要包括客户端程序代码,服务器端代码,测试工具和一些库构成,下面我们对比较重要的目录做些介绍. BUILD 这个目录在本系列的上篇文章中我 ...

最新文章

  1. LeetCode简单题之数字转换为十六进制数
  2. 多级NUMA:AMD EPYC互连速率、位宽与功耗的关系
  3. 【控制】《多智能体机器人系统信息融合与协调》范波老师-第3章-多 Agent 协调的学习与对策
  4. 什么叫dfs文件服务器,什么是DFS(分布式文件系统)以及DFS的优点
  5. Symantec Backup Exec 2014 备份Exchange 2013之二安装主备服务器
  6. c语言什么叫为代码写注释算法,急!-伪代码不知哪位高手能够告诉我,什么是伪代码?伪代码编 爱问知识人...
  7. PHP 父类静态方法中调用子类静态方法
  8. Win32 Application 、Win32 Console Application、MFC工程项目
  9. Web前端开发工具和框架
  10. 海康硬盘录像机管理员密码初始化方法
  11. c语言 uint16_t,c中数据类型uint16_t,uint32_t,uint64_t输入输出使用方法
  12. 【禁止套娃】用PPSSPP模拟PSP模拟Neogeo模拟SNK拳皇97
  13. el-input和和filter结合实现实时搜索
  14. 1425: PIPI的消消乐Ⅴ
  15. java获取虎牙直播弹幕消息,虎牙直播弹幕筛选器
  16. 【微信小程序开发】缓存Storage的存入与获取
  17. 【保姆式教程】用PowerDesigner导出数据库表结构为Word/Excel表格
  18. oracle数据库报错:ORA-01654: 索引 aaa 无法通过 128 (在表空间 bb 中) 扩展
  19. 学习日志--1.html
  20. 工资管理系统的需求概述的资料收集与分析:

热门文章

  1. python 声音模仿_浅谈盘点5种基于Python生成的个性化语音方法
  2. iis7网站可用php吗,在IIS7下面添加对PHP网页的支持
  3. 计算机备份u盘,如何备份电脑系统到u盘
  4. pie函数--Matplotlib
  5. 非堵塞socket实现android手机与PC的文件传输
  6. android 进入三方应用动画,Android 动画各种实现总结分享 AndroidAnimationExercise
  7. Java七大设计模式原则(附相关电子图书下载)
  8. 使用servlet技术与前端进行交互,出现乱码的解决方案,创建一个类,如下:
  9. 通过编写纯代码与JDBC实现对mysql的数据实现增删改查案例,jdbc连接数据库六步完整步骤详解,适合编程新手,通俗易懂
  10. c++多边形扫描线填充算法_一文读懂扫描线算法