Select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程
Maxfd:文件描述符范围,比待检测文件描述符最大值大1
Readfds:读监控文件描述符集
Writefds:写监控文件描述符集
Exceptfds:异常监控文件描述符集
Timeout值为0,不管是否有文件满足要求,都立刻返回,无文件满足要求返回0,有文件满足要求返回一正值
Timeout为NULL,select将阻塞进程,直到某文件满足要求
Timeout值为正整数(所指向结构体其某成员值),即超时时间
——————/
Select调用返回值情况:
正常情况返回满足要求文件描述符个数
经过timeout等待后仍无文件满足要求,返回0
如select被某信号中断,返回-1并设置errno为EINTR
如出错,返回-1并设置相应errno
——————/
Select系统调用使用方法:
1. 将要监控文件添加到文件描述符集
2. 调用Select监控
3. 判断文件是否发生变化
——————/
系统提供4个宏对描述符集进行操作:
宏FD_CLR从文件描述符集fdset中清除文件描述符fd;
宏FD_ZERO清空文件描述符集fdset;
在调用select后使用FD_ISSET来检测文件描述符集fdset中的文件fd是否发生了变化
——————/
select系统调用可能会阻塞进程,该调用由驱动poll方法实现,原型:
1. 使用poll_wait将等待队列添加到poll_table中
2. 返回描述设备是否可读或可写的掩码
——————/位掩码
POLLIN设备可读
POLLRDNORM数据可读
POLLOUT设备可写
POLLWRNORM数据可写
设备可读通常返回(POLLIN|POLLRDNORM )
设备可写通常返回(POLLOUT|POLLWRNORM )
——————/
——————/
int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set*exceptfds, const struct timeval *timeout)
——————/
Maxfd:文件描述符范围,比待检测文件描述符最大值大1
Readfds:读监控文件描述符集
Writefds:写监控文件描述符集
Exceptfds:异常监控文件描述符集
Timeout值为0,不管是否有文件满足要求,都立刻返回,无文件满足要求返回0,有文件满足要求返回一正值
Timeout为NULL,select将阻塞进程,直到某文件满足要求
Timeout值为正整数(所指向结构体其某成员值),即超时时间
——————/
Select调用返回值情况:
正常情况返回满足要求文件描述符个数
经过timeout等待后仍无文件满足要求,返回0
如select被某信号中断,返回-1并设置errno为EINTR
如出错,返回-1并设置相应errno
——————/
Select系统调用使用方法:
1. 将要监控文件添加到文件描述符集
2. 调用Select监控
3. 判断文件是否发生变化
——————/
系统提供4个宏对描述符集进行操作:
#include <sys/select.h>
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)
宏FD_SET将文件描述符fd添加到文件描述符集fdset中;
宏FD_CLR从文件描述符集fdset中清除文件描述符fd;
宏FD_ZERO清空文件描述符集fdset;
在调用select后使用FD_ISSET来检测文件描述符集fdset中的文件fd是否发生了变化
——————/
FD_ZERO(&fds); //清空集合
FD_SET(fd1,&fds); //设置描述符
FD_SET(fd2,&fds); //设置描述符
maxfdp=fd1+1; //描述符最大值加1,假设fd1>fd2
switch(select(maxfdp,&fds,NULL,NULL,&timeout))
case -1:
exit(-1); //select错误,退出程序
case 0:
break;
default:
if(FD_ISSET(fd1,&fds)) //测试fd1是否可读
——————/
select系统调用可能会阻塞进程,该调用由驱动poll方法实现,原型:
unsigned int (*poll)(struct file *filp,poll_table *wait)
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
——————/
1. 使用poll_wait将等待队列添加到poll_table中
2. 返回描述设备是否可读或可写的掩码
——————/位掩码
POLLIN设备可读
POLLRDNORM数据可读
POLLOUT设备可写
POLLWRNORM数据可写
设备可读通常返回(POLLIN|POLLRDNORM )
设备可写通常返回(POLLOUT|POLLWRNORM )
——————/
static unsigned int mem_poll(struct file *filp,poll_table *wait)
{
struct scull_pipe *dev =filp->private_data;
unsigned int mask =0;
poll_wait(filp,&dev->inq,wait);
if (可读)
mask = POLLIN |POLLRDNORM;/*设备可读,返回掩码*/
return mask;
}
Poll方法仅做一登记,真正阻塞发生在select.c的do_select函数
——————/
Select //app
do_select //kernel
for(;;) {
for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) //因监控多个文件
struct file *file= fget_light(i, &fput_needed);
struct file_operations *f_op= file->f_op;
mask = (*f_op->poll)(file, wait);
// #define POLLIN_SET (POLLRDNORM | POLLIN |……)
if ((mask & POLLIN_SET) && (in & bit))
// (in & bit)判断file可读否,但poll返回可写,不应将retval++
retval++; //初始值0
if (retval || timed_out || signal_pending(current))
break; //跳出最外层循环不阻塞,否则执行下句带超时可唤醒调度
poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,to, slack))