微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm驱动linux异步通知与异步IO

arm驱动linux异步通知与异步IO

时间:11-19 来源:互联网 点击:

ruct fasync_struct **fapp进行初始化,
//当程序释放设备使用myfasync_drv_fasync(-1, file, 0),就执行goto out释放中断
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
{
struct fasync_struct *fa, **fp;
struct fasync_struct *new = NULL;
int result = 0;
if (on) {//第一次分配fapp空间
new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
if (!new)
return -ENOMEM;
}
write_lock_irq(&fasync_lock);
for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {//第一次初始化fapp
if (fa->fa_file == filp) {
if(on) {
fa->fa_fd = fd;
kmem_cache_free(fasync_cache, new);
} else {
*fp = fa->fa_next;
kmem_cache_free(fasync_cache, fa);
result = 1;
}
goto out;
}
}
if (on) {
new->magic = FASYNC_MAGIC;
new->fa_file = filp;
new->fa_fd = fd;
new->fa_next = *fapp;
*fapp = new;
result = 1;
}
out:
write_unlock_irq(&fasync_lock);
return result;
}
EXPORT_SYMBOL(fasync_helper);

释放信号函数
内核部分函数二)kill_fasync(struct fasync_struct * * fp, int sig, int band)
参数:sig就是我们要发送的信号;band(带宽),一般都是使用POLL_IN,表示设备可读,如果设备可写,使用POLL_OUT
内核源码三)释放(产生)异步读信号函数

void __kill_fasync(struct fasync_struct *fa, int sig, int band)
{
while (fa) {
struct fown_struct * fown;
//如果设备文件镜像不存在如设备文件不存在(被删除或改名)或取消了注册FASYNC;镜像映射失败跳出kill_fasync,不产生信号
if (fa->magic != FASYNC_MAGIC) {
printk(KERN_ERR "kill_fasync: bad magic number in "
"fasync_struct!\n");
return;
}
fown = &fa->fa_file->f_owner;
/* Dont send SIGURG to processes which have not set a
queued signum: SIGURG has its own default signalling
mechanism. */
if (!(sig == SIGURG && fown->signum == 0))
send_sigio(fown, fa->fa_fd, band);
fa = fa->fa_next;
}
}
EXPORT_SYMBOL(__kill_fasync);

模板二)信号的异步通知机制模板

struct VirtualDisk{
struct cdev cdev;
//...其他全局变量....
struct fasync_struct *async_queue;//异步结构体指针
};
/*异步读信号*/
static int myfasync_drv_fasync(int fd, struct file *file, int mode){
struct VirtualDisk *devp = file->private_data; /*获得设备结构体指针*/
//....................
return fasync_helper(fd, file, mode, &devp->async_queue);
}
static ssize_t myfasync_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){
struct VirtualDisk *devp = file->private_data; /*获得设备结构体指针*/
//...............
//产生异步读信号SIGIO
if(devp->async_queue)kill_fasync(&devp->async_queue, SIGIO, POLL_IN);
return 0;
}
static int myfasync_drv_release(struct inode *inode, struct file *file)
{
/*当设备关闭时,需要将fasync_struct从异步队列中删除/*
myfasync_drv_fasync(-1, file, 0);
return 0;
}

实例二)驱动程序完整实例:

//“myfasync_drv”,"myfasync_","myfasync_drv"
#include //模块所需的大量符号和函数定义
#include
#include //文件系统相关的函数和头文件
#include //指定初始化和清除函数
#include
#include //cdev结构的头文件包含
#include
#include
//#include //包含驱动程序使用的大部分内核API的定义,包括睡眠函数以及各种变量声明
#include //在内核和用户空间中移动数据的函数
#include
#include
#include
#include
#define VIRTUALDISK_SIZE 0x1000//4k
#define MEM_CLEAR 0x1
#define VIRTUALDISK_MAJOR 250
int VirtualDisk_major = VIRTUALDISK_MAJOR;
struct fasync_struct *async_queue;//异步结构体指针
struct VirtualDisk{
struct cdev cdev;//详细看cdev机制
unsigned char mem[VIRTUALDISK_SIZE ];
long count; /*记录设备目前被多少设备打开*/

};
static struct class *myfasync_class;
static struct class_device *myfasync_class_dev;
struct VirtualDisk *VirtualDiskp;
static int myfasync_drv_fasync(int fd, struct file *file, int mode){
printk("myfasync_drv_fasync %d\n", fd);
return fasync_helper(fd, file, mode, &async_queue);
}
static int myfasync_drv_open(struct inode *inode, struct file *file)
{
printk("myfasync_drv open\n");
file->private_data = VirtualDiskp;
VirtualDiskp->count++; /*增加设备打开次数*/
return 0;
}
static int myfasync_drv_release(struct inode *inode, struct file *file)
{
printk("myfasync_drv release\n");
VirtualDiskp->count--; /*减少设备打开次数*/
myfasync_drv_fasync(-1, file, 0);//当设备关闭时,需要将fasync_struct从异步队列中删除
return 0;
}
/*seek文件定位函数:seek()函数对文件定位的起始地址可以是文件开头(SEEK_SET,0)、当前位置(SEEK_CUR,1)、文件尾(SEEK_END,2)*/
static loff_t myfasync_drv_llseek(struct file *file, loff_t offset, int origin){
loff_t ret = 0;/*返回的位置偏移*/

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top