select()函数、poll()函数

转载 2012年03月24日 21:48:54
重读2.4 052 fs/select.c
target="_blank">http://docs.google.com/Doc?id=dcbsxfpf_213vc73kssk
2008-4-22
这里讨论的是select和poll的系统调用实现方式.
首先要熟悉的是内核中为poll和select定义的各种输入输出消息的含义:
             POLLIN   
有数据可以读入,read不会阻塞,注意:select的请情况下,即使到EOF也是ready的.
             POLLPRI   紧急数据,比如TCP,或者packet
模式的peseudo-terminal发现slave的状态有变化.
             POLLOUT   写入不会阻塞.
             POLLRDHUP :从Linux 2.6.17开始支持,不能再读取了. 比如tcp半连接状态.
             POLLERR   :输出出错
             POLLHUP   :Hang up (output only).
             POLLNVAL  :Invalid request: fd not open (output only).
       如果定义了宏 _XOPEN_SOURCE下面的宏也有效:
            POLLRDNORM : POLLIN.
            POLLRDBAND : 高优先级的数据read for read (generally unused on Linux).
            POLLWRNORM : Equivalent to POLLOUT.
            POLLWRBAND : Priority data may be written.
asmlinkage long
sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
{
        fd_set_bits fds;
        char *bits;
        .....
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) { /*获取timeout */
                ......
                if ((unsigned long) sec f_op && file->f_op->poll)
                                        mask = file->f_op->poll(file, wait); /*调用对应文件的poll函数*/
                                fput(file);
                        }
                        if ((mask & POLLIN_SET) && ISSET(bit,
__IN(fds,off))) {
                                SET(bit, __RES_IN(fds,off));
                                retval++;
                                wait = NULL; /*有结果就不再等了*/
                        }
                        ..... /*根据返回值更新结果*/
                }
                wait = NULL; /*只第一轮挂上等待队列即可*/
                if (retval || !__timeout || signal_pending(current))
/*超时,有文件ready,有信号,都返回*/
                        break;
                .....
                __timeout = schedule_timeout(__timeout); /*否则休眠...*/
        }
        current->state = TASK_RUNNING;
        poll_freewait(&table);
        /*
         * Up-to-date the caller timeout.
         */
        *timeout = __timeout;
        return retval;
}
这里的逻辑是这样:
  第一轮扫描的时候调用文件的poll函数(如,pipe_poll),
把证调用select的进程挂到文件所属的某个等待队列,以备文件ready的时候
唤醒这个队列.
  第二轮就不用挂载等待队列了,如果有ready的也就不再挂载了,让app尽快处理.
令:有信号量的时候要返回,因为signal的处理函数是在进程返回的时候才能得到服务.(见arch/../
kernel/entry.S.
简单看看一个poll的实现:
static unsigned int
pipe_poll(struct file *filp, poll_table *wait)
{
        unsigned int mask;
        struct inode *inode = filp->f_dentry->d_inode;
        poll_wait(filp, PIPE_WAIT(*inode), wait);
              
/*在wait(一个table)中申请poll_table_entry->wait挂入inode的等待队列*/
        /* Reading only -- no need for acquiring the semaphore.  */
        mask = POLLIN | POLLRDNORM;
        if (PIPE_EMPTY(*inode)) /*pipe空了,进程可以写入*/
                mask = POLLOUT | POLLWRNORM;
        if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
                mask |= POLLHUP; /*写入hangup,禁止写入*/
        if (!PIPE_READERS(*inode))
                mask |= POLLERR;
        return mask;
}
void __pollwait(struct file * filp, wait_queue_head_t * wait_address,   poll_table
*p)
{                                       / *current要在这个队列上等待*/  
/*select的wait table*/
        struct poll_table_page *table = p->table;
        if (!table || POLL_TABLE_FULL(table)) {
           .../* table初始化 */
        }
        /* Add a new entry */
        {
                struct poll_table_entry * entry = table->entry;
                table->entry = entry+1;
                 get_file(filp);
                 entry->filp = filp;
                entry->wait_address = wait_address; /*wait address就是上面的pipe的inode的wait
queue*/
                init_waitqueue_entry(&entry->wait, current);/*current是调用select的进程*/
                add_wait_queue(wait_address,&entry->wait); /*select的poll
table等待在inode上....*/
        }
}
可见,select的wait
table记载了当前调用select的进程现在在等待多少资源,加入了多少等待队列.
而sys_poll和select是极为类似的,不再分析了..
asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout)


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/78225/showart_1227077.html

linux网络编程之socket(十三):epoll 系列函数简介、与select、poll 的区别

一、epoll 系列函数简介#include int epoll_create(int size); int epoll_create1(int flags); int epoll_ctl(int ...

IO复用函数--Select,poll,epoll的比较

IO复用–Select,poll,epoll比较 IO复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,他就会通知该进程。IO复用适合的场合: 1》当客户处理多个文件描述符,交互式输入和...

【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程。I/O复...

基于tiny4412按键中断驱动的poll、select函数演示

poll函数应用背景文件阻塞、非阻塞操作对单个文件可能影响不大,但当我们以阻塞的方式打开多个文件时,有时会出现一种不好的现象,下面利用伪代码演示一下:#include int fd1,fd2;int ...

驱动函数poll 和 应用里的 select

http://blog.csdn.net/hanchaoman/article/details/7444337 http://www.oschina.net/question/565065_679...

详述socket编程之select()和poll()函数

select()函数和poll()函数均是主要用来处理多路I/O复用的情况。比如一个服务器既想等待输入终端到来,又想等待若干个套接字有客户请求到达,这时候就需要借助select或者poll函数了。 ...

Unix网络编程代码 第6章 I/O复用:select、poll和epoll函数

第6章 I/O复用:select、poll和epoll函数 6.4 str_cli函数(修订版) //使用select #define _POSIX_SOURCE #include /* soc...

select在并发中的两点限制与poll函数的使用

用select实现的并发服务器,能达到的并发数,受两方面限制 一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。 select中的fd_set集合容量的限制(FD_SETSIZE) ,这需要...

《UNIX网络编程卷1》读书笔记--第六章I/O复用:select和poll函数

前言I/O复用采用轮询的方式处理多个描述符,当有文件准备好时,就通知进程。 关注点 I/O复用的应用场合 采用I/O复用的客户端和服务器程序 I/O复用的应用场合1. 当客户处理多个描述符时(通常是交...

详述socket编程之select()和poll()函数

select()函数和poll()函数均是主要用来处理多路I/O复用的情况。比如一个服务器既想等待输入终端到来,又想等待若干个套接字有客户请求到达,这时候就需要借助select或者poll函数了。 ...
  • wdt3385
  • wdt3385
  • 2012年07月23日 16:52
  • 934
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:select()函数、poll()函数
举报原因:
原因补充:

(最多只允许输入30个字)