内核向应用层异步通知的方法,kill_fasync及fasync_helper用法

kill_fasync及fasync_helper用于异步通知中
kill_fasync(&fasync_read, SIGIO, POLL_IN);; //向用户发可读信号,fasync_read可用来区分向谁发
哪个进程调用这个fasync_helper就向谁发
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) {
        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) {
        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;
}
别忘了realease时调用一把释放
所以用法为
用户层
    signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号
    fcntl(fd, F_SETOWN, getpid());
    oflags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, oflags | FASYNC); //调用驱动的
fasync_helper

驱动
    
kill_fasync发送信号调用signal安装的信号

   设备关闭时    kpp_fasync(-1, filp, 0);


代码示例(字符设备驱动案例)

(驱动部分)

struct fasync_struct *fasync_read;

static int read_fasync(int fd, struct file *filp, int mode)
{
    return fasync_helper(fd, filp, mode, &fasync_read);
}

static const struct file_operations my_gpio_fops =
{
  .owner = THIS_MODULE,
  .open = my_gpio_open,
  .release = my_gpio_release,
  .read = my_gpio_read,
  .unlocked_ioctl = my_gpio_ioctl,  
.fasync = read_fasync,
};

static irqreturn_t my_handler_u0(int irq, void *dev_id)//驱动中中断处理函数

{

......

    if (fasync_read){
   kill_fasync(&fasync_read, SIGIO, POLL_IN);//异步通知用户层

    }

}

用户层

    signal(SIGIO, input_handler);
    fcntl(gps_fd, F_SETOWN, getpid());
    oflags = fcntl(gps_fd, F_GETFL);
    fcntl(gps_fd, F_SETFL, oflags | FASYNC);

void input_handler(int signum)//用户层响应底层信号的处理
{
    ........
}


你可能感兴趣的:(异步,C语言,字符设备驱动)