APR分析-高级IO篇

近两天稍轻闲了些,便抓紧时间学习、学习再学习。在“APR分析-文件IO篇”,我们只分析了最基本的I/O操作,如文件的open、close、write和read。当然File

I/O操作不止这些,在这一篇中我们来看看APR提供的一些高级I/O设施,包括记录锁、I/O多路复用和内存映射文件(内存映射文件将和共享内存一起分析)。

一、记录锁或(区域锁)[注1]

我见过的对记录锁讲解最详细的书就是《Unix高级环境编程》,特别是关于进程、文件描述符和记录锁三者之间关系的讲解更是让人受益匪浅,有此书的朋友一定不要放过哟。这里将其中的三原则摘录到这:

关于记录锁的自动继承和释放有三条规则:

(1)锁与进程、文件两方面有关。这有两重含意:第一重很明显,当一个进程终止时,它所建立的锁全部释放;第二重意思就不很明显,任何时候关闭一个描述符时,则该进程通过这一描述符可以存访的文件上的任何一把锁都被释放(这些锁都是该进程设置的)。

(2)由fork产生的子程序不继承父进程所设置的锁。这意味着,若一个进程得到一把锁,然后调用fork,那么对于父进程获得的锁而言,子进程被视为另一个进程,对于从父进程处继承过来的任一描述符,子进程要调用fcntl以获得它自己的锁。这与锁的作用是相一致的。锁的作用是阻止多个进程同时写同一个文件(或同一文件区域)。如果子进程继承父进程的锁,则父、子进程就可以同时写同一个文件。

(3)在执行exec后,新程序可以继承原执行程序的锁。

话归正题谈APR的记录锁,平心而论APR的提供的加索和解锁接口并没有什么独到的地方,APR之所以将之封装起来,无非是为了提供一个统一的跨平台接口,并且不破坏APR整体代码风格的一致性。APR记录锁源码位置在$(APR_HOME)/file_io/unix目录下flock.c,头文件仍然是apr_file_io.h。apr_file_lock和apr_file_unlock仅提供对整个文件的加锁和解锁,而并不支持对文件中任意范围数据的加锁和解锁。至于该锁是建议锁(advisory

lock)还是强制锁(mandatory lock),需要看具体的平台的实现了。两个函数均利用fcntl实现记录锁功能(前提是所在平台支持fcntl,由于fcntl是POSIX标准,绝大多数平台都支持)。代码中有一处值得鉴赏:

while ((rc = fcntl(thefile->filedes, fc, &l)) < 0&& errno == EINTR)

continue;

这里这么做的原因就是考虑到fcntl的调用可能被某信号中断,一旦中断我们去要重启fcntl函数。

二、I/O多路复用[注2]

在经典的《Unix网络编程第1卷》Chapter

6中作者详细介绍了五种I/O模型,分别为:

- blocking I/O

- nonblocking I/O

- I/O multiplexing (select and poll)

- signal driven I/O (SIGIO)

- asynchronous I/O (the POSIX aio_functions)

作者同时对这5种I/O模型作了很详细的对比分析,很值得一看。这里所说的I/O多路复用就是第三种模型,它既解决了Blocking

I/O数据处理不及时,又解决了Non-Blocking I/O采用轮旬的CPU浪费问题,同时它与异步I/O不同的是它得到了各大平台的广泛支持。

APR I/O多路复用源码主要在$(APR_HOME)/poll/unix目录下的poll.c和select.c中,头文件为apr_poll.h。APR提供统一的apr_poll接口,但是apr_pollset_t结构定义和apr_poll的实现则根据宏POLLSET_USES_SELECT、POLL_USES_POLL和POLLSET_USES_POLL的定义与否而不同。这里拿poll的实现(That

is使用poll来实现apr_poll及apr_pollset_xx相关,与之对应的是使用select来实现apr_poll及apr_pollset_xx相关)来分析:在poll的实现下,apr_pollset_t的定义如下:

/* in poll.c */

struct apr_pollset_t

{

apr_pool_t *pool;

apr_uint32_t nelts;

apr_uint32_t nalloc;

struct pollfd *pollset;

apr_pollfd_t *query_set;

apr_pollfd_t *result_set;

};

统一的apr_pollfd_t定义如下:

/* in apr_poll.h */

struct apr_pollfd_t {

apr_pool_t*p;             /* associated pool */

apr_datatype_e desc_type;   /*descriptor type */

apr_int16_treqevents;      /* requested events */

apr_int16_trtnevents;      /* returned events */

apr_descriptordesc;        /* @see apr_descriptor */

void*client_data;          /* allowsapp to associate context */

};

把数据结构定义贴出来便于后面分析时参照理解。

假设我们像这样apr_pollset_create(&mypollset,10, p, 0)调用,那么在apr_pollset_create后,我们可以用图示来表示mypollset变量的状态:

mypollset

-------

nalloc  ----> 10 /*该mypollset的“容量”,在create的时候由参数指定*/

-------

nelts   ----> 0  /*刚初始化,mypollset中并没有任何element,之后每add一次,nelts就+1

*/

-------

---------------------------------------------

pollset --------->  pollset[0] | pollset[1] |...|pollset[nalloc-1]

---------------------------------------------

-------

-----------------------------------------------------

query_set --------->  query_set[0] | query_set[1] |...|query_set[nalloc-1]

-----------------------------------------------------

-------

---------------------------------------------------------

result_set --------->  result_set[0] | result_set[1] |...|result_set[nalloc-1]

---------------------------------------------------------

-------

pollset、query_set和result_set这几个集合的关系通过下图说明:

apr_pollfd_t *descriptor ---> [pollset_add]--------> query_set ------ [pollset_poll] -----> result_set (输出)

|                                                                                           /|/

------------------->pollset ------ [pollset_poll] --------------------

apr_pollset_xx系列是改版后APR I/O复用新增的接口集,它以apr_pollset_t作为其管理的基本单位,其中apr_pollset_poll用于监视pollset中的所有descriptor(s)。而apr_poll则是旧版的APR

I/O复用接口,它同样可以实现apr_pollset_poll的功能,只是它的基本管理单位是apr_pollfd_t,其相关函数还包括apr_poll_setup、apr_poll_socket_add等在apr-1.1.1版中已看不到的几个接口。新版本中建议使用apr_pollset_poll,起码APR的测试用例(testpoll.c)是这么做的。

select实现的思路与poll实现的思路是一致的,只是apr_pollset_t的结构不同,原因不言自明。

三、总结

由于APR对高级I/O的封装很“薄”,所以基本上没有太多很精致的东西。

四、参考资料

1、《Unix高级环境编程》

2、《Unix网络编程卷1、2》

[注1]

对于Unix,“记录”这个定语也是误用,因为Unix内核根本没有使用文件记录这种概念。一个更适合的术语可能是“区域锁”,因为它锁定的只是文件的一个区域(也可能是整个文件)--摘自《Unix高级环境编程》。

[注2]

在《Unix网络编程卷1》译者译为"多路复用",在《Unix高级环境编程》中译者译为"多路转接",我更倾向于前者。I/O多路复用其英文为"I/OMultiplexing"。

C语言apr_socket,APR分析-高级IO篇相关推荐

  1. APR分析-共享内存篇

    APR分析-共享内存篇 共享内存是一种重要的IPC方式.在项目中多次用到共享内存,只是用而并未深入研究.这次趁研究APR代码的机会复习了共享内存的相关资料. APR共享内存封装的源代码的位置在$(AP ...

  2. Linux性能分析之IO篇

    硬盘IO篇 这里用到iostat用于分析磁盘IO的利器 iostat 3 10 的意思是每3秒检测一次,一共检测10次 %iowait 值得注意的一个地方,表示理论上越低表示磁盘越不繁忙. tps:每 ...

  3. linux系统资源分析 - 磁盘IO篇

    目录 一.理解磁盘IO 二.普通文件IO调度 三.磁盘阵列 四.常用命令 4.1 iostat命令详解 五.综合案例(内存&IO) 一.理解磁盘IO 以超市结账为例,来理解磁盘IO的队列情况( ...

  4. android apr分析,APR分析信号篇

    APR分析-信号篇 U know信号是Unix的重要系统机制.信号机制使用起来很简单,但是理解起来有并不是那么Easy.APR Signal的封装也并不繁琐,代码量很少,所以分析APR Signal的 ...

  5. 一个C语言的基本教程—IO篇

    文章目录 10.与用户交互的关键--IO篇 (1).I/O是什么 (2).换个办法操作字符 #1.新的朋友--getchar和putchar #2.getchar的妙用 (3).重新认识一下--pri ...

  6. 50万数据生成6位数不重复字符串_R语言系列3:高级数据管理

    R语言系列3:高级数据管理 此文内容为<R语言实战>的笔记,人民邮电出版社出版. 从高中电脑课学VB开始,大一课内开始学习C++,到后来大二为了数模学习Matlab,到大三为了搞深度学习自 ...

  7. Spring定时任务高级使用篇

    Spring定时任务高级使用篇 前面一篇博文 <Spring之定时任务基本使用篇> 介绍了Spring环境下,定时任务的简单使用姿势,也留了一些问题,这一篇则希望能针对这些问题给个答案 I ...

  8. Linux之高级IO

    目录 一.五种IO模型 以网络为例 什么叫做IO? 什么叫做高效的IO呢? 为什么第二个大爷的效率很高呢? 五种IO模型 感性认识 这五个人,在钓鱼的时候,谁的效率是最高的? 阻塞IO 非阻塞IO 信 ...

  9. c语言获取指针分配的字节数,c语言指针知识点总结(共6篇).docx

    c语言指针知识点总结(共6篇) C语言指针教学中的知识点分析与总结 摘要:分析指针的基本概念及指针在数组.函数.字符串.动态存储分配等方面的应用,提出指针教学过程中易混淆概念及注意事项,对初学者深入理 ...

  10. Wireshark数据抓包分析(网络协议篇)第1章网络协议抓包概述

    Wireshark数据抓包分析(网络协议篇)第1章网络协议抓包概述 网络协议是用于不同计算机之间进行网络通信的.网络协议是网络上所有设备(如网络服务器.计算机.交换机.路由器等)之间通信规则的集合,它 ...

最新文章

  1. Android 通过Intent调用系统功能和Action动作和服务广播【大全】
  2. 手機電視挑戰傳統視聽習慣
  3. 99. Leetcode 322. 零钱兑换 (动态规划-完全背包)
  4. Mysql5.7读写分离
  5. winmail计算机三级,2016年计算机三级网络技术机考模拟题(1)
  6. svm算法 java实现_SVM算法实现(一)
  7. QQ 可注销版本上线;拼多多成立技术顾问委员会;董明珠:建议偷手机判 10 年 | 极客头条...
  8. Java+selenium 自动化测试--自动化测试模型介绍
  9. 机器人伪装成人类在 GitHub 上为开源项目修复 bug
  10. linux下用arcconf做raid5,arcconf工具相关命令V1.0
  11. android8.1dolby,努比亚X刷杜比音效教程-按推理支持绝多数安卓8和安卓9系统
  12. hive Unexpected column vector type LIST
  13. 关于计算机的想象类作文,想象类作文范文
  14. QThread: Destroyed while thread is still running的处理方法
  15. luogu 4234 最小差值生成树 LCT
  16. 继昨天的猜拳游戏,升级为老虎机版
  17. debian重启ssh服务_Win10自带的ssh客户端key权限设置
  18. pythonGUI(二)基本元素之二
  19. 忽略validateRequest设置
  20. html左侧下拉输入选项菜单栏,怎么实现html可输入下拉菜单

热门文章

  1. 英特尔cpu发布时间表_英特尔10代桌面cpu上市时间(英特尔10代发售时间)
  2. 体检信息管理系统功能表
  3. Drilldown饼状图
  4. 计算机管理器磁盘清理,win10 磁盘空间清理管理器已停止工作怎么解决
  5. 51nod 1299 监狱逃离
  6. 去哪儿能找到那种直接翻译好的外文文献去阅读呢?
  7. word里双横线怎么打_word怎么加双下划线
  8. 《人间告白》---我看万物像你,我看你像万物
  9. 人生之路优化,bug修复
  10. 加密货币如何改变着IT产业