linux select&poll
来源:互联网 发布:网络语言暴力的例子 编辑:程序博客网 时间:2024/05/23 02:05
还有一个与设备阻塞与非阻塞访问息息相关的论题,即select和poll,select和poll的本质一样,前者在BSD Unix中引入,后者在System V中引入。poll和select用于查询设备的状态,以便用户程序获知是否能对设备进行非阻塞的访问,它们都需要设备驱动程序中的poll函数支持。
驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下:
void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);
poll_wait函数所做的工作是把当前进程添加到wait参数指定的等待列表(poll_table)中。下面我们给globalvar的驱动添加一个poll函数:
static unsigned int globalvar_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(filp, &outq, wait);
//数据是否可获得?
if (flag != 0)
{
mask |= POLLIN | POLLRDNORM; //标示数据可获得
}
return mask;
}
需要说明的是,poll_wait函数并不阻塞,程序中poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待outq信号量可获得,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪, select/poll都立即返回。
我们编写一个用户态应用程序来测试改写后的驱动。程序中要用到BSD Unix中引入的select函数,其原型为:
int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合,numfds的值是需要检查的号码最高的文件描述符加1。timeout参数是一个指向struct timeval类型的指针,它可以使select()在等待timeout时间后若没有文件描述符准备好则返回。struct timeval数据结构为:
struct timeval
{
int tv_sec; /* seconds */
int tv_usec; /* microseconds */
};
除此之外,我们还将使用下列API:
FD_ZERO(fd_set *set)――清除一个文件描述符集;
FD_SET(int fd,fd_set *set)――将一个文件描述符加入文件描述符集中;
FD_CLR(int fd,fd_set *set)――将一个文件描述符从文件描述符集中清除;
FD_ISSET(int fd,fd_set *set)――判断文件描述符是否被置位。
下面的用户态测试程序等待/dev/globalvar可读,但是设置了5秒的等待超时,若超过5秒仍然没有数据可读,则输出"No data within 5 seconds":
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
int fd, num;
fd_set rfds;
struct timeval tv;
fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
if (fd != - 1)
{
while (1)
{
//查看globalvar是否有输入
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
//设置超时时间为5s
tv.tv_sec = 5;
tv.tv_usec = 0;
select(fd + 1, &rfds, NULL, NULL, &tv);
//数据是否可获得?
if (FD_ISSET(fd, &rfds))
{
read(fd, &num, sizeof(int));
printf("The globalvar is %d/n", num);
//输入为0,退出
if (num == 0)
{
close(fd);
break;
}
}
else
printf("No data within 5 seconds./n");
}
}
else
{
printf("device open failure/n");
}
}
开两个终端,分别运行程序:一个对globalvar进行写,一个用上述程序对globalvar进行读。当我们在写终端给globalvar输入一个值后,读终端立即就能输出该值,当我们连续5秒没有输入时,"No data within 5 seconds"
驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下:
void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);
poll_wait函数所做的工作是把当前进程添加到wait参数指定的等待列表(poll_table)中。下面我们给globalvar的驱动添加一个poll函数:
static unsigned int globalvar_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(filp, &outq, wait);
//数据是否可获得?
if (flag != 0)
{
mask |= POLLIN | POLLRDNORM; //标示数据可获得
}
return mask;
}
需要说明的是,poll_wait函数并不阻塞,程序中poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待outq信号量可获得,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪, select/poll都立即返回。
我们编写一个用户态应用程序来测试改写后的驱动。程序中要用到BSD Unix中引入的select函数,其原型为:
int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合,numfds的值是需要检查的号码最高的文件描述符加1。timeout参数是一个指向struct timeval类型的指针,它可以使select()在等待timeout时间后若没有文件描述符准备好则返回。struct timeval数据结构为:
struct timeval
{
int tv_sec; /* seconds */
int tv_usec; /* microseconds */
};
除此之外,我们还将使用下列API:
FD_ZERO(fd_set *set)――清除一个文件描述符集;
FD_SET(int fd,fd_set *set)――将一个文件描述符加入文件描述符集中;
FD_CLR(int fd,fd_set *set)――将一个文件描述符从文件描述符集中清除;
FD_ISSET(int fd,fd_set *set)――判断文件描述符是否被置位。
下面的用户态测试程序等待/dev/globalvar可读,但是设置了5秒的等待超时,若超过5秒仍然没有数据可读,则输出"No data within 5 seconds":
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
int fd, num;
fd_set rfds;
struct timeval tv;
fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
if (fd != - 1)
{
while (1)
{
//查看globalvar是否有输入
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
//设置超时时间为5s
tv.tv_sec = 5;
tv.tv_usec = 0;
select(fd + 1, &rfds, NULL, NULL, &tv);
//数据是否可获得?
if (FD_ISSET(fd, &rfds))
{
read(fd, &num, sizeof(int));
printf("The globalvar is %d/n", num);
//输入为0,退出
if (num == 0)
{
close(fd);
break;
}
}
else
printf("No data within 5 seconds./n");
}
}
else
{
printf("device open failure/n");
}
}
开两个终端,分别运行程序:一个对globalvar进行写,一个用上述程序对globalvar进行读。当我们在写终端给globalvar输入一个值后,读终端立即就能输出该值,当我们连续5秒没有输入时,"No data within 5 seconds"
- linux select poll
- linux select&poll
- linux之select/poll
- linux select poll epoll
- linux epoll poll select
- Linux的poll和select
- linux select pselect poll 异同
- Linux epoll poll select 详解
- LINUX多路复用select,poll,epoll
- Linux select、poll、epoll解析
- LINUX多路复用select,poll,epoll
- Linux学习:多路复用 select / poll
- linux下select 和 poll的用法
- linux下select 和 poll的用法
- linux下select和poll的用法
- linux下select和poll的用法
- linux下select 和 poll的用法
- Linux下select和poll的用法
- 浅谈构造函数(c#)
- zoj 2124 Perfect Pth Powers
- java nio基础教程
- Cairngorm简介(转)
- 发布了“我开发了一个木马”之后
- linux select&poll
- 系统架构-基础篇-(高性能基础建设说明与选型条件)
- 认识JVM--第一篇
- 为了下载!
- Android 应用程序版本
- Cmake introduction 3
- C++ socket实现获取局域网IP&MAC
- boos::asio- based SuperCom
- 认识JVM--第二篇