kill_async与fasync_helper函数

来源:互联网 发布:unity3d安装包下载 编辑:程序博客网 时间:2024/06/05 14:20

fasync是为了使驱动的读写和应用程序的读写分开,使得应用程序可以在驱动读写的时候去做别的事。

应用程序通过fcntl给自己的SIGIO信号安装自己的响应函数,

驱动通过kill_fasync(&async, SIGIO, POLL_IN); 发SIGIO信号给应用程序,应用程序就调用自己安装的响应函数去处理。

fasync_helper作用就是初始化fasync这个东西,包括分配内存和设置属性,最后在驱动的release里把fasync_helper初始化的东西free掉。

 

这里有一份自己写的完整的内核驱动发送SIGIO和用户空间接收SIGIO的代码,测试过ok:

http://download.csdn.net/detail/luckywang1103/9050619

有些系统没有mdev的需要自己手动创建设备节点:在/dev/目录下mknod fasync_dev c 250 0

 


下面是驱动程序和测试的应用程序,还没试过,先摘下来;

转自:http://blog.csdn.net/mirkerson/article/details/7443907

驱动程序

#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/kdev_t.h>#include <linux/cdev.h>#include <linux/kernel.h>#include <linux/string.h>#include <asm/uaccess.h>#define DEVICE_NAME "chardev"static int chardev_open(struct inode *inodp, struct file *filp);static ssize_t chardev_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos);static ssize_t chardev_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos);static int chardev_fasync(int fd, struct file *filp, int mode);static int chardev_release(struct inode *inodp, struct file *filp);static struct file_operations chardev_fops = {        .open = chardev_open,        .read = chardev_read,        .write = chardev_write,        .fasync = chardev_fasync,        .release = chardev_release,};static struct fasync_struct *async = NULL;static struct semaphore sem;static struct cdev *cdevp;static dev_t devno;static char buffer[8192];static int chardev_open(struct inode *inodp, struct file *filp){        return 0;}static ssize_t chardev_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos){        if (down_interruptible(&sem))                goto err;        count = strlen(buffer);        copy_to_user(buff, buffer, count);        up(&sem);        return count;err:        return -ERESTARTSYS;}static ssize_t chardev_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos){        if (down_interruptible(&sem))                goto err;        memset(buffer, '/0', sizeof(buffer));        copy_from_user(buffer, buff, count);        up(&sem);        if (async)                kill_fasync(&async, SIGIO, POLL_IN);        return count;err:        return -ERESTARTSYS;}static int chardev_fasync(int fd, struct file *filp, int mode){        return fasync_helper(fd, filp, mode, &async);}static int chardev_release(struct inode *inodp, struct file *filp){        return chardev_fasync(-1, filp, 0);}static int __init chardev_init(void){        int ret;        ret = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);        if (ret < 0)                goto out;        init_MUTEX(&sem);        cdevp = cdev_alloc();        if (!cdevp)                goto alloc_err;        cdev_init(cdevp, &chardev_fops);        ret = cdev_add(cdevp, devno, 1);        if (!ret)                goto out;alloc_err:        unregister_chrdev_region(devno, 1);out:        return ret;}static void __exit chardev_exit(void){        cdev_del(cdevp);        unregister_chrdev_region(devno, 1);}MODULE_LICENSE("GPL");module_init(chardev_init);module_exit(chardev_exit);

应用程序:

/* * asynctest.c: use async notification to read stdin * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>int gotdata=0;static int i = 0;void sighandler(int signo){    if (signo==SIGIO)        gotdata++;    printf("/nin sighandler %d/n",i);    return;}char buffer[4096];int main(int argc, char **argv){    int count;    struct sigaction action;    FILE *fp;    int fd = 0;    fd = open("/dev/test",O_RDWR);    memset(&action, 0, sizeof(action));    action.sa_handler = sighandler;    action.sa_flags = 0;    sigaction(SIGIO, &action, NULL);    fcntl(fd, F_SETOWN, getpid());    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FASYNC); ++i;    while(i != 2) {    //printf("/nin while %d/n",++i);        /* this only returns if a signal arrives */#if 0    fp = fopen("log2","aw+");    fprintf(fp,"/nin while %d/n",++i);    fclose(fp);#endif        sleep(2); /* one day */        if (!gotdata)            continue;        count=read(fd, buffer, 4);    printf("/nin while %d/n",++i);        /* buggy: if avail data is more than 4kbytes... */        write(fd,buffer,count);    //printf("/nin while %d/n",++i);        gotdata=0;    }}




0 0
原创粉丝点击