Linux驱动实践:中断处理函数如何【发送信号】给应用层?

发布时间 - 2025-06-26 00:00:00    点击率:

作者:道哥,一位拥有10多年嵌入式开发经验的老兵,专注于c++/c++、嵌入式开发和linux。

目录

驱动程序示例代码全貌 Makefile 文件编译、测试 应用程序示例代码全貌 编译、测试 别人的经验,我们的阶梯!

大家好,我是道哥,今天我要为大家讲解的技术知识点是:【中断程序如何发送信号给应用层】。

最近分享的几篇文章都相对基础,涉及字符类设备的驱动程序以及中断处理程序。

虽然现代项目可能用不到这样的技术,但万丈高楼平地起。

只有理解这些最基础的知识点,才能在学习那些进化出来的高级技术时,逐步获得成就感。

如果缺少这些基础环节,很多深层次的东西学起来就会感觉像空中楼阁。

就好比研究Linux内核,如果从Linux 4.x/5.x版本开始研究,可以看到很多“历史遗留”代码。

这些代码见证了Linux一步一步的发展历史,甚至有些人会专门研究Linux 0.11版本的内核源码,因为很多基本思想是相通的。

今天这篇文章,主要还是以代码实例为主,将之前的两个知识点结合起来:

在中断处理函数中,发送信号给应用层,以此来通知应用层处理相应的中断业务。

驱动程序示例代码全貌

首先创建驱动模块目录:

$ cd ~/tmp/linux-4.15/drivers
$ mkdir my_driver_interrupt_signal
$ touch my_driver_interrupt_signal.c

文件内容如下:

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

// 中断号
#define IRQ_NUM 1

// 定义驱动程序的 ID,在中断处理函数中用来判断是否需要处理
#define IRQ_DRIVER_ID 1234

// 设备名称
#define MYDEV_NAME "mydev"

// 驱动程序数据结构
struct myirq {
    int devid;
};

struct myirq mydev = { IRQ_DRIVER_ID };

#define KBD_DATA_REG        0x60  
#define KBD_STATUS_REG      0x64
#define KBD_SCANCODE_MASK   0x7f
#define KBD_STATUS_MASK     0x80

// 设备类
static struct class *my_class;

// 用来保存设备
struct cdev my_cdev;

// 用来保存设备号
int mydev_major = 0;
int mydev_minor = 0;

// 用来保存向谁发送信号,应用程序通过 ioctl 把自己的进程 ID 设置进来。
static int g_pid = 0;

// 用来发送信号给应用程序
static void send_signal(int sig_no) {
    int ret;
    struct siginfo info;
    struct task_struct *my_task = NULL;

    if (0 == g_pid) {
        // 说明应用程序没有设置自己的 PID
        printk("pid[%d] is not valid! \n", g_pid);
        return;
    }

    printk("send signal %d to pid %d \n", sig_no, g_pid);

    // 构造信号结构体
    memset(&info, 0, sizeof(struct siginfo));
    info.si_signo = sig_no;
    info.si_errno = 100;
    info.si_code = 200;

    // 获取自己的任务信息,使用的是 RCU 锁
    rcu_read_lock();
    my_task = pid_task(find_vpid(g_pid), PIDTYPE_PID);
    rcu_read_unlock();

    if (my_task == NULL) {
        printk("get pid_task failed! \n");
        return;
    }

    // 发送信号
    ret = send_sig_info(sig_no, &info, my_task);
    if (ret < 0) {
        printk("send_sig_info failed\n");
    }
}

这段代码展示了如何在中断处理函数中发送信号给应用层,确保应用层能够及时处理中断业务。


# linux  # ai  # c++  # 自己的  # 应用层  # 应用程序  # 的是  # 万丈高楼平地起  # 我是  # 就会  # 空中楼阁  # 这段  # 数据结构 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何为不同团队 ID 动态生成多个独立按钮  如何用PHP快速搭建CMS系统?  BootStrap整体框架之基础布局组件  Python并发异常传播_错误处理解析【教程】  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  详解Oracle修改字段类型方法总结  Swift中swift中的switch 语句  Laravel API资源类怎么用_Laravel API Resource数据转换  如何在阿里云虚拟服务器快速搭建网站?  ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  如何用虚拟主机快速搭建网站?详细步骤解析  Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  Laravel如何升级到最新版本?(升级指南和步骤)  三星网站视频制作教程下载,三星w23网页如何全屏?  Laravel Docker环境搭建教程_Laravel Sail使用指南  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  使用豆包 AI 辅助进行简单网页 HTML 结构设计  瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口  如何实现建站之星域名转发设置?  制作旅游网站html,怎样注册旅游网站?  如何在IIS中新建站点并解决端口绑定冲突?  Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制  微信小程序 canvas开发实例及注意事项  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  JS中对数组元素进行增删改移的方法总结  Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  bing浏览器学术搜索入口_bing学术文献检索地址  Laravel DB事务怎么使用_Laravel数据库事务回滚操作  Laravel如何处理文件下载请求?(Response示例)  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  微信小程序 wx.uploadFile无法上传解决办法  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  如何用狗爹虚拟主机快速搭建网站?  Android Socket接口实现即时通讯实例代码  Laravel中的Facade(门面)到底是什么原理  如何在云主机快速搭建网站站点?  香港服务器选型指南:免备案配置与高效建站方案解析  Python自动化办公教程_ExcelWordPDF批量处理案例  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  php 三元运算符实例详细介绍  如何快速查询网址的建站时间与历史轨迹?  Firefox Developer Edition开发者版本入口  如何彻底删除建站之星生成的Banner?