[arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作【转】
本文转载自:http://7071976.blog.51cto.com/7061976/1392082
《[arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作》涉及内核驱动函数二个,内核结构体零个,分析了内核驱动函数二个;可参考的相关应用程序模板或内核驱动模板二个,可参考的相关应用程序模板或内核驱动一个
一、概念:Poll是非阻塞IO----轮询操作
非阻塞 I/O 的应用程序常常使用 poll, select, 和 epoll 系统调用. poll, select 和 epoll 本质上有相同的功能: 每个允许一个进程来决定它是否可读或者写一个或多个文件而不阻塞.
Tip:select()和poll(),epoll查询是否可对设备进行无阻塞的访问,这几个系统调用最终又会引发设备驱动中的poll()函数被执行
PS:看到这感觉晕了,暂且不理会
二、使用场景:
它们常常用在必须使用多输入输出流的应用程序(如调用read,write字符设备驱动文件/dev/****)。因为这些调用也可阻塞进程直到任何一个给定集合的文件描述符可用来读或写.
三、相关函数
1、内核函数
内核驱动函数一)a)poll()函数原型:
|
1
|
unsigned int (*poll) (struct file *filp, poll_table *wait); |
作用:调用poll_wait(),将可能引起设备文件状态变化的等待队列头添加到poll_table.
返回值:返回是否能对设备进行无阻塞读写访问的掩码
放回值mask常量及函数
常量 说明
POLLIN 普通或优先级带数据可读
POLLRDNORM 普通数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级数据可读
POLLOUT 普通数据可写
POLLWRNORM 普通数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
内核驱动函数二)b)poll_wait()函数原型:
|
1
|
void poll_wait(struct file *filp, wait_queue_head_t *queue, poll_table *wait); |
作用:将可能引起设备文件状态变化的等待队列头添加到poll_table
2、应用程序poll函数
|
1
|
int poll(struct pollfd *fds, nfds_t nfds, int timeout) |
a) 参数:
fds 指向 struct pollfd 数组
nfds 指定 pollfd 数组元素的个数,也就是要监测几个 pollfd
timeout 时间参数,单位ms,1000ms=1s
Tip:fds可以是很多个文件(如网卡,按键),poll可以论寻fds[n]
b)结构体pollfd
struct pollfd {
int fd;
short events;
short revents;
};
3、总结:从应用程序的调用来看,并不需要理会内核函数中的参数poll_table *wait是什么,只需要调用poll_wait()
四、使用模板
模板一)a)内核程序模板
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
static DECLARE_WAIT_QUEUE_HEAD(waitq);//定义结构体名称为waitqpoll(struct file *file, poll_table *wait){//返回mask unsigned int mask = 0; poll_wait(file, &waitq, wait); if(...)//可读 { mask |= POLLIN | POLLRDNORM; //标识数据可获得 } if(...)//可写 { mask |= POLLOUT | POLLRDNORM; //标识数据可写入 } return mask;} |
模板二)b)测试程序模板
|
1
2
3
4
|
struct pollfd fds[n];fds[0].fd = fd;fds[0].events = POLLIN;poll(fds, n, 5000); |
c)再次理解下面几句
fds 指向 struct pollfd 数组
nfds 指定 pollfd 数组元素的个数,也就是要监测几个 pollfd
timeout 时间参数,单位ms,1000ms=1s
Tip:fds可以是很多个文件(如网卡,按键),poll可以论寻fds[n]
实例一)五、案例jz2440中断非阻塞驱动实例
1、 非阻塞内核按键驱动。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
//“irq_drv”,"irq_","irq"#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/delay.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//定义结构体名称为button_waitqstatic struct class *irq_class;static struct class_device *irq_class_dev;static int ev_press = 0;static unsigned char key_val;struct pin_desc{ unsigned int pin; unsigned int key_val;};struct pin_desc pins_desc[3] = { {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03},};static irqreturn_t irq_handle(int irq, void *dev__id){ //printk("irq = %d\n", irq); int pinval; struct pin_desc *pindesc = (struct pin_desc *)dev__id; pinval = s3c2410_gpio_getpin(pindesc->pin); if(!pinval){//按下 key_val = pindesc->key_val; }else{//松开 key_val = 0x80 | pindesc->key_val; } ev_press = 1; wake_up_interruptible(&button_waitq); return IRQ_RETVAL(IRQ_HANDLED);//warn:返回IRQ_HANDLED}static unsigned irq_drv_poll(struct file *file, poll_table *wait){ unsigned int mask = 0; poll_wait(file, &button_waitq, wait); // 不会立即休眠 if (ev_press) mask |= POLLIN | POLLRDNORM; return mask;}static int irq_drv_open(struct inode *inode, struct file *file){ printk("irq_dev read\n");// request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void * dev_id); dev_id随意 request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]); request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH, "s3", &pins_desc[1]); request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH, "s4", &pins_desc[2]); return 0;}static ssize_t irq_drv_read (struct file *file, char __user *buf, size_t count, loff_t *ppos){ if(count != 1)return -EINVAL; wait_event_interruptible(button_waitq, ev_press);//ev_press标志(if!(ev_press)),那么一直休眠 copy_to_user(buf, &key_val, 1);//一个 char 0xff ev_press = 0; return 1;//warn :return the size of val}static ssize_t irq_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){ printk("irq_dev write\n"); return 0;}static ssize_t irq_drv_release(struct inode *inode, struct file *file){ free_irq(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2]); return 0;}static struct file_operations irq_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = irq_drv_open, .write = irq_drv_write, .read = irq_drv_read, .release = irq_drv_release, .poll = irq_drv_poll,};int major;static int irq_drv_init(void){ major = register_chrdev(0, "irq_drv", &irq_drv_fops); // 注册, 告诉内核 if (major < 0) { printk(" can't register major number\n"); return major; } irq_class = class_create(THIS_MODULE, "irq_drv"); if (IS_ERR(irq_class)) return PTR_ERR(irq_class); irq_class_dev = class_device_create(irq_class, NULL, MKDEV(major, 0), NULL, "irq"); /* /dev/xyz */ if (IS_ERR(irq_class_dev)) return PTR_ERR(irq_class_dev); return 0;}static void irq_drv_exit(void){ unregister_chrdev(major, "irq_drv"); // 卸载 class_device_unregister(irq_class_dev); class_destroy(irq_class);}module_init(irq_drv_init);module_exit(irq_drv_exit);MODULE_LICENSE("GPL"); |
2、测试应用程序
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <unistd.h>#include <poll.h>/* irq */int main(int argc, char **argv){ int fd; unsigned char key_val; int cnt = 0; int ret; struct pollfd fds[1]; fd = open("/dev/irq", O_RDWR); if (fd < 0) { printf("can't open!\n"); exit(1); } fds[0].fd = fd; fds[0].events = POLLIN; while (1) { ret = poll(fds, 1, 5000); if(ret == 0){ printf("time out!\n"); }else{ read(fd, &key_val, 1); printf("key_Vals = 0x%x\n", key_val); } } return 0;}Makefile#myirq.binobjs := $(patsubst %c, %o, $(shell ls *.c))myarmgcc := /workspacearm/armlinuxgcc2626/bin/arm-linux-gccmyirq.bin:$(objs) $(myarmgcc) -o $@ $^ cp *.bin /opt/fsmini/%.o:%.c $(myarmgcc) -c -o $@ $<clean: rm -f *.bin *.o |
[arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作【转】的更多相关文章
- arm驱动linux异步通知与异步IO【转】
转自:http://blog.csdn.net/chinazhangzhong123/article/details/51638793 <[ arm驱动] linux异步通知与 异步IO> ...
- 嵌入式Linux内核开发工程师必须掌握的三十道题
如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师. 1. Linux中主要有哪几种内核锁?(进程同步与互斥) (1)自旋锁:非睡眠锁 (2)信号量: ...
- 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)
嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
- 🍛 餐厅吃饭版理解 IO 模型:阻塞 / 非阻塞 / IO 复用 / 信号驱动 / 异步
IO 概念 一个基本的 IO,它会涉及到两个系统对象,一个是调用这个 IO 的进程对象,另一个就是系统内核 (kernel).当一个 read 操作发生时,它会经历两个阶段: 通过 read 系统调用 ...
- 编码风格——linux内核开发的coding style
总结linux内核开发的coding style, 便于以后写代码时参考. 下面只是罗列一些规则, 具体说明可以参考: 内核源码(Documentation/CodingStyle) 01 - 缩进 ...
- 如何参与Linux内核开发(转)
本文来源于linux内核代码的Document文件夹下的Hoto文件.Chinese translated version of Documentation/HOWTO If you have any ...
- 如何参与linux 内核开发
如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以向中文版维护者求助.如果本翻译更新不及时或者翻 译存在问题,请联系中文版维护者. 英文版维护者: Gre ...
- Linux内核开发进阶书籍推荐(不适合初学者)
Linux内核开发进阶书籍推荐(不适合初学者) 很早之前就想写一篇文章总结一下Linux Kernel开发的相关资料,项目的原因,再加上家里的一些事情,一直没能找到闲暇,今天终于有些时间,希望可以完成 ...
随机推荐
- 如何将一个int转换成cstring
如:int a = 5;CString b;b.Format("%d",a);补充:如果a是double,或a是float的就是:b.Format("%f",a ...
- hdu 2713
#include<stdio.h> #include<string.h> int map[151000][2]; int max(int a,int b) { return ...
- Spring-IOC源码解读2.3-BeanDefinition的注册
在DefaultListAbleBeanFactory中通过一个HashMap持有载入的BeanDefinition信息 ,这个HashMap的定义在DefaultListAbleBeanFactor ...
- angularjs bootstrap 简介
1.angular特色 数据双向绑定 模块化 var myapp=angular.module... 控制器 myapp.controller(){} 2.bootstrap特色 栅格结构 cs ...
- php那些坑
1.创建数组不是new array(),是$aaa=array(),没有new,数组可以传入键值$aaa=array("key"=>"value"); 2 ...
- Mongodb报错:ERROR: child process failed, exited with error number 1
Mongodb在启动时报错: 2018-10-16T11:18:54.533+0800 I CONTROL [main] Automatically disabling TLS 1.0, to for ...
- java 文件复制操作
本案例采用第三方 jar 包完成,commons-io-2.5.jar, 这个 jar 对文件操作非常方便,大家可以尝试使用一下. 这里贴一个简单的 demo 供大家使用 import java.io ...
- ThreadGroup
http://blog.csdn.net/a352193394/article/details/39323427
- hadoop+yarn+hbase+storm+kafka+spark+zookeeper)高可用集群详细配置
配置 hadoop+yarn+hbase+storm+kafka+spark+zookeeper 高可用集群,同时安装相关组建:JDK,MySQL,Hive,Flume 文章目录 环境介绍 节点介绍 ...
- js上传文件研究
https://github.com/shengulong/javascript-file-upload