《[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()函数原型:
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()函数原型:
void poll_wait(struct file *filp, wait_queue_head_t *queue, poll_table *wait);
效果:将或许引起设备文件状况改变的等候行列头添加到poll_table
2、应用程序poll函数
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)内核程序模板
static DECLARE_WAIT_QUEUE_HEAD(waitq);//界说结构体名称为waitq
poll(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)测验程序模板
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、 非堵塞内核按键驱动。
//“irq_drv”,”irq_”,”irq”
#include
#include
#include
#include
#include
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//界说结构体名称为button_waitq
static 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(” cant 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、测验应用程序
#include
#include
#include
#include
#include
#include
*/
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(“cant 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.bin
objs := $(patsubst %c, %o, $(shell ls *.c))
myarmgcc := /workspacearm/armlinuxgcc2626/bin/arm-linux-gcc
myirq.bin:$(objs)
$(myarmgcc) -o $@ $^
cp *.bin /opt/fsmini/
%.o:%.c
$(myarmgcc) -c -o $@ $<
clean:
rm -f *.bin *.o
Curtiss Falcon