当前位置: 首页 > news >正文

6.Linux按键驱动-阻塞与非阻塞

默认打开文件时候是阻塞的

当设置打开方式为非阻塞时,无数据时会返回。
当设置打开方式为阻塞时,无数据的时候会等待

1.设置打开方式为非阻塞
在这里插入图片描述
立即返回,无法读出,返回-1
在这里插入图片描述

2.设置为阻塞
在这里插入图片描述

核心在于驱动程序中的.read函数的支持
在这里插入图片描述

3.代码实现
应用程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>static int fd;/* 信号处理函数 */
/*static void sig_func(int sig)
{int val;int num;read(fd,&val,4);num  = val >>8;printf("get button: %d val = %d\n", num, val - num *(1 << 8));
}*/int main(int argc, char** argv)
{int val;int num;struct pollfd fds[1];int timeout_ms = 5000;int ret;int flags;int i;/* 判断输入值是否合法 */if(argc != 2){printf("Usage ./button_app /dev/devname\n");return -1;}fd = open(argv[1], O_RDONLY);if (fd == -1){printf("open err\n");}else{printf("open success\n");}/* 初始化文件监听描述符 *//*fds[0].fd     = fd;fds[0].events = POLLIN;*//*绑定SIGIO和sig_func *///signal(SIGIO, sig_func);/* APP把自己的pid告诉驱动 *///fcntl(fd, F_SETOWN, getpid());/* APP把自己的pid告诉驱动程序 *///flags = fcntl(fd,F_GETFL);/* 获得标志位 *///fcntl(fd, F_SETFL, flags | FASYNC);/* 使能异步通知 *///printf("设置了FASYNC\n");/*while(1){printf("www.100ask.net \n");sleep(2);}*//*while(1){ret = poll(fds, 1, timeout_ms);if((ret == 1) && (fds[0].revents == POLLIN)){read(fd, &val, 4);num  = val >>8;printf("get button: %d val = %d\n", num, val - num *(1 << 8));}else{printf("timeout\n");}}*//* 设置打开方式为非阻塞 */fcntl(fd,F_SETFL,O_NONBLOCK);for (i = 0; i < 10; i++){if (read(fd, &val, 4) == 4)printf("get button: 0x%x\n", val);elseprintf("get button: -1\n");}/* 设置打开方式为阻塞 */flags = fcntl(fd,F_GETFL);fcntl(fd,F_SETFL,flags & ~O_NONBLOCK);while(1){if (read(fd, &val, 4) == 4){num  = val >>8;printf("get button: %d val = %d\n", num, val - num *(1 << 8));}elseprintf("get button: -1\n");}close(fd);return 0;
}

驱动程序:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/fcntl.h>/* 定义结构体来描述gpio */
struct gpio_key{int gpio;struct gpio_desc* gpiod;int flag;int irq;
};/* 定义全局变量来存储设备树中的所有gpio节点信息 */
static struct gpio_key* gpio_keys_100ask;/* 字符设备的主设备号 */
static unsigned int major = 0;
static struct class *gpio_class;
//static int g_key = 0;/* 定义等待队列 */
static DECLARE_WAIT_QUEUE_HEAD(gpio_key_wait);
struct fasync_struct * button_fasync;/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;#define NEXT_POS(x) ((x+1) % BUF_LEN)int is_key_buf_empty(void)
{return (r == w);
}int is_key_buf_full(void)
{return (r == NEXT_POS(w));
}void put_key(int key)
{if (!is_key_buf_full()){g_keys[w] = key;w = NEXT_POS(w);}
}int get_key(void)
{int key = 0;if (!is_key_buf_empty()){key = g_keys[r];r = NEXT_POS(r);}return key;
}static ssize_t gpio_read(struct file *fp, char __user *buf, size_t size, loff_t * offset)
{int err;int key;if(is_key_buf_empty() && (fp->f_flags & O_NONBLOCK)){return -EAGAIN;}//wait_event_interruptible(gpio_key_wait, !is_key_buf_empty());key = get_key();//err = copy_to_user(buf, &g_key, 4);err = copy_to_user(buf, &key, 4);//g_key = 0;//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 4;
}static unsigned int gpio_poll(struct file *fp, struct poll_table_struct *wait)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);poll_wait(fp, &gpio_key_wait, wait);return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
}static int gpio_fasync(int fd , struct file *file, int on)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);if (fasync_helper(fd, file, on, &button_fasync) >= 0){return 0;}else{return -EIO;}
}static const struct file_operations gpio_fops = {.owner = THIS_MODULE,.read  = gpio_read,.poll  = gpio_poll,.fasync = gpio_fasync,
};static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{struct gpio_key* gpio_key = dev_id;int val;int key;val = gpio_get_value(gpio_key->gpio);//printk("key %d %d\n", gpio_key->gpio, val);//g_key = (gpio_key->gpio << 8) | val;key = (gpio_key->gpio << 8) | val;put_key(key);wake_up_interruptible(&gpio_key_wait);/* 发信号 */kill_fasync(&button_fasync, SIGIO, POLL_IN);//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return IRQ_HANDLED;
}static int gpio_probe(struct platform_device *pdev)
{int count, i;struct device_node *node;int err;node = pdev->dev.of_node;count = of_gpio_count(node);if (!count){printk("%s %s line %d, there isn't any gpio available\n", __FILE__, __FUNCTION__, __LINE__);return -1;}/* 申请资源 */gpio_keys_100ask = kzalloc(sizeof(struct gpio_key) * count, GFP_KERNEL);if (!gpio_keys_100ask){printk("kzalloc error\n");return -1;}/* 获得资源 */for (i = 0; i < count; i++){gpio_keys_100ask[i].gpio = of_get_gpio(node, i);if (gpio_keys_100ask[i].gpio < 0){printk("%s %s line %d, of_get_gpio_flags fail\n", __FILE__, __FUNCTION__, __LINE__);return -1;}gpio_keys_100ask[i].gpiod = gpio_to_desc(gpio_keys_100ask[i].gpio);gpio_keys_100ask[i].irq   = gpio_to_irq(gpio_keys_100ask[i].gpio);/* 申请中断 */err = request_irq(gpio_keys_100ask[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "test1_gpio_keys_100ask", &gpio_keys_100ask[i]);if (err) {printk("request_irq err\n");}}/* 注册字符设备 */major = register_chrdev(major, "100ask_key", &gpio_fops);if(major < 0){printk("register_chrdev err'\n");return -1;}/* 注册类 */gpio_class = class_create(THIS_MODULE, "100ask_key_class");/* 注册设备 */device_create(gpio_class, NULL, MKDEV(major,0), NULL, "100ask_key_button");printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static int gpio_remove(struct platform_device *pdev)
{int count, i;struct device_node *node;node = pdev->dev.of_node;count = of_gpio_count(node);device_destroy(gpio_class, MKDEV(major,0));class_destroy(gpio_class);unregister_chrdev(major, "100ask_key");for (i = 0; i < count; i++){free_irq(gpio_keys_100ask[i].irq, &gpio_keys_100ask[i]);}kfree(gpio_keys_100ask);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/*
* 在设备树中添加的节点的compatible属性为:"test1_100ask,test1_gpio_key"
*/
static const struct of_device_id gpio_key_of_match[] = {{.compatible = "test1_100ask,test1_gpio_key"},{/* 这里必须要有一个空项,表示结束 */}
};static struct platform_driver gpio_driver = {.driver = {.name	= "test1_gpio_keys_100ask",.of_match_table = gpio_key_of_match,},.probe	= gpio_probe,.remove = gpio_remove,
};/* 基于platform总线来实现这个程序 */
static int gpio_init(void)  
{int ret;ret = platform_driver_register(&gpio_driver);if (ret != 0){printk("platform_driver_register err\n");return -1;}else{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);}return ret;
}static void gpio_exit(void)
{platform_driver_unregister(&gpio_driver);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
}module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("GPL");

4.代码路径:

/home/book/nfs_rootfs/CSDN/01_gpio_irq/06_read_key_irq_poll_fasync_block

http://www.mrgr.cn/news/59316.html

相关文章:

  • Java避坑案例 - 高并发场景下的分布式缓存策略
  • Java面试题——微服务篇
  • 【时空分布预测】电动汽车充电负荷时空分布预测
  • 【第三章·基本算术运算】第一节:C 语言运算符和表达式
  • Zypher Network Layer3 主网上线,“宝藏方舟”活动是亮点
  • 使用Python来下一场深夜雪
  • 安全知识见闻-脚本语言对与安全的重要性
  • 使用FRP搭建内网穿透服务(新版toml配置文件,搭配反向代理方便内网网站访问)【使用frp搭建内网穿透】
  • 索引的使用和优化
  • 基于SSM“毛毛宠物店”宠物信息交流平台的设计与实现
  • Linux中C/C++程序编译过程与动静态链接库概述
  • LeetCode438.找到字符串中所有字母异位词
  • Macos系统使用wine安装window的exe软件
  • Redis 线程控制 总结
  • 图片懒加载
  • lodash 库作用
  • python的装饰器
  • 好/坏代码实例解读:图文并茂说明
  • 在MySQL中存储IP地址的最佳实践
  • C#判断带数字的字符串数组连续性的两种方式
  • 【JavaSE】认识String类,了解,进阶到熟练掌握
  • 使用 Resilience4j 实现重试
  • PHP模拟多继承的方式:traits
  • 数据结构 - 散列表,初探
  • Java篇图书管理系统
  • 深度图像和距离图像