I/O的理解

47 篇文章 0 订阅
19 篇文章 0 订阅

I/O条件就绪是指:数据已经到达,此时调用读函数一定会成功;或设备已经可以承接输出操作,此时调用写函数一定会成功。I/O条件就绪发生在调用具体的I/O函数之前,I/O就绪后如非对设备内核对象(Windows下为文件句柄,Linux下为文件描述符)进行特殊设置(如设置设备内核对象为非阻塞模式),则发出的I/O调用过程其实是用户缓冲区与内核缓冲区之间进行数据拷贝的过程,这个过程是阻塞的。

异步I/O是指:先通过调用I/O函数向内核发起I/O请求(这些函数调用后都会立即返回),内核将内核缓冲区中的数据拷贝至用户缓存,或将用户缓存中的数据拷贝至内核缓存并将内核缓存中的数据输出到设备,然后通知用户程序(如Windows中使预先设定的事件内核对象变为有信号状态,或通过完成端口的方式)。所以,用户向内核发起异步I/O请求时需要告诉内核的有:文件描述符、用户缓冲区指针、用户缓冲区大小、完成通知方式等。

应用进程需要有一种预先告知内核的能力,使得内核一旦发现应用进程指定的一个或多个设备内核对象I/O条件就绪时就通知用户进程,这个能力就是I/O复用,I/O复用函数可以使用select或poll(Linux)。
在这里插入图片描述

当应用层发起一个读请求时,比如从网卡读数据:
recv(s,buf,len,0);
这个len仅仅代表buf缓冲区的长度,并不表示此次必须要读到len个字节才返回。当发起recv调用时,recv内部将检查内核缓冲区中是否有数据,如果有,封闭内核缓冲区,然后将内核缓冲区中的数据拷贝至用户缓冲区(即buf),然后离开临界区,以便内核继续向内核缓冲区追加数据,或让其它读函数进入临界区读取数据,然后函数返回。如果内核缓冲区没有数据,则需要循环检测,这也是为什么当对方没有给自己发数据时,recv调用将会等待的原因。下面用伪代码大概描述读数据的实现过程:

void Read()
{
	while (1)
	{
		进入临界区;
		if (内核缓冲区中的数据量 > 0)
			将内核缓冲区的数据拷贝至用户缓冲区;
			更新相关变量的值(如存放内核缓冲区中的字节数的变量);
			离开临界区;
			break;
		离开临界区;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值