如何理解Linux操作系统 IO 模式

发布时间:2021-11-02 09:21:07 作者:柒染
来源:亿速云 阅读:147

这期内容当中小编将会给大家带来有关如何理解Linux操作系统 IO 模式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

 IO

如何理解Linux操作系统 IO 模式

IO  (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作,通常用户进程中的一个完整IO分为两阶段:用户进程空间<-->内核空间、内核空间<-->设备空间(磁盘、网络等)。IO有内存IO、网络IO和磁盘IO三种,通常我们说的IO指的是后两者。

LINUX中进程无法直接操作I/O设备,其必须通过系统调用请求kernel来协助完成I/O动作;内核会为每个I/O设备维护一个缓冲区。

对于一个输入操作来说,进程IO系统调用后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备IO一般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。

所以,对于一个网络输入操作通常包括两个不同阶段:

(1)等待网络数据到达网卡&rarr;读取到内核缓冲区,数据准备好;

(2)从内核缓冲区复制数据到进程空间。

关键概念理解

同步才有阻塞和非阻塞之分;

阻塞与非阻塞关乎如何对待事情产生的结果(阻塞:不等到想要的结果我就不走了)

明确进程状态

理解进程的状态转换

如何理解Linux操作系统 IO 模式

从操作系统层面执行应用程序理解 IO 模型

阻塞IO模型:

如何理解Linux操作系统 IO 模式

当调用recv()函数时,系统首先查是否有准备好的数据。如果数据没有准备好,那么系统就处于等待状态。当数据准备好后,将数据从系统缓冲区复制到用户空间,然后该函数返回。在套接应用程序中,当调用recv()函数时,未必用户空间就已经存在数据,那么此时recv()函数就会处于等待状态。

阻塞模式给网络编程带来了一个很大的问题,如在调用  send()的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。这给多客户机、多业务逻辑的网络编程带来了挑战。这时,我们可能会选择多线程的方式来解决这个问题。

应对多客户机的网络应用,最简单的解决方式是在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。

具体使用多进程还是多线程,并没有一个特定的模式。传统意义上,进程的开销要远远大于线程,所以,如果需要同时为较多的客户机提供服务,则不推荐使用多进程;如果单个服务执行体需要消耗较多的  CPU 资源,譬如需要进行大规模或长时间的数据运算或文件访问,则进程较为安全。

非阻塞IO模型

如何理解Linux操作系统 IO 模式

IO复用模型:

如何理解Linux操作系统 IO 模式

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。

所以,I/O  多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select()函数就可以返回。

异步IO模型

如何理解Linux操作系统 IO 模式

区别IO多路复用中的select poll epoll

select

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,  struct timeval *timeout); select  函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据  可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以  通过遍历fdset,来找到就绪的描述符

poll

int poll (struct pollfd *fds, unsigned int nfds, int timeout);  不同与select使用三个位图来表示三个fdset的方式,poll使用一个  pollfd的指针实现。pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。  和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。

epoll

epoll是通过事件的就绪通知方式,调用epoll_create创建实例,调用epoll_ctl添加或删除监控的文件描述符,调用epoll_wait阻塞住,直到有就绪的文件描述符,通过epoll_event参数返回就绪状态的文件描述符和事件。

epoll操作过程需要三个接口,分别如下: int epoll_create(int  size);//创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大 生成一个 epoll  专用的文件描述符,其实是申请一个内核空间,用来存放想关注的 socket fd 上是否发生以及发生了什么事件。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

控制某个 epoll 文件描述符上的事件:注册、修改、删除。其中参数 epfd 是 epoll_create() 创建 epoll  专用的文件描述符。

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int  timeout);

等待 I/O 事件的发生;返回发生事件数。参数说明:

epfd: 由 epoll_create() 生成的 Epoll 专用的文件描述符;

epoll_event: 用于回传代处理事件的数组;

maxevents: 每次能处理的事件数;

timeout: 等待 I/O 事件发生的超时值;

区别总结

(1)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。

(2)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,epoll 通过 mmap  把内核空间和用户空间映射到同一块内存,省去了拷贝的操作。

应用举例

tornado 的 IOLoop 模块 是异步机制的核心,它包含了一系列已经打开的文件描述符和每个描述符的处理器 (handlers)。这些  handlers 就是对 select, poll , epoll等的封装。(所以本质上说是 IO 复用)

没有用异步,通过使用多进程的WSGI server(比如uWSGI)来实现并发,这也是WSGI普遍的做法。

Linux后端服务器开发要学关于IO的哪些知识点

网络IO是网络通信的血管,数据是血液。血液的流动是不能离开血管的。

上述就是小编为大家分享的如何理解Linux操作系统 IO 模式了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. Java中BIO、NIO、AIO的理解
  2. 怎么理解JAVA IO流

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

io linux

上一篇:编译时JAVA最常见的错误是什么

下一篇:Java项目的UML反向工程工具是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》