首页 > 其他分享 >异步通知和MISC设备驱动

异步通知和MISC设备驱动

时间:2024-03-25 23:22:18浏览次数:20  
标签:异步 struct int demo MISC fasync device 驱动

异步通知:

驱动程序中的异步通知是指驱动程序可以向应用程序发送通知,告知应用程序发生了某种事件。这种通知是异步的,即应用程序可以继续执行其他操作,而不需要主动轮询或等待事件的发生。 在Linux内核中,实现驱动异步通知的一种常见方式是使用fasync机制。这个机制的核心是利用fasync_helper函数和kill_fasync函数来实现驱动程序和应用程序之间的异步通信。
  • fasync_helper函数:
在驱动程序中,通过调用fasync_helper函数可以将应用程序的PID添加到驱动程序的异步通知列表中,从而告知内核在特定事件发生时通知这些应用程序。
  • kill_fasync函数:
当驱动程序需要向应用程序发送通知时,可以调用kill_fasync函数向所有在异步通知列表中的应用程序发送信号。 应用程序在接收到信号后,可以注册信号处理程序来处理异步通知,从而实现在事件发生时做出相应的处理   fsync函数说明:
int fasync_helper(int fd, struct file *filp, int on, struct fasync_struct **fapp);

// 参数说明
fd:文件描述符,指定要进行异步通知的文件描述符。
filp:指向表示文件的结构体指针,即struct file结构体的指针。
on:指定是否开启异步通知,非零值表示开启,零值表示关闭。
fapp:指向指针的指针,用于操作异步通知队列。
// 返回值说明
成功,返回0;失败,返回负数错误码,如-EINVAL等。

int kill_fasync(struct fasync_struct **fapp, int sig, int poll_event);

// 参数说明
fapp:指向指针的指针,用于操作异步通知队列。
sig:要发送的信号类型,通常是SIGIO。
poll_event:指定事件类型,通常是POLL_IN(输入事件)或POLL_OUT(输出事件)。
// 返回值说明
成功,返回0;失败,返回负数错误码,如-EINVAL等。
 

MISC设备驱动:

MISC 驱动叫做杂项驱动,就是开发板上的某些外设无法进行分类的时候就可以使用 MISC 驱动。所有的 MISC 设备驱动的主设备号都为 10,不同的设备使用不同的从设备号。随着 Linux字符设备驱动的不断增加,设备号变得越来越紧张,尤其是主设备号,MISC 设备驱动就用于解决此问题。MISC 设备会自动创建 cdev。
    int minor;                              // 次设备号,用于标识设备
    const char *name;                       // 设备名称
    const struct file_operations *fops;     // 设备文件操作
    struct list_head list;                  // 设备链表头
    struct device *parent;                  // 父设备指针
    struct device *this_device;             // 当前设备指针
    const struct attribute_group **groups;  // 属性组指针数组
    const char *nodename;                   // 设备节点名称
    umode_t mode;                           // 设备访问权限模式
};
 

测试demo:

驱动测试demo:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/sched.h>

static struct miscdevice fasync_device;

static int fasync_demo_fasync(int fd, struct file *filp, int mode)
{
    return fasync_helper(fd, filp, mode, &fasync_device.this_device->async_queue);
}

static ssize_t fasync_demo_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    // 在此示例中,read函数仅作为占位符,不做实际操作
    return 0;
}

static ssize_t fasync_demo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    // 触发异步通知
    kill_fasync(&fasync_device.this_device->fasync_list, SIGIO, POLL_OUT);

    return count;
}

static const struct file_operations fasync_demo_fops = {
    .owner = THIS_MODULE,
    .read = fasync_demo_read,
    .write = fasync_demo_write,
    .fasync = fasync_demo_fasync, // 将fasync函数指针指向实现的fasync函数
};

static int __init fasync_demo_init(void)
{
    fasync_device.minor = MISC_DYNAMIC_MINOR;
    fasync_device.name = "fasync_demo_device";
    fasync_device.fops = &fasync_demo_fops;

    misc_register(&fasync_device);

    printk(KERN_INFO "Fasync demo device registered\n");

    return 0;
}

static void __exit fasync_demo_exit(void)
{
    misc_deregister(&fasync_device);

    printk(KERN_INFO "Fasync demo device unregistered\n");
}

module_init(fasync_demo_init);
module_exit(fasync_demo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lethe1203");
MODULE_DESCRIPTION("Fasync && misc demo");

 

用户程序测试demo:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>

#define DEVICE_FILE "/dev/fasync_demo_device"

void signal_handler(int signo)
{
    printf("Asynchronous notification received!\n");
}

int main()
{
    int fd;
    struct sigaction sa;

    // 设置信号处理程序
    sa.sa_handler = signal_handler;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGIO, &sa, NULL);

    // 打开设备文件
    fd = open(DEVICE_FILE, O_RDWR);
    if (fd < 0) {
        perror("Failed to open the device...");
        return -1;
    }

    // 将进程设置为接收SIGIO信号
    fcntl(fd, F_SETOWN, getpid());

    // 开启异步通知
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC);

    // 写入数据以触发异步通知
    write(fd, "Trigger asynchronous notification", sizeof("Trigger asynchronous notification"));

    // 等待异步通知
    pause();

    // 关闭设备文件
    close(fd);

    return 0;
}
在上面demo中,在驱动程序中使用fasync_helper函数来设置异步通知,并在应用程序中使用fcntl和信号处理程序来处理异步通知。当应用程序写入数据到设备文件时,会触发异步通知,驱动程序通过kill_fasync函数发送SIGIO信号通知应用程序。应用程序接收到SIGIO信号后,调用信号处理程序 signal_handler 来处理异步通知。    

标签:异步,struct,int,demo,MISC,fasync,device,驱动
From: https://www.cnblogs.com/lethe1203/p/18095661

相关文章

  • wsl2 ubuntu子系统安装显卡驱动与cuda
    wsl2安装参考文档:http://t.csdnimg.cn/ClwJ9演示安装ubuntu22列出可安装的子系统命令:wsl--list--onlinePSC:\Users\linyu>wsl--list--online以下是可安装的有效分发的列表。使用'wsl.exe--install<Distro>'安装。NAMEF......
  • 掌握C#中异步魔法:同步方法如何优雅调用异步方法
     概述:上述C#示例演示了如何在同步方法中调用异步方法。通过使用`async`和`await`关键字,实现了同步方法对异步方法的调用。建议使用`await`而不是`Result`来避免潜在的死锁问题。这种模式在处理异步任务时能够提高代码的可读性和性能。在C#中,从同步方法调用异步方法的过程涉及......
  • 异步秒杀场景下消息队列如何防止消息丢失
    1、生产者写入消息时使用确认机制。生产者向写入消息时,写入成功则消息队列给生产者返回一个成功标识,写入失败,则返回一个失败标识,然后生产者通过失败重试机制重新写入消息。2、将消息队列中的消息持久化到磁盘中3、手动确认机制允许消费者对接收到的每一条消息进行确认,从而确......
  • 高抗干扰/抗噪液晶驱动芯片VK2C23A/B 永嘉原厂LCD液晶段码屏驱动芯片适用于导轨电表,早
    VK2C23A/B概述:      VK2C23A/B是一个点阵式存储映射的LCD驱动器,可支持最大224点(56SEGx4COM)或者最大416点(52SEGx8COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点:•......
  • 数智时代“通关攻略”,开天aPaaS驱动千行万业创新提速
    本文分享自华为云社区《数智时代“通关攻略”,开天aPaaS驱动千行万业创新提速》,作者:华为云头条。随着新一代ICT技术的深化演进,尤其是技术之间的相互融合与作用,全球产业正在加速迈入数智时代。借助信息技术,以高效低成本的方式开启新的业务增长点,已然成为企业转型的必由之路。3月1......
  • 在linux中无需修改内核驱动就能操作GPIO口的示例
    一、首先编写一个脚本文件init.sh#!/bin/bashecho2>/sys/class/gpio/exportsleep1echo3>/sys/class/gpio/exportsleep1echoout>/sys/class/gpio/gpio3/directionecho1>/sys/class/gpio/gpio3/value这段代码是在Linux系统中使用shell脚本语言编写的。让......
  • 同步通信 and 异步通讯
    同步调用存在的问题 异步调用方案:时间驱动模式 优势:1、服务解耦(添加服务不用修改支付服务的代码)2、性能提升、吞吐量的提高(支付成功之后,后续的服务和支付服务没有关系,由Broker事件通知完成)3、服务没有强依赖,不担心级联失败问题4、流浪削峰 总结:......
  • Python实战:异步I/O:asyncio事件循环
    1.引言在Python中,异步I/O是一种非阻塞的I/O操作方式。与传统的同步I/O操作不同,异步I/O允许程序在等待I/O操作完成的同时执行其他任务。asyncio是Python标准库中用于编写异步代码的库,它提供了一个事件循环来处理异步操作。事件循环是asyncio的核心组件,它负责调度和执行异步......
  • Python编程异步爬虫——aiohttp的使用
    异步爬虫—aiohttp的使用基本介绍asyncio模块其内部实现了对TCP、UDP、SSL协议的异步操作,但是对于HTTP请求来说,就需要用aiohttp实现了。aiohttp是一个基于asyncio的异步HTTP网络模块,它既提供了服务端,又提供了客户端。requests发起的是同步网络请求,aiohttp则是异步。ai......
  • NCV7718CDPR2G半桥驱动器规格书PDF数据手册引脚图图片价格参数概概述
    产品概述:NCV7718是一款六角半桥驱动器,具有专为汽车和工业运动控制应用设计的保护功能。NCV7718具有独立的控制和诊断功能。该器件可在正向、反向、制动和高阻抗状态下运行。驱动器通过16位SPI接口进行控制,并且菊花链兼容规格书参数:引脚图:......