poll和select操作
一个应用使用设备时采用
阻塞IO:会使进程休眠,让出CPU,高效
非阻塞IO:不停查询,占用CPU,低效
一个应用控制多个设备文件来达到需求,但当一个设备文件发生阻塞时调用进程被休眠,
其他设备文件就停止工作
阻塞方式:在read调用时阻塞
应用–>read()–>sys_read—>xxx_read例程
IO复用:阻塞一组文件的描述符
应用–>poll()/select()–>sys_poll—>xxx_poll–>poll_wait例程
比如一个应用中使用多个串口,一个串口在等待接收数据而阻塞,
其他串口已接收到数据不能读.
linux应用中使用select()/poll()实现
select()介绍较多,poll()与它功能相同,有更方便的接口.
poll()函数也是用于IO复用的函数.
4个按键用read读取和键盘读取信息
应用部分
#include <poll.h>
int main(void)
{
struct pollfd pfds[2];
pfds[0].fd = 0; //标准输入文件描述符
pfds[0].events = POLLIN; //是否可读
pfds[1].fd = fd; //开发板中的键盘
pfds[1].events = POLLIN; //按键是否触发中断
if(pfds[0].revents & POLLIN){
fgets(buf,sizeof(buf),stdin);
printf("%s",buf);
}
if(pfds[1].revents & POLLIN){
ret = read(fd,&event,sizeof(event));
}
}
驱动部分
//设计一个描述按键的结构体类型
struct buttons{
char *name; //名称
unsigned int irqno; //中断号
int gpio; //按键对应的gpio口
int code; //键值
unsigned long flags; //触发方式
};
//定义一个数组来保存多个按键的数据
struct buttons buttons_set[] = {
[0] = {
.name = "key1_up",
.irqno = IRQ_EINT(0),
.gpio = S5PV210_GPH0(0),
.code = KEY_UP,
.flags = IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
},略
}
static struct file_operations fops = {
.poll = button_poll,
};
static int __init button_init(void)
{
for(i = 0; i < ARRAY_SIZE(buttons_set);i++){
ret= request_irq(buttons_set[i].irqno,button_irq_svc,
buttons_set[i].flags,buttons_set[i].name,&buttons_set[i]);
}
static void __exit button_exit(void)
{
for(i = 0; i < ARRAY_SIZE(buttons_set);i++){
free_irq(buttons_set[i].irqno,&buttons_set[i]);
}
}
中断程序
irqreturn_t button_irq_svc(int irqno, void *dev)
{
p = (struct buttons *)dev;
找到
p->
p->code
p->value
}
小结:
IO模型
同步:
阻塞IO read
非阻塞IO open(O_NONBLOCK)read
异步:
阻塞IO poll
非阻塞IO 类