提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本文主要是针对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操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就