Chinaunix首页 | 论坛 | 博客
  • 博客访问: 392796
  • 博文数量: 80
  • 博客积分: 1982
  • 博客等级: 上尉
  • 技术积分: 1737
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-26 22:41
文章存档

2013年(9)

2012年(71)

分类: LINUX

2012-11-23 16:14:14

    select 系统调用用于多路监控,当没有一个文件满足要求时,select 将阻塞调用进程。
int select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set
           *exceptfds, const struct timeval *timeout)
maxfd:文件描述符的范围,比待检测的最大文件描述符大 1
struct timeval {
    long tv_sec; /* seconds */
    long tv_usec; /* microseconds */
};
    timeout 值为 0,不管是否有文件满足要求,都立刻返回,无文件满足要求返回 0,有文件满足要求返回一个正值。
    timeout 值为 NULL,select 将阻塞进程,直到某个文件满足要求。
    timeout 值为正整数,就是等待的最长时间,即 select 在 timeout 时间内阻塞进程。
    与 select 系统调用对应的 poll 设备方法如下:
unsigned int (*poll) (struct file *file, poll_table *wait);
typedef struct poll_table_struct {
    poll_queue_proc qproc;
} poll_table;
 
1.使用 poll_wait 将等待队列添加到 poll_table 中。
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
    if (p && wait_address)
        p->qproc(filp, wait_address, p);
}
2.返回描述设备是否可读或可写的掩码。
if(有数据可读) //根据具体的驱动实现
    mask = POLLIN | POLLRDNORM;
return mask;
 
位掩码:
POLLIN 设备可读
POLLRDNORM 数据可读
POLLOUT 设备可写
POLLWRNORM 数据可写
设备可读通常返回 (POLLIN | POLLRDNORM)
设备可写通常返回 (POLLOUT | POLLWRNORM)
 
do_select
    poll_initwait(&table);
        init_poll_funcptr(&pwq->pt, __pollwait);
    for (;;) {
        for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
            if (f_op && f_op->poll)
            mask = (*f_op->poll)(file, retval ? NULL : wait);
        }
        /* 返回的条件是 1.有文件可读或可写 2.超时 3.有信号 */
        if (retval || timed_out || signal_pending(current))
            break;
        poll_schedule_timeout //阻塞发生在select系统调用的实现中
    }
 
    与 select 系统调用类似,poll 系统调用同样可以完成上述功能。
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
    int fd;  /* file descriptor */
    short events; /* request events */
    short revents; /* returned events */ 
};
nfds:要监控的文件数量
timeout:超时时间,以 ms 为单位
 
select 用户空间编程示例:
    FD_ZERO(&fds);  //清空集合
    FD_SET(fd1, &fds);  //设置描述符
    FD_SET(fd2, &fds);
    maxfd = fd1 + 1;
    switch(select(maxfd, &fds, NULL, NULL, &timeout))
    {//判断返回值
        case xxx: if(FD_ISSET(fd1,&fds))
        ……
    }
    ……
 
    系统提供了几个宏对描述符集进行操作:
    void FD_SET(int fd, fd_set *fdset)
    void FD_CLR(int fd, fd_set *fdset)
    void FD_ZERO(fd_set *fdset)
    void FD_ISSET(int fd, fd_set *fdset)

poll 用户空间编程示例:
    struct pollfd fds[1];
    fds[0].fd     = fd;
    fds[0].events = POLLIN;
    ret = poll(fds, 1, 5000);
    ……

                       ——忠于梦想 勇于实践    linux_xpj@opencores.org
阅读(1309) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~