linux驱动之异步通知

异步通知

为了启动文件的异步通知机制,用户程序需要执行两个步骤:

1 fcntl(int fd, F_SETOWN, getpid());  //设置接受SIGIO和SIGURG的进程,如果getpid()为负表示以该值绝对值为值的进程组,其实就是对filp->f_owner赋值

signal(SIGIO, button_signal_function);//接收到SIGIO信号时,调用button_signal_function函数

2 flag |= FASYNC;

fcntl(fd, F_SETFL, flag);//设置文件状态标志,只有设置了FASYNC标志,才能启动异步通知,调用内核的fasync函数

驱动程序要使用的函数

int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
{
    if (!on)
        return fasync_remove_entry(filp, fapp);
    return fasync_add_entry(fd, filp, fapp);
}

fasync_struct结构体如下

struct fasync_struct {
    spinlock_t      fa_lock;
    int         magic;
    int         fa_fd;
    struct fasync_struct    *fa_next; /* singly linked list */
    struct file     *fa_file;
    struct rcu_head     fa_rcu;
};



static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp)
{
    struct fasync_struct *new;

    new = fasync_alloc();
    if (!new)
        return -ENOMEM;

    /*
     * fasync_insert_entry() returns the old (update) entry if
     * it existed.
     *
     * So free the (unused) new entry and return 0 to let the
     * caller know that we didn't add any new fasync entries.
     */
    if (fasync_insert_entry(fd, filp, fapp, new)) {
        fasync_free(new);
        return 0;
    }

    return 1;
}


主要是调用fasync_insert_entry函数

struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct fasync_struct *new)
{
        struct fasync_struct *fa, **fp;

    spin_lock(&filp->f_lock);
    spin_lock(&fasync_lock);
    for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
        if (fa->fa_file != filp)
            continue;

        spin_lock_irq(&fa->fa_lock);
        fa->fa_fd = fd;
        spin_unlock_irq(&fa->fa_lock);
        goto out;
    }

    spin_lock_init(&new->fa_lock);
    new->magic = FASYNC_MAGIC;
    new->fa_file = filp;
    new->fa_fd = fd;
    new->fa_next = *fapp;
    rcu_assign_pointer(*fapp, new);
    filp->f_flags |= FASYNC;

out:
    spin_unlock(&fasync_lock);
    spin_unlock(&filp->f_lock);
    return fa;
}

该函数在链表中查找是否存在指定的filp,如果存在将该fasync_struct对应的fa_fd替换成新的fd,如果不存在该filp,则添加新的fasync_struct结构体,并以指定的filp,fd等初始化,添加到链表的末尾。

当指定的事件发生时,内核使用kill_fasync函数通知应用程序


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值