socket_IO模型

1 背景知识

1.1 用户空间和内核空间

好比32位系统,寻址空间是4G。内存分为用户空间和内核空间,内核空间仅供内核使用,用户空间给各个进程使用。os的核心是内核,只有内核能够访问被保护的内存空间。为了保证进程没法直接操做内核 ,在用户空间的进程没法访问内核空间。linux

系统调用函数运行于内核态,可是向用户态开放接口。网络

对于磁盘,网卡等设备,进程都没法直接访问,因此相关数据都用通过系统调用。socket

1.2 进程阻塞

正在执行的进程,因为期待的事件未发生,好比io操做未完成,新数据未到达,就由系统自动执行阻塞,由运行状态变为阻塞状态。因此,进程的阻塞是自身的自动行为,只有处于运行状态(获取cpu时间片)的进程才能转为阻塞状态。而且处于阻塞状态的进程不占用cpu。函数

1.3 文件描述符(句柄)

fd是指向具体文件的一个引用。spa

fd是一个非负整数。当进程打开一个新文件或者socket,系统就为该文件分配一个fd,用来标识这个文件,这个分配的数字从0开始。系统默认状况下,限制每一个进程能打来的文件为1024。3d

1.4 标准io

在标准io机制中,在内核中有页缓冲(内核高速缓冲),在用户空间有流缓冲。指针

对于读操做,数据首先被读到页缓冲(当页缓冲中没有该数据),而后再拷贝到进程的内存地址。blog

对于写操做,数据先被写到流缓冲,而后将屡次写操做一次性写到页缓冲(减小系统调用),页缓冲再将屡次写操做一次性写到磁盘(提升磁盘io效率)接口

 

2  linux中的几种IO模型

网络io的本质是socket的读取。对于一次网络io请求,有两个阶段:进程

  a 等待对端传递的数据就绪,就绪就拷贝到系统内核缓冲区,若是没有就绪就一直等待就绪。

  b 将内核缓冲区中的数据拷贝到进程的地址空间中。

2.1 bio

 

阻塞io是最经常使用的socket模型,而且默认状况下,全部socket都是阻塞的。

首先,进程要请求网络数据时,使用recvfrom系统调用函数,而后系统调用从用户空间转移到内核空间运行。在内核空间等待对端数据报的到达,到达后内核空间的缓冲区后,把数据报拷贝到用户空间应用的缓冲地址。这个过程完成后,就返回获取成功给进程,进程没有延迟,开始处理数据报。

整个过程当中,进程都是自我阻塞的,在等待数据就绪的过程当中,进程只能等待,没法做其余事情。好处是数据一就绪,进程就立刻能够进行下一步的处理。

2.2 nio

在非阻塞模型中,当系统调用发现内核空间中未准备好数据,则直接返回一个error。进程会周期性轮训,询问内核空间是否准备好好数据。在此期间,进程不会等待(就是非阻塞)。

相对于阻塞模型,非阻塞模型释放了进程,能够同时处理其余信息。但因为是周期性轮训,进程就不会在第一时间知道网路数据已准备好,因此增长了延迟。

但若是进程要处理多个socket,非阻塞模型老是比阻塞模型效率更高。

2.3 mio

 

就是用select、epoll、poll,将多个socket的文件描述符传给内核,让内核去监听它们是否就绪。

当用户进程调用 select,整个进程就被阻塞,当任何一个socket的数据在内核中 准备好了,select就会将可读条件返回。而后进程使用系统调用,将数据拷贝到用户空间(这一步就至关于bio)。

nio是进程主动去询问多个socket的数据在内核中是否准备好,而mio是采用select去实时监听多个socket在内核中的数据是否准备好。

 2.4 aio

进程使用aio_read函数将socket文件描述符,缓冲区指针、缓冲区大小和文件偏移传递给内核,而且告诉内核等数据准备好后直接传给aio_read中。

进程不阻塞,数据准备好后,不须要进程再经过系统调用去读。

2.5 比较

bio,nio,mio,在数据拷贝到用户空间这个阶段进程会被阻塞,属于同步模型。

aio在这个阶段进程不被阻塞

相关文章
相关标签/搜索