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

select和poll函数讲解

阻塞方式block,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回。使用Select就可以完成非阻塞non-block,就是进程或线程执...
  • cqybhjz
  • cqybhjz
  • 2016年04月23日 21:00
  • 1481

UNIX网络编程--I/O复用:select函数和poll函数讲解(六)

一、select函数    select函数允许进程指示内核等待多个事件中的任一个发生,并仅在一个或者多个事件发生或经过某个指定的时间后才唤醒进程。 我们所关心的描述字不受限于套接口,任何描述字都...
  • yusiguyuan
  • yusiguyuan
  • 2013年09月20日 15:00
  • 4519

轮询操作 (select poll)

原文地址:http://blog.csdn.net/unbutun/article/details/4722448 L轮询函数 轮询的概念和作用 使用非阻塞I/O的应用程序通常会使用sele...
  • kangear
  • kangear
  • 2012年10月05日 15:42
  • 1353

select()和poll()的区别是什么?

Whats thedifference between select() and poll()? 原文地址:http://www.unixguide.net/network/socketfaq/2....
  • mituan2008
  • mituan2008
  • 2011年08月17日 16:21
  • 6222

UNIX中的Poll函数

poll函数和select函数非常相似,但是函数接口不一样。   int poll(struct pollfd fdarray[], nfds_t nfds, int timeout); ...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013年03月12日 16:43
  • 3755

select函数与poll函数

select函数 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:   (1)当客户处理多个描述字时(一般是交互式输入和网络套接口...
  • ZHYFXY
  • ZHYFXY
  • 2017年03月30日 21:08
  • 144

select()函数、poll()函数

重读2.4 052 fs/select.c target="_blank">http://docs.google.com/Doc?id=dcbsxfpf_213vc73kssk 2008-4-22...
  • lifan_3a
  • lifan_3a
  • 2014年07月01日 23:40
  • 265

采用管道函数创建有名管道,使用select函数替代使用poll函数实验多路复用

创建两个有名管道,获取3个文件描述符(2个管道,1个标准输入),然后初始化读文件描述符,select监视文件描述符 的文件读写,管道1输出到屏幕上,管道2输出到屏幕上,标准输入‘Q’来进行判读是否退出...
  • zm1_1zm
  • zm1_1zm
  • 2017年08月15日 15:23
  • 163

select/poll使用简单分析

简单分析一下linux下select和poll的使用,加深下自己的记忆,如有不足或错误之处,还请各位道友指导!...
  • u014627661
  • u014627661
  • 2016年03月17日 21:15
  • 717

Linux Poll函数初级实例

网络编程
  • XW370168409
  • XW370168409
  • 2016年12月01日 22:36
  • 389
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:select()函数、poll()函数
举报原因:
原因补充:

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