提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本文主要是针对Socket I/O 模型做自我学习总结。
网络I/O的模型大致有如下几种: 网络I/O的本质是socket的读取,socket在linux系统被抽象为流,I/O可以理解为对流的操作。 这个操作又分为两个阶段: 等待流数据准备(wating for the data to be ready)。 从内核向进程复制数据(copying the data from the kernel to the process)。 第一步通常涉及等待网络上的数据分组到达,然后被复制到内核的某个缓冲区。 第二步把数据从内核缓冲区复制到应用进程缓冲区。 举个简单比喻,来了解这几种模型。 网络IO好比钓鱼,等待鱼上钩就是网络中等待数据准备好的过程,鱼上钩了,把鱼拉上岸就是内核复制数据阶段。 钓鱼的人就是一个应用进程。 阻塞I/O是最流行的I/O模型。
一、基本概念
进程(线程)切换:所有系统都有调度进程的能力,它可以挂起一个当前正在运行的进程,并恢复之前挂起的进程。
进程(线程)的阻塞:运行中的进程,有时会等待其他事件的执行完成,比如等待锁,请求I/O的读写;进程在等待过程会被系统自动执行阻塞,此时进程不占用CPU。
文件描述符:在Linux,文件描述符是一个用于表述指向文件引用的抽象化概念,它是一个非负整数。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符,网络套接字也是文件描述符。
Linux信号处理:Linux进程运行中可以接收来自系统或者进程的信号值,然后根据信号值去运行相应捕捉函数;信号相当于是硬件中断的软件模拟。
用户空间和内核空间:操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的权限。为了避免用户进程直接操作内核,保证内核安全,操作系统将虚拟内存划分为两部分,一部分是内核空间(kernel-space),一部分是用户空间(user-space)。在linux系统中,内核模块运行在内核空间,对应的进程处于内核态;而用户程序运行在用户空间,对应的进程处于用户态。
同步:调用某个东西,调用方得等待这个调用结果返回才能继续往后执行。
异步:和同步相反,调用方不会立刻得到结果,而是在调用发出之后调用者可以继续执行后续的操作,被调用者通过状态、通知或者回调函数来处理这个调用。
同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)。
阻塞:指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。
非阻塞:不能立刻得到结果之前,该调用不会阻塞当前线程,而会立刻返回。
阻塞和非阻塞 强调的是程序在等待调用结果(消息,返回值)时的状态。
同步异步不能和阻塞非阻塞混为一谈,实际上他们有区别。比如对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。 例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。
同步IO和异步IO的区别就在于:数据访问的时候进程是否阻塞。
阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回。
同步和异步都只针对于本机SOCKET而言的。
阻塞和非阻塞是指当server端的进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪;
而同步和异步是指client端访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就绪与读写两个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待"通知")
异步式I/O会以阻塞的方式等待I/O 操作的完成或数据的返回,而只是将I/O 请求发送给操作系统,继续执行下一条语句。当操作系统完成I/O 操作时,以事件的形式通知执行I/O 操作的线程,线程会在特定时候处理这个事件。为了处理异步I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予以处理。
阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程所使用的CPU 核心利用率永远是100%,I/O 以事件的方式通知。在阻塞模式下,多线程往往能提高系统吞吐量,因为一个线程阻塞时还有其他线程在工作,多线程可以让CPU 资源不被阻塞中的线程浪费。而在非阻塞模式下,线程不会被I/O 阻塞,永远在利用CPU。多线程带来的好处仅仅是在多核CPU 的情况下利用更多的核。
二、Unix 五种 I/O 模型:
1.阻塞式 I/O
应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。
在调用recv()/recvfrom()函数时,发生在内核中等待数据(R1阶段)和复制数据(R2阶段)的过程。
阻塞式I/O在R1和R2阶段都是阻塞的。
阻塞式I/O的特点:最基础的/O模型就是阻塞/O模型,也是最简单的模型。所有的操作都是顺序执行的。阻塞IO模型中,用户空间的应用程序执行一个系统调用(recvfrom),会导致应用程序被阻塞,直到内核缓冲区的数据准备好,并且将数据从内核复制到用户进程。最后进程才被