io-同步 异步 阻塞 非阻塞

异步io是kernel帮你的线程盯着该线程所要的数据是否可用,而线程可以去做别的事情。当数据可用时kernel会把数据拷贝到指定的内存地址然后通知通知你的线程。需要利用事件等机制来完成。

同步io是你的线程自己去向内核查询所要的数据是否可用。在查询的时候,数据不可用的话:
如果内核将这个线程塞进等待队列,直到数据可用时,内核将线程加进可运行队列,并将可用数据给它,则是阻塞型io;
如果内核不将其塞进等待队列,而是直接给他一个error代码表示数据不可用,则是非阻塞io。执行非阻塞型io的线程需要一遍一遍的去询问内核数据是否可用,否则它可能读不到可用的数据。

可见-同步 异步 阻塞 非阻塞的关系。
①异步同步是指线程对数据获取的方式而言的,
异步:内核主动通知线程读写已经完成,
同步:线程主动询问内核读写就绪,可以去读或写了。

②而阻塞非阻塞是在线程主动询问内核时,内核对线程的不同处理方式。所以阻塞非阻塞都是在同步的情况下发生的。


|----异步
|----同步|-----阻塞
             |-----非阻塞

执行同步io时,就是直接向内核索取数据,非阻塞io(r如read函数)会立即返回,阻塞io(如read函数)则在数据可用时返回。线程中需要对返回值检查,返回值一般是数据不可用时的错误代码或可用数据。
执行异步io时,就像向内核提交一个"申请当数据可用时的事件通知"的服务(所以可以立即返回),所以需要向内核提交一个事件参数,当数据可用时,内核自动读写数据到指定的内存地址并触发该事件。

当然执行异步io的谈不上阻塞非阻塞,因为他在执行异步io(比如read)时内核没机会没理由将它阻塞。

http://blog.csdn.net/historyasamirror/article/details/5778378
https://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/

2014-11-24 18:25:15
1.select ,poll,epoll都是同步非阻塞的函数
对于select而言:
应用程序在open的时候需要设置O_NONBLOCK标志,这样在read的时候如果无数据可读,则会直接返回。
所以这种情况下,需要先调用select函数,对应驱动中的poll函数,如果驱动中无数据可读,驱动会将此线程加入等待队列,有数据可读时(和其他一些情况)就会唤醒对应线程。线程继续执行就直接调用read函数去读取数据就可以读到数据。
linux下socket没有实现异步
linux下串口没有实现异步

但是都实现了同步非阻塞,如下是serial_core.c中的poll接口
static const struct tty_operations uart_ops = {
	.open		= uart_open,
	.close		= uart_close,
	.write		= uart_write,
	.put_char	= uart_put_char,
	.flush_chars	= uart_flush_chars,
	.write_room	= uart_write_room,
	.chars_in_buffer= uart_chars_in_buffer,
	.flush_buffer	= uart_flush_buffer,
	.ioctl		= uart_ioctl,
	.throttle	= uart_throttle,
	.unthrottle	= uart_unthrottle,
	.send_xchar	= uart_send_xchar,
	.set_termios	= uart_set_termios,
	.set_ldisc	= uart_set_ldisc,
	.stop		= uart_stop,
	.start		= uart_start,
	.hangup		= uart_hangup,
	.break_ctl	= uart_break_ctl,
	.wait_until_sent= uart_wait_until_sent,
#ifdef CONFIG_PROC_FS
	.proc_fops	= &uart_proc_fops,
#endif
	.tiocmget	= uart_tiocmget,
	.tiocmset	= uart_tiocmset,
	.get_icount	= uart_get_icount,
#ifdef CONFIG_CONSOLE_POLL
	.poll_init	= uart_poll_init,
	.poll_get_char	= uart_poll_get_char,
	.poll_put_char	= uart_poll_put_char,
#endif
};


2017-6-16
对于io复用的使用有一个套路,叫reactor模式。使用这种框架写代码和直接使用io复用函数相比,主要是把业务作为回调函数去注册,这样事件发生时调用回调函数,从而实现业务代码和基础设施代码分离。


当然,reactor框架一般会把操作系统的大多数io事件都会集成进来.比如libev就实现了文件变化事件,网络io事件,定时器事件等
根据reator框架用多少个线程去执行回调函数,还可以初步分为单线程reactor和多线程reactor

和reactor相对的是proactor框架,他是把操作系统的异步函数用回调的机制实现出来。


同步阻塞的内核实现:

同步非阻塞的额内核实现:

2.异步io模型
先看一个例子

异步的内核实现:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值