linux 多个异步通知,linux下使用异步通知

阻塞式I/O是一直等待直到设备可以访问,非阻塞式I/O是定期轮询设备是否可以访问。

异步通知则是当设备可以访问时才主动通知应用程序,有点像设备的硬中断。

并不是所有的设备都支持异步通知,应用程序通常假设只有套接字和终端才有异步通知的能力。

异步通知存在一个问题,当进程收到SIGIO信号时,它并不知道是哪个文件有了新的输入,如果

有多于一个的文件可以异步通知同一个进程,那么应用进程还需要借助于poll或select来确定输入

的来源。

应用层

fcntl - manipulate file descriptor

fcntl(fd, F_SETFL, flags | O_ASYNC);

效果:

If you set the O_ASYNC status flag on a file descriptor by using the F_SETFL command of fcntl(),

a SIGIO signal is sent whenever input or output becomes possible on that file descriptor.

例子

#include #include #include #include #include #define MAX_LEN 100

void my_handler(int signum)

{

char data[MAX_LEN];

int len;

len = read(STDIN_FILENO, &data, MAX_LEN);

data[len] = 0;

printf("Input message: %s

", data);

exit(0);

}

int main(void)

{

int oflags;

/* set new SIGIO handler */

signal(SIGIO, my_handler);

/* set fd's owner process */

fcntl(STDIN_FILENO, F_SETOWN, getpid());

/* get old fd flags */

oflags = fcntl(STDIN_FILENO, F_GETFL);

/* set new fd flags */

fcntl(STDIN_FILENO, F_SETFL, oflags | O_ASYNC);

/* infinitely wait until recv SIGIO */

while(1);

return 0;

}

为了能处理设备发出的SIGIO信号,用户程序需要做:

1. 设置设备文件的拥有者为本进程,这样一来才能收到设备驱动发出的SIGIO信号。

2. 使设备文件支持异步通知,即设置O_ASYNC标志。

3. 通过signal()指定SIGIO的处理函数。

设备驱动

struct fasync_struct {

spinlock_t fa_lock;

int magic;

int fa_fd; /* 文件描述符 */

struct fasync_struct *fa_next; /* 用于链入单向链表 */

struct file *fa_file; /* fa_file->f_owner记录接收信号的进程 */

struct rcu_head fa_rcu;

};

(1) 设备的异步通知链

struct xxx_dev {

struct cdev cdev;

...

struct fasync_struct *async_queue; /* 异步通知链 */

};

(2) 插入到异步通知链

static int xxx_fasync(int fd, struct file *filp, int on)

{

struct xxx_dev *dev = filp->private_data;

return fasync_helper(fd, filp, on, &dev->async_queue);

}

(3) 发送信号通知进程

设备使用kill_fasync()来发送信号给用户进程,一般sig为SIGIO,可读时band为POLL_IN,

可写时band为POLL_OUT。

static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)

{

struct xxx_dev *dev = filp->private_data;

...

if (dev->async_queue) {

kill_fasync(&dev->async_queue, SIGIO, POLL_IN);

}

...

}

(4) 从异步通知链中删除

在关闭文件时,需要把对应的异步通知结构从链表中删除。

static xxx_release(struct inode *inode, struct file *filp)

{

struct xxx_dev *dev = filp->private_data;

...

fasync_helper(-1, filp, 0, &dev->async_queue);

...

}

内核API

异步通知结构体的插入和删除,失败返回负值,没有变化返回0,有变化返回正值。

/* fasync_helper() is used by almost all character device drivers to set up the

* fasync queue, and for regular files by the file lease code. It returns negative

* on error, 0 if it did no changes and positive if it added/deleted the entry.

*/

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); /* 插入 */

}

发送信号,通知用户进程,sig一般设为SIGIO,可读时band为POLL_IN,可写时band为POLL_OUT。

void kill_fasync(struct fasync_struct **fp, int sig, int band)

{

/* First a quick test without locking: usually the list is empty. */

if (*fp) {

rcu_read_lock();

kill_fasync_rcu(rcu_dereference(*fp), sig, band);

rcu_read_unlock();

}

}

Reference

[1]. http://www.cnblogs.com/hanyan225/archive/2010/10/20/1857040.html

[2]. 《设备驱动程序》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux下,有多种方式可以实现异步通知。以下是其中一些常用的方法: 1. 信号(Signals):Linux系统中的信号机制是一种基本的异步通知机制。通过向进程发送信号,可以触发相应的信号处理函数来处理特定事件。常见的信号包括SIGINT(中断信号)和SIGTERM(终止信号)。可以使用signal()函数或者sigaction()函数来注册信号处理函数。 2. 事件驱动编程(Event-driven programming):事件驱动编程是一种基于事件和回调函数的编程模型,常用于异步通知和事件处理。在Linux中,可以使用库如libevent或者libuv来实现事件驱动编程。这些库提供了事件循环(event loop)和回调函数机制,可以处理各种异步事件。 3. 文件描述符(File descriptors)和I/O多路复用(I/O multiplexing):在Linux中,文件描述符用于表示打开的文件、套接字等资源。通过使用I/O多路复用机制,如select()、poll()或者epoll(),可以在一个线程中同时监听多个文件描述符上的I/O事件,实现异步通知和非阻塞I/O操作。 4. 管道(Pipes)和消息队列(Message queues):管道和消息队列是进程间通信的一种方式,可以在不同的进程之间实现异步通知。通过使用管道或消息队列,一个进程可以向另一个进程发送消息,接收进程可以在准备好处理消息时进行异步通知。 这些是常见的Linux下实现异步通知的方法,具体选择哪种方法取决于应用的需求和情况。在实际应用中,可以根据具体的场景选择最合适的方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值