linux设备驱动开发之设备驱动的异步通知与异步IO

    xiaoxiao2024-10-21  93

    异步通知概念

    当设备就绪的时候,主动通知应用程序。

    设备驱动支持异步通知代码

    index 452df8f..b0a1038 100644 @@ -40,6 +40,7 @@ struct globalfifo_dev struct mutex mutex; wait_queue_head_t r_wait; wait_queue_head_t w_wait; + struct fasync_struct *async_queue; }; static struct globalfifo_dev *globalfifo_devp = NULL; @@ -270,6 +271,11 @@ static ssize_t globalfifo_write (struct file *filep, const char __user *buf, siz #ifdef globalfifo_debug printk(KERN_DEBUG "globalfifo_write = %s\n", dev->mem); #endif + if (dev->async_queue) // post readable signal when async + { + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + printk("%s kill SIGIO\n", __func__); + } } out: @@ -347,8 +353,16 @@ static int globalfifo_open (struct inode *inode, struct file *filep) return 0; } +static int globalfifo_fasync (int fd, struct file *filep, int mode) +{ + struct globalfifo_dev *dev = filep->private_data; + return fasync_helper(fd, filep, mode, &dev->async_queue); +} + static int globalfifo_release (struct inode *inode, struct file *filep) { + // remove async function form the async queue + globalfifo_fasync(-1, filep, 0); return 0; } @@ -362,6 +376,7 @@ static struct file_operations chrdev_file_operations = .open = globalfifo_open, .release = globalfifo_release, .poll = globalfifo_poll, + .fasync = globalfifo_fasync, // binging the interface @fasync }; /**

    增加异步IO应用层编码

    /** ** This file is part of the LinuxTrainningCompany project. ** Copyright (C) duanzhonghuan Co., Ltd. ** All Rights Reserved. ** Unauthorized copying of this file, via any medium is strictly prohibited ** Proprietary and confidential ** ** Written by duanzhonghuan <15818411038@163.com>, 2019/5/18 **/ #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "unistd.h" void signal_handle(int signo) { printf("Have caught the Signal: %d\n", signo); exit(0); } int main(void) { int fd, oflags; fd = open("/dev/globalfifo", O_RDWR); if (fd != -1) { // if the signal @SIGIO is captured, // the function of @signal_handle is called signal(SIGIO, signal_handle); // set one of the @fd owners as the process fcntl(fd, F_SETOWN, getpid()); // receive the asynchronous sinals oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | O_ASYNC); while(1) { sleep(1); } } else { printf("open /dev/globalfifo failed \n"); } #if 0 signal(SIGINT, signal_handle); signal(SIGTERM, signal_handle); while(1) {} #endif return 0; }

    由此可见,为了能在用户空间中处理一个设备释放的信号,它必须完成3项工作。 1)通过F_SETOWN IO控制命令设置设备文件的拥有者为本进程,这样从设备驱动发出的信号才能被本进程接收到。 2)通过F_SETFL IO控制命令设置设备文件以支持FASYNC,即异步通知模式。 3)通过signal()函数连接信号和信号处理函数。

    AIO

    ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*aio_fsync) (struct kiocb *, int datasync);

    有关AIO的介绍可参考Asynchronous I/O and vectored operations

    总结

    使用信号可以实现设备驱动与用户程序之间的异步通知。我们利用这个特性与设备驱动进行通信。关于AIO,drivers/char/mem.c里实现的null、zero驱动是通过AIO机制实现的。
    最新回复(0)