栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux阻塞与非阻塞IO–非阻塞式IO

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux阻塞与非阻塞IO–非阻塞式IO

Linux阻塞与非阻塞IO–非阻塞式IO

非阻塞式IO可通过以下方式实现:
select 、poll 、 epoll

select:
在APP中
select的使用,需要按照以下四部进行

(1)fd_set readfds ;    int fd;
(2)FD_ZERO(&readfds);//清空所有fd_set的所有位,每个位对应一个描述符(也就是关心的事件)
(3)FD_SET(fd, &readfds);//设置fd_set中的某一位
(4)select(fd + 1, &readfds, NULL, NULL, &timeout);
			//函数原型:int select(int nfds, fd_set *readfds, fd_set *writefds,  fd_set *exceptfds, struct timeval *timeout);
			//通过返回值,可判断是否有事件发生
(5)FD_ISSET(fd, &readfds);//查看具体哪个事件发生,如果实现要的某个事件,则进行下一步操作

在驱动中:
需加入下边语句

if (filp->f_flags & O_NONBLOCK) { 
 if(atomic_read(&dev->releasekey) == 0) 
 return -EAGAIN;
 }

poll

驱动中有个结构体

struct file_operations {
	int (*open) (struct inode *, struct file *);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);**
	...
}

这个函数指针 (*poll) (struct file *, struct poll_table_struct *);需要自己去实现,然后在申请字符设备时使用。。
在APP中,poll需要做以下操作:

(1)struct pollfd fds;
			 struct pollfd {
			               int   fd;         
			               short events;     
			               short revents;    
			           };

(2)初始化fds的成员;
				fds.fd = fd;//想要监视的描述符
				fds.events = POLLIN;//事件类型
(3)poll(&fds, 1, 500);//函数原型如下

				int poll(struct pollfd *fds, nfds_t nfds, int timeout);//三个参数分别为,pollfd结构体,描述符数量,超时时间
				通过判断返回值(事件发生时,对应的描述符就会被返回),就可知道是否有对应事件发生

当对应事件发生时,驱动会自动调函数指针unsigned int (*poll) (struct file *, struct poll_table_struct *);

例程:

//驱动

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define IMX6UIRQ_CNT		1			
#define IMX6UIRQ_NAME		"noblockio"	
#define KEY0VALUE			0x01		
#define INVAKEY				0xFF		
#define KEY_NUM				1			


struct irq_keydesc {
	int gpio;								
	int irqnum;								
	unsigned char value;					
	char name[10];							
	irqreturn_t (*handler)(int, void *);	
};


struct imx6uirq_dev{
	dev_t devid;				
	struct cdev cdev;		                 
	struct class *class;	
	struct device *device;	
	int major;				
	int minor;				
	struct device_node	*nd; 	
	atomic_t keyvalue;		
	atomic_t releasekey;	
	struct timer_list timer;
	struct irq_keydesc irqkeydesc[KEY_NUM];	
	unsigned char curkeynum;				

	wait_queue_head_t r_wait;	
};

struct imx6uirq_dev imx6uirq;	


static irqreturn_t key0_handler(int irq, void *dev_id)
{
	struct imx6uirq_dev *dev = (struct imx6uirq_dev*)dev_id;

	dev->curkeynum = 0;
	dev->timer.data = (volatile long)dev_id;
	mod_timer(&dev->timer, jiffies + msecs_to_jiffies(10));	
	return IRQ_RETVAL(IRQ_HANDLED);
}


void timer_function(unsigned long arg)
{
	unsigned char value;
	unsigned char num;
	struct irq_keydesc *keydesc;
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)arg;

	num = dev->curkeynum;
	keydesc = &dev->irqkeydesc[num];

	value = gpio_get_value(keydesc->gpio); 	
	if(value == 0){ 						
		atomic_set(&dev->keyvalue, keydesc->value);
	}
	else{ 									
		atomic_set(&dev->keyvalue, 0x80 | keydesc->value);
		atomic_set(&dev->releasekey, 1);	
	}               

	
	if(atomic_read(&dev->releasekey)) {	
		
		wake_up_interruptible(&dev->r_wait);
	}
}


static int keyio_init(void)
{
	unsigned char i = 0;
	char name[10];
	int ret = 0;
	
	imx6uirq.nd = of_find_node_by_path("/key");
	if (imx6uirq.nd== NULL){
		printk("key node not find!rn");
		return -EINVAL;
	} 

	
	for (i = 0; i < KEY_NUM; i++) {
		imx6uirq.irqkeydesc[i].gpio = of_get_named_gpio(imx6uirq.nd ,"key-gpio", i);
		if (imx6uirq.irqkeydesc[i].gpio < 0) {
			printk("can't get key%drn", i);
		}
	}
	
	
	for (i = 0; i < KEY_NUM; i++) {
		memset(imx6uirq.irqkeydesc[i].name, 0, sizeof(name));	
		sprintf(imx6uirq.irqkeydesc[i].name, "KEY%d", i);		
		gpio_request(imx6uirq.irqkeydesc[i].gpio, name);
		gpio_direction_input(imx6uirq.irqkeydesc[i].gpio);	
		imx6uirq.irqkeydesc[i].irqnum = irq_of_parse_and_map(imx6uirq.nd, i);
#if 0
		imx6uirq.irqkeydesc[i].irqnum = gpio_to_irq(imx6uirq.irqkeydesc[i].gpio);
#endif
	}

	
	imx6uirq.irqkeydesc[0].handler = key0_handler;
	imx6uirq.irqkeydesc[0].value = KEY0VALUE;
	
	for (i = 0; i < KEY_NUM; i++) {
		ret = request_irq(imx6uirq.irqkeydesc[i].irqnum, imx6uirq.irqkeydesc[i].handler, 
		                 IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, imx6uirq.irqkeydesc[i].name, &imx6uirq);
		if(ret < 0){
			printk("irq %d request failed!rn", imx6uirq.irqkeydesc[i].irqnum);
			return -EFAULT;
		}
	}

	
    init_timer(&imx6uirq.timer);
    imx6uirq.timer.function = timer_function;

	
	init_waitqueue_head(&imx6uirq.r_wait);
	return 0;
}


static int imx6uirq_open(struct inode *inode, struct file *filp)
{
	filp->private_data = &imx6uirq;	
	return 0;
}

 
static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
	int ret = 0;
	unsigned char keyvalue = 0;
	unsigned char releasekey = 0;
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

	if (filp->f_flags & O_NONBLOCK)	{ 
		if(atomic_read(&dev->releasekey) == 0)	
			return -EAGAIN;
	} else {							
		
 		ret = wait_event_interruptible(dev->r_wait, atomic_read(&dev->releasekey)); 
		if (ret) {
			goto wait_error;
		}
	}

	keyvalue = atomic_read(&dev->keyvalue);
	releasekey = atomic_read(&dev->releasekey);

	if (releasekey) { 	
		if (keyvalue & 0x80) {
			keyvalue &= ~0x80;
			ret = copy_to_user(buf, &keyvalue, sizeof(keyvalue));
		} else {
			goto data_error;
		}
		atomic_set(&dev->releasekey, 0);
	} else {
		goto data_error;
	}
	return 0;

wait_error:
	return ret;
data_error:
	return -EINVAL;
}

 
unsigned int imx6uirq_poll(struct file *filp, struct poll_table_struct *wait)
{
	unsigned int mask = 0;
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

	poll_wait(filp, &dev->r_wait, wait);	
	
	if(atomic_read(&dev->releasekey)) {		
		mask = POLLIN | POLLRDNORM;			
	}
	return mask;
}


static struct file_operations imx6uirq_fops = {
	.owner = THIS_MODULE,
	.open = imx6uirq_open,
	.read = imx6uirq_read,
	.poll = imx6uirq_poll,
};


static int __init imx6uirq_init(void)
{
	
	if (imx6uirq.major) {
		imx6uirq.devid = MKDEV(imx6uirq.major, 0);
		register_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
	} else {
		alloc_chrdev_region(&imx6uirq.devid, 0, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
		imx6uirq.major = MAJOR(imx6uirq.devid);
		imx6uirq.minor = MINOR(imx6uirq.devid);
	}

	
	cdev_init(&imx6uirq.cdev, &imx6uirq_fops);
	cdev_add(&imx6uirq.cdev, imx6uirq.devid, IMX6UIRQ_CNT);

	
	imx6uirq.class = class_create(THIS_MODULE, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.class)) {	
		return PTR_ERR(imx6uirq.class);
	}

	
	imx6uirq.device = device_create(imx6uirq.class, NULL, imx6uirq.devid, NULL, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.device)) {
		return PTR_ERR(imx6uirq.device);
	}
		
	
	atomic_set(&imx6uirq.keyvalue, INVAKEY);
	atomic_set(&imx6uirq.releasekey, 0);
	keyio_init();
	return 0;
}


static void __exit imx6uirq_exit(void)
{
	unsigned i = 0;
	
	del_timer_sync(&imx6uirq.timer);	
		
		
	for (i = 0; i < KEY_NUM; i++) {
		free_irq(imx6uirq.irqkeydesc[i].irqnum, &imx6uirq);
	}
	cdev_del(&imx6uirq.cdev);
	unregister_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT);
	device_destroy(imx6uirq.class, imx6uirq.devid);
	class_destroy(imx6uirq.class);
}	
	
module_init(imx6uirq_init);
module_exit(imx6uirq_exit);
MODULE_LICENSE("GPL");
	
	
//APP
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "poll.h"
#include "sys/select.h"
#include "sys/time.h"
#include "linux/ioctl.h"



int main(int argc, char *argv[])
{
	int fd;
	int ret = 0;
	char *filename;
	struct pollfd fds;
	fd_set readfds;
	struct timeval timeout;
	unsigned char data;

	if (argc != 2) {
		printf("Error Usage!rn");
		return -1;
	}

	filename = argv[1];
	fd = open(filename, O_RDWR | O_NONBLOCK);	
	if (fd < 0) {
		printf("Can't open file %srn", filename);
		return -1;
	}

#if 0
	
	fds.fd = fd;
	fds.events = POLLIN;
		
	while (1) {
		ret = poll(&fds, 1, 500);
		if (ret) {	
			ret = read(fd, &data, sizeof(data));
			if(ret < 0) {
				
			} else {
				if(data)
					printf("key value = %d rn", data);
			} 	
		} else if (ret == 0) { 	
			
		} else if (ret < 0) {	
			
		}
	}
#endif

	while (1) {	
		FD_ZERO(&readfds);
		FD_SET(fd, &readfds);
		
		timeout.tv_sec = 0;
		timeout.tv_usec = 500000; 
		ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
		switch (ret) {
			case 0: 	
				
				break;
			case -1:	
				
				break;
			default:  
				if(FD_ISSET(fd, &readfds)) {
					ret = read(fd, &data, sizeof(data));
					if (ret < 0) {
						
					} else {
						if (data)
							printf("key value=%drn", data);
					}
				}
				break;
		}	
	}

	close(fd);
	return ret;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/460871.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号