- 1、本文档共10页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
Select函数实现原理分析
Select函数实现原理分析
2009年05月12日 星期二 下午 03:21
Select函数实现原理分析(转载)select需要驱动程序的支持,驱动程序实现fops内的poll函数。select通过每个设备文件对应的poll函数提供的信息判断当前是否有资源可用(如可读或写),如果有的话则返回可用资源的文件描述符个数,没有的话则睡眠,等待有资源变为可用时再被唤醒继续执行。下面我们分两个过程来分析select:1. select的睡眠过程支持阻塞操作的设备驱动通常会实现一组自身的等待队列如读/写等待队列用于支持上层(用户层)所需的BLOCK或NONBLOCK操作。当应用程序通过设备驱动访问该设备时(默认为BLOCK操作),若该设备当前没有数据可读或写,则将该用户进程插入到该设备驱动对应的读/写等待队列让其睡眠一段时间,等到有数据可读/写时再将该进程唤醒。select就是巧妙的利用等待队列机制让用户进程适当在没有资源可读/写时睡眠,有资源可读/写时唤醒。下面我们看看select睡眠的详细过程。select会循环遍历它所监测的fd_set(一组文件描述符(fd)的集合)内的所有文件描述符对应的驱动程序的poll函数。驱动程序提供的poll函数首先会将调用select的用户进程插入到该设备驱动对应资源的等待队列(如读/写等待队列),然后返回一个bitmask告诉select当前资源哪些可用。当select循环遍历完所有fd_set内指定的文件描述符对应的poll函数后,如果没有一个资源可用(即没有一个文件可供操作),则select让该进程睡眠,一直等到有资源可用为止,进程被唤醒(或者timeout)继续往下执行。 下面分析一下代码是如何实现的。select的调用path如下:sys_select - core_sys_select - do_select其中最重要的函数是do_select, 最主要的工作是在这里, 前面两个函数主要做一些准备工作。do_select定义如下:int do_select(int n, fd_set_bits *fds, s64 *timeout){struct poll_wqueues table;poll_table *wait;int retval, i;rcu_read_lock();retval = max_select_fd(n, fds);rcu_read_unlock();if (retval return retval;n = retval;poll_initwait(table);wait = table.pt;if (!*timeout)wait = NULL;retval = 0; //retval用于保存已经准备好的描述符数,初始为0for (;;) {unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;long __timeout;set_current_state(TASK_INTERRUPTIBLE); //将当前进程状态改为TASK_INTERRUPTIBLEinp = fds-in; outp = fds-out; exp = fds-ex;rinp = fds-res_in; routp = fds-res_out; rexp = fds-res_ex;for (i = 0; i 遍历每个描述符unsigned long in, out, ex, all_bits, bit = 1, mask, j;unsigned long res_in = 0, res_out = 0, res_ex = 0;const struct file_operations *f_op = NULL;struct file *file = NULL;in = *inp ; out = *outp ; ex = *exp ;all_bits = in | out | ex;if (all_bits == 0) {i = __NFDBITS; // //如果这个字没有待查找的描述符, 跳过这个长字(32位)continue;}for (j = 0; j 遍历每个长字里的每个位int fput_needed;if (i = n)break;if (!(bit all_bits))continue;file = fget_light(i, fput_needed);if (file) {f_op = file-f_op;MARK(fs_select, %d %lld,i, (long long)*ti
文档评论(0)