Linux内核驱动开发-001字符设备开发-内核中断驱动独立按键+等待队列优化

1驱动程序

/*************************************************************************
	> File Name: key_wait.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: 2024年04月23日 星期二 13时20分42秒
 ************************************************************************/

#if 1
/*=========================The key_wait driver=========================*/

/*==========头文件包含==========*/
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/wait.h>
#include <linux/sched.h>

/*==========函数声明==========*/

static int __init key_driver_init(void);

static int key_driver_open(struct inode *node, struct file *fp);
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static int key_driver_close(struct inode *node, struct file *fp);

void disable_irq_r(void);
void free_irq_r(void);
static void __exit key_driver_exit(void);


/*==========全局变量==========*/

/*保存键值*/
static int key = 0;

/*字符设备文件操作结构体*/
static struct file_operations fops =
{
	.owner = THIS_MODULE,
	.open = key_driver_open,
	.read = key_driver_read,
	.write = key_driver_write,
	.release = key_driver_close
};

/*杂项设备结构体*/
static struct miscdevice key_dev = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "key_r",
	.fops = &fops,
};

/*===全局变量-等待队列===*/
/*等待队列头*/
static wait_queue_head_t wq;
/*等待条件*/
static int condition;


/*******************************************************************************
* 函 数 名	: key_interrupt
* 函数功能	: 处理中断任务
* 输    入  : 
*           irq : 中断号
*           *p  :中断处理函数传参,一般传【NULL】
* 输    出  :
*   irqreturn_t :表示中断由该设备处理,是一个枚举类型
*******************************************************************************/
irqreturn_t key_interrupt(int irq, void *p)
{
	printk("key_interrupt\n");
	if(irq == IRQ_EINT8)
	{
		key = 1;
	}
	else if(irq == IRQ_EINT11)
	{
		key = 2;
	}

    condition=1;//按键按下->触发中断->条件为真->唤醒队列
    wake_up(&wq);//唤醒队列

	return IRQ_HANDLED;
}

/*******************************************************************************
* 函 数 名	: key_driver_init
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int __init key_driver_init(void)
{
	int ret;

    /* 1 注册杂项设备*/
	ret = misc_register(&key_dev);
	if(ret <  0)
	{
		printk("misc_register is failed\n");
		goto misc_register_err;
	}
    /* 2 注册中断-【中断号】-【中断处理函数指针】-【中断产生的条件和系统处理中断时的行为(这里处理中断时不响应其他中断)】-【给中断名命名】-【中断服务函数传参-NULL】*/
	ret = request_irq(IRQ_EINT8, key_interrupt, IRQF_TRIGGER_FALLING | IRQF_DISABLED, "key1", NULL);
	if(ret < 0)
	{
		printk("request_irq is failed\n");
		goto request_irq_err;
	}

    /* 3 初始化等待队列*/
    init_waitqueue_head(&wq);

    printk("key_driver_init OK\n");

	return 0;

request_irq_err:
    misc_deregister(&key_dev);
misc_register_err:
	return -1;
}

/*******************************************************************************
* 函 数 名	: key_driver_open
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int key_driver_open(struct inode *node, struct file *fp)
{
	printk("request_irq OK\n");

	return 0;
}

/*******************************************************************************
* 函 数 名	: key_driver_read
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t key_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{
    condition=0;

    /*等待事件中断,在更改任何可能改变等待条件结果的变量后,必须调用【wake_up】-要等待的等待队列-要等待的时间*/
    wait_event_interruptible(wq,condition);
	copy_to_user(user_buffer, &key, sizeof(key));
	key = 0;

	return sizeof(key);
}

/*******************************************************************************
* 函 数 名	: key_driver_write
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t key_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{
	return 0;
}

/*******************************************************************************
* 函 数 名	: key_driver_close
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int key_driver_close(struct inode *node, struct file *fp)
{
	return 0;
}
/*******************************************************************************
* 函 数 名	: disable_irq_r
* 函数功能	: 禁止中断
* 输    入  : 							
* 输    出  :
*******************************************************************************/
void disable_irq_r(void)
{
    /*禁止中断,如果中断正在执行,则等待中断执行结束后再禁止它*/
	disable_irq(IRQ_EINT8);
}

/*******************************************************************************
* 函 数 名	: free_irq_r
* 函数功能	:
* 输    入  :
* 输    出  :
*******************************************************************************/
void free_irq_r(void)
{
    /*注销中断*/
	free_irq(IRQ_EINT8, NULL);
}
/*******************************************************************************
* 函 数 名	: key_driver_exit
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void __exit key_driver_exit(void)
{
    disable_irq_r();//禁止中断
    free_irq_r();//注销中断
	misc_deregister(&key_dev);
}


module_init(key_driver_init);
module_exit(key_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
/*=========================The key_wait driver=========================*/
#endif


/*=========================The key_wait driver=========================
*总结:
* 1 等待队列:
*  定义全局变量(等待队列头,队列唤醒的条件)->初始化等待队列(创建该按键中断的等待队列)->等待事件中断(即有按键按下)->唤醒等待队列(条件为真,唤醒等待队列)
*  
* 要点:
* 读时等待
* 中断发生时唤醒
* 
*
*
* */

2应用程序

/*************************************************************************
	> File Name: main.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: 2024年04月21日 星期日 15时56分47秒
 ************************************************************************/

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main(void)
{  
#if 1
/*====================key-r====================*/    
    int fd=0;
    int n=0;

    fd=open("dev/key_r",O_RDWR);
    if(fd<0)
    {
        printf("opening is failed\n");
        return -1;
    }

    while(1)
    {
        read(fd,&n,4);
        printf("%d\n",n);
        sleep(1);
    }
    return 0;
/*========================================*/    
#endif
}

最近更新

  1. TCP协议是安全的吗?

    2024-04-29 12:46:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-29 12:46:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-29 12:46:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-29 12:46:01       18 阅读

热门阅读

  1. Unity坐标相关——坐标系,单位

    2024-04-29 12:46:01       13 阅读
  2. Node.js 的 fs 模块分析及其应用

    2024-04-29 12:46:01       16 阅读
  3. 使用动态ip上网稳定吗?

    2024-04-29 12:46:01       13 阅读
  4. 安装k8s

    2024-04-29 12:46:01       12 阅读
  5. web server apache tomcat11-20-connectors 连接器

    2024-04-29 12:46:01       14 阅读
  6. Odoo用浏览器与企业版客户端的区别

    2024-04-29 12:46:01       12 阅读
  7. ssh连接自动断开的几种可能

    2024-04-29 12:46:01       17 阅读
  8. linux 提权总结_linux提权

    2024-04-29 12:46:01       14 阅读
  9. 阿赵Json工具AzhaoJson的Lua版本

    2024-04-29 12:46:01       11 阅读
  10. 【Spark】读取本地文件

    2024-04-29 12:46:01       9 阅读
  11. rust语言tokio库spawn, blocking_spawn等的使用

    2024-04-29 12:46:01       20 阅读
  12. Element

    Element

    2024-04-29 12:46:01      14 阅读
  13. H3C 交换机配置 IGMP-snooping 注意点

    2024-04-29 12:46:01       12 阅读