当前位置: 首页 > news >正文

seo网站关键词违反建设投诉网站举报

seo网站关键词,违反建设投诉网站举报,微网站素材,建设厅网站文件作者 | 小林coding来源 | 小林coding#xff08;CodingLin#xff09;文件系统的基本组成文件系统是操作系统中负责管理持久数据的子系统#xff0c;说简单点#xff0c;就是负责把用户的文件存到磁盘硬件中#xff0c;因为即使计算机断电了#xff0c;磁盘里的数据并不会… 作者 | 小林coding来源 | 小林codingCodingLin文件系统的基本组成文件系统是操作系统中负责管理持久数据的子系统说简单点就是负责把用户的文件存到磁盘硬件中因为即使计算机断电了磁盘里的数据并不会丢失所以可以持久化的保存文件。文件系统的基本数据单位是文件它的目的是对磁盘上的文件进行组织管理那组织的方式不同就会形成不同的文件系统。Linux 最经典的一句话是「一切皆文件」不仅普通的文件和目录就连块设备、管道、socket 等也都是统一交给文件系统管理的。Linux 文件系统会为每个文件分配两个数据结构索引节点index node和目录项directory entry它们主要用来记录文件的元信息和目录层次结构。索引节点也就是 inode用来记录文件的元信息比如 inode 编号、文件大小、访问权限、创建时间、修改时间、数据在磁盘的位置等等。索引节点是文件的唯一标识它们之间一一对应也同样都会被存储在硬盘中所以索引节点同样占用磁盘空间。目录项也就是 dentry用来记录文件的名字、索引节点指针以及与其他目录项的层级关联关系。多个目录项关联起来就会形成目录结构但它与索引节点不同的是目录项是由内核维护的一个数据结构不存放于磁盘而是缓存在内存。由于索引节点唯一标识一个文件而目录项记录着文件的名所以目录项和索引节点的关系是多对一也就是说一个文件可以有多个别字。比如硬链接的实现就是多个目录项中的索引节点指向同一个文件。注意目录也是文件也是用索引节点唯一标识和普通文件不同的是普通文件在磁盘里面保存的是文件数据而目录文件在磁盘里面保存子目录或文件。目录项和目录是一个东西吗虽然名字很相近但是它们不是一个东西目录是个文件持久化存储在磁盘而目录项是内核一个数据结构缓存在内存。如果查询目录频繁从磁盘读效率会很低所以内核会把已经读过的目录用目录项这个数据结构缓存在内存下次再次读到相同的目录时只需从内存读就可以大大提高了文件系统的效率。注意目录项这个数据结构不只是表示目录也是可以表示文件的。那文件数据是如何存储在磁盘的呢磁盘读写的最小单位是扇区扇区的大小只有 512B 大小很明显如果每次读写都以这么小为单位那这读写的效率会非常低。所以文件系统把多个扇区组成了一个逻辑块每次读写的最小单位就是逻辑块数据块Linux 中的逻辑块大小为 4KB也就是一次性读写 8 个扇区这将大大提高了磁盘的读写的效率。以上就是索引节点、目录项以及文件数据的关系下面这个图就很好的展示了它们之间的关系索引节点是存储在硬盘上的数据那么为了加速文件的访问通常会把索引节点加载到内存中。另外磁盘进行格式化的时候会被分成三个存储区域分别是超级块、索引节点区和数据块区。超级块用来存储文件系统的详细信息比如块个数、块大小、空闲块等等。索引节点区用来存储索引节点数据块区用来存储文件或目录数据我们不可能把超级块和索引节点区全部加载到内存这样内存肯定撑不住所以只有当需要使用的时候才将其加载进内存它们加载进内存的时机是不同的超级块当文件系统挂载时进入内存索引节点区当文件被访问时进入内存虚拟文件系统文件系统的种类众多而操作系统希望对用户提供一个统一的接口于是在用户层与文件系统层引入了中间层这个中间层就称为虚拟文件系统Virtual File SystemVFS。VFS 定义了一组所有文件系统都支持的数据结构和标准接口这样程序员不需要了解文件系统的工作原理只需要了解 VFS 提供的统一接口即可。在 Linux 文件系统中用户空间、系统调用、虚拟机文件系统、缓存、文件系统以及存储之间的关系如下图Linux 支持的文件系统也不少根据存储位置的不同可以把文件系统分为三类磁盘的文件系统它是直接把数据存储在磁盘中比如 Ext 2/3/4、XFS 等都是这类文件系统。内存的文件系统这类文件系统的数据不是存储在硬盘的而是占用内存空间我们经常用到的 /proc 和 /sys 文件系统都属于这一类读写这类文件实际上是读写内核中相关的数据数据。网络的文件系统用来访问其他计算机主机数据的文件系统比如 NFS、SMB 等等。文件系统首先要先挂载到某个目录才可以正常使用比如 Linux 系统在启动时会把文件系统挂载到根目录。文件的使用我们从用户角度来看文件的话就是我们要怎么使用文件首先我们得通过系统调用来打开一个文件。fd  open(name, flag); # 打开文件 ... write(fd,...);         # 写数据 ... close(fd);             # 关闭文件 上面简单的代码是读取一个文件的过程首先用 open 系统调用打开文件open 的参数中包含文件的路径名和文件名。使用 write 写数据其中 write 使用 open 所返回的文件描述符并不使用文件名作为参数。使用完文件后要用 close 系统调用关闭文件避免资源的泄露。我们打开了一个文件后操作系统会跟踪进程打开的所有文件所谓的跟踪呢就是操作系统为每个进程维护一个打开文件表文件表里的每一项代表「文件描述符」所以说文件描述符是打开文件的标识。打开文件表操作系统在打开文件表中维护着打开文件的状态和信息文件指针系统跟踪上次读写位置作为当前文件位置指针这种指针对打开文件的某个进程来说是唯一的文件打开计数器文件关闭时操作系统必须重用其打开文件表条目否则表内空间不够用。因为多个进程可能打开同一个文件所以系统在删除打开文件条目之前必须等待最后一个进程关闭文件该计数器跟踪打开和关闭的数量当该计数为 0 时系统关闭文件删除该条目文件磁盘位置绝大多数文件操作都要求系统修改文件数据该信息保存在内存中以免每个操作都从磁盘中读取访问权限每个进程打开文件都需要有一个访问模式创建、只读、读写、添加等该信息保存在进程的打开文件表中以便操作系统能允许或拒绝之后的 I/O 请求在用户视角里文件就是一个持久化的数据结构但操作系统并不会关心你想存在磁盘上的任何的数据结构操作系统的视角是如何把文件数据和磁盘块对应起来。所以用户和操作系统对文件的读写操作是有差异的用户习惯以字节的方式读写文件而操作系统则是以数据块来读写文件那屏蔽掉这种差异的工作就是文件系统了。我们来分别看一下读文件和写文件的过程当用户进程从文件读取 1 个字节大小的数据时文件系统则需要获取字节所在的数据块再返回数据块对应的用户进程所需的数据部分。当用户进程把 1 个字节大小的数据写进文件时文件系统则找到需要写入数据的数据块的位置然后修改数据块中对应的部分最后再把数据块写回磁盘。所以说文件系统的基本操作单位是数据块。文件的存储文件的数据是要存储在硬盘上面的数据在磁盘上的存放方式就像程序在内存中存放的方式那样有以下两种连续空间存放方式非连续空间存放方式其中非连续空间存放方式又可以分为「链表方式」和「索引方式」。不同的存储方式有各自的特点重点是要分析它们的存储效率和读写性能接下来分别对每种存储方式说一下。连续空间存放方式连续空间存放方式顾名思义文件存放在磁盘「连续的」物理空间中。这种模式下文件的数据都是紧密相连读写效率很高因为一次磁盘寻道就可以读出整个文件。使用连续存放的方式有一个前提必须先知道一个文件的大小这样文件系统才会根据文件的大小在磁盘上找到一块连续的空间分配给文件。所以文件头里需要指定「起始块的位置」和「长度」有了这两个信息就可以很好的表示文件存放方式是一块连续的磁盘空间。注意此处说的文件头就类似于 Linux 的 inode。连续空间存放方式连续空间存放的方式虽然读写效率高但是有「磁盘空间碎片」和「文件长度不易扩展」的缺陷。如下图如果文件 B 被删除磁盘上就留下一块空缺这时如果新来的文件小于其中的一个空缺我们就可以将其放在相应空缺里。但如果该文件的大小大于所有的空缺但却小于空缺大小之和则虽然磁盘上有足够的空缺但该文件还是不能存放。当然了我们可以通过将现有文件进行挪动来腾出空间以容纳新的文件但是这个在磁盘挪动文件是非常耗时所以这种方式不太现实。磁盘碎片另外一个缺陷是文件长度扩展不方便例如上图中的文件 A 要想扩大一下需要更多的磁盘空间唯一的办法就只能是挪动的方式前面也说了这种方式效率是非常低的。那么有没有更好的方式来解决上面的问题呢答案当然有既然连续空间存放的方式不太行那么我们就改变存放的方式使用非连续空间存放方式来解决这些缺陷。非连续空间存放方式非连续空间存放方式分为「链表方式」和「索引方式」。我们先来看看链表的方式。链表的方式存放是离散的不用连续的于是就可以消除磁盘碎片可大大提高磁盘空间的利用率同时文件的长度可以动态扩展。根据实现的方式的不同链表可分为「隐式链表」和「显式链接」两种形式。文件要以「隐式链表」的方式存放的话实现的方式是文件头要包含「第一块」和「最后一块」的位置并且每个数据块里面留出一个指针空间用来存放下一个数据块的位置这样一个数据块连着一个数据块从链头看是就可以顺着指针找到所有的数据块所以存放的方式可以是不连续的。隐式链表隐式链表的存放方式的缺点在于无法直接访问数据块只能通过指针顺序访问文件以及数据块指针消耗了一定的存储空间。隐式链接分配的稳定性较差系统在运行过程中由于软件或者硬件错误导致链表中的指针丢失或损坏会导致文件数据的丢失。如果取出每个磁盘块的指针把它放在内存的一个表中就可以解决上述隐式链表的两个不足。那么这种实现方式是「显式链接」它指把用于链接文件各数据块的指针显式地存放在内存的一张链接表中该表在整个磁盘仅设置一张每个表项中存放链接指针指向下一个数据块号。对于显式链接的工作方式我们举个例子文件 A 依次使用了磁盘块 4、7、2、10 和 12 文件 B 依次使用了磁盘块 6、3、11 和 14 。利用下图中的表可以从第 4 块开始顺着链走到最后找到文件 A 的全部磁盘块。同样从第 6 块开始顺着链走到最后也能够找出文件 B 的全部磁盘块。最后这两个链都以一个不属于有效磁盘编号的特殊标记如 -1 结束。内存中的这样一个表格称为文件分配表File Allocation TableFAT。显式链接由于查找记录的过程是在内存中进行的因而不仅显著地提高了检索速度而且大大减少了访问磁盘的次数。但也正是整个表都存放在内存中的关系它的主要的缺点是不适用于大磁盘。比如对于 200GB 的磁盘和 1KB 大小的块这张表需要有 2 亿项每一项对应于这 2 亿个磁盘块中的一个块每项如果需要 4 个字节那这张表要占用 800MB 内存很显然 FAT 方案对于大磁盘而言不太合适。接下来我们来看看索引的方式。链表的方式解决了连续分配的磁盘碎片和文件动态扩展的问题但是不能有效支持直接访问FAT除外索引的方式可以解决这个问题。索引的实现是为每个文件创建一个「索引数据块」里面存放的是指向文件数据块的指针列表说白了就像书的目录一样要找哪个章节的内容看目录查就可以。另外文件头需要包含指向「索引数据块」的指针这样就可以通过文件头知道索引数据块的位置再通过索引数据块里的索引信息找到对应的数据块。创建文件时索引块的所有指针都设为空。当首次写入第 i 块时先从空闲空间中取得一个块再将其地址写到索引块的第 i 个条目。索引的方式索引的方式优点在于文件的创建、增大、缩小很方便不会有碎片的问题支持顺序读写和随机读写由于索引数据也是存放在磁盘块的如果文件很小明明只需一块就可以存放的下但还是需要额外分配一块来存放索引数据所以缺陷之一就是存储索引带来的开销。如果文件很大大到一个索引数据块放不下索引信息这时又要如何处理大文件的存放呢我们可以通过组合的方式来处理大文件的存。先来看看链表 索引的组合这种组合称为「链式索引块」它的实现方式是在索引数据块留出一个存放下一个索引数据块的指针于是当一个索引数据块的索引信息用完了就可以通过指针的方式找到下一个索引数据块的信息。那这种方式也会出现前面提到的链表方式的问题万一某个指针损坏了后面的数据也就会无法读取了。链式索引块还有另外一种组合方式是索引 索引的方式这种组合称为「多级索引块」实现方式是通过一个索引块来存放多个索引数据块一层套一层索引像极了俄罗斯套娃是吧。多级索引块Unix 文件的实现方式我们先把前面提到的文件实现方式做个比较那早期 Unix 文件系统是组合了前面的文件存放方式的优点如下图早期 Unix 文件系统它是根据文件的大小存放的方式会有所变化如果存放文件所需的数据块小于 10 块则采用直接查找的方式如果存放文件所需的数据块超过 10 块则采用一级间接索引方式如果前面两种方式都不够存放大文件则采用二级间接索引方式如果二级间接索引也不够存放大文件采用三级间接索引方式那么文件头Inode就需要包含 13 个指针10 个指向数据块的指针第 11 个指向索引块的指针第 12 个指向二级索引块的指针第 13 个指向三级索引块的指针所以这种方式能很灵活地支持小文件和大文件的存放对于小文件使用直接查找的方式可减少索引数据块的开销对于大文件则以多级索引的方式来支持所以大文件在访问数据块时需要大量查询这个方案就用在了 Linux Ext 2/3 文件系统里虽然解决大文件的存储但是对于大文件的访问需要大量的查询效率比较低。为了解决这个问题Ext 4 做了一定的改变具体怎么解决的本文就不展开了。空闲空间管理前面说到的文件的存储是针对已经被占用的数据块组织和管理接下来的问题是如果我要保存一个数据块我应该放在硬盘上的哪个位置呢难道需要将所有的块扫描一遍找个空的地方随便放吗那这种方式效率就太低了所以针对磁盘的空闲空间也是要引入管理的机制接下来介绍几种常见的方法空闲表法空闲链表法位图法空闲表法空闲表法就是为所有空闲空间建立一张表表内容包括空闲区的第一个块号和该空闲区的块个数注意这个方式是连续分配的。如下图空闲表法当请求分配磁盘空间时系统依次扫描空闲表里的内容直到找到一个合适的空闲区域为止。当用户撤销一个文件时系统回收文件空间。这时也需顺序扫描空闲表寻找一个空闲表条目并将释放空间的第一个物理块号及它占用的块数填到这个条目中。这种方法仅当有少量的空闲区时才有较好的效果。因为如果存储空间中有着大量的小的空闲区则空闲表变得很大这样查询效率会很低。另外这种分配技术适用于建立连续文件。空闲链表法我们也可以使用「链表」的方式来管理空闲空间每一个空闲块里有一个指针指向下一个空闲块这样也能很方便的找到空闲块并管理起来。如下图空闲链表法当创建文件需要一块或几块时就从链头上依次取下一块或几块。反之当回收空间时把这些空闲块依次接到链头上。这种技术只要在主存中保存一个指针令它指向第一个空闲块。其特点是简单但不能随机访问工作效率低因为每当在链上增加或移动空闲块时需要做很多 I/O 操作同时数据块的指针消耗了一定的存储空间。空闲表法和空闲链表法都不适合用于大型文件系统因为这会使空闲表或空闲链表太大。位图法位图是利用二进制的一位来表示磁盘中一个盘块的使用情况磁盘上所有的盘块都有一个二进制位与之对应。当值为 0 时表示对应的盘块空闲值为 1 时表示对应的盘块已分配。它形式如下1111110011111110001110110111111100111 ... 在 Linux 文件系统就采用了位图的方式来管理空闲空间不仅用于数据空闲块的管理还用于 inode 空闲块的管理因为 inode 也是存储在磁盘的自然也要有对其管理。文件系统的结构前面提到 Linux 是用位图的方式管理空闲空间用户在创建一个新文件时Linux 内核会通过 inode 的位图找到空闲可用的 inode并进行分配。要存储数据时会通过块的位图找到空闲的块并分配但仔细计算一下还是有问题的。数据块的位图是放在磁盘块里的假设是放在一个块里一个块 4K每位表示一个数据块共可以表示 4 * 1024 * 8 2^15 个空闲块由于 1 个数据块是 4K 大小那么最大可以表示的空间为 2^15 * 4 * 1024 2^27 个 byte也就是 128M。也就是说按照上面的结构如果采用「一个块的位图 一系列的块」外加「一个块的 inode 的位图 一系列的 inode 的结构」能表示的最大空间也就 128M这太少了现在很多文件都比这个大。在 Linux 文件系统把这个结构称为一个块组那么有 N 多的块组就能够表示 N 大的文件。下图给出了 Linux Ext2 整个文件系统的结构和块组的内容文件系统都由大量块组组成在硬盘上相继排布最前面的第一个块是引导块在系统启动时用于启用引导接着后面就是一个一个连续的块组了块组的内容如下超级块包含的是文件系统的重要信息比如 inode 总个数、块总个数、每个块组的 inode 个数、每个块组的块个数等等。块组描述符包含文件系统中各个块组的状态比如块组中空闲块和 inode 的数目等每个块组都包含了文件系统中「所有块组的组描述符信息」。数据位图和 inode 位图 用于表示对应的数据块或 inode 是空闲的还是被使用中。inode 列表包含了块组中所有的 inodeinode 用于保存文件系统中与各个文件和目录相关的所有元数据。数据块包含文件的有用数据。你可以会发现每个块组里有很多重复的信息比如超级块和块组描述符表这两个都是全局信息而且非常的重要这么做是有两个原因如果系统崩溃破坏了超级块或块组描述符有关文件系统结构和内容的所有信息都会丢失。如果有冗余的副本该信息是可能恢复的。通过使文件和管理数据尽可能接近减少了磁头寻道和旋转这可以提高文件系统的性能。不过Ext2 的后续版本采用了稀疏技术。该做法是超级块和块组描述符表不再存储到文件系统的每个块组中而是只写入到块组 0、块组 1 和其他 ID 可以表示为 3、 5、7 的幂的块组中。目录的存储在前面我们知道了一个普通文件是如何存储的但还有一个特殊的文件经常用到的目录它是如何保存的呢基于 Linux 一切皆文件的设计思想目录其实也是个文件你甚至可以通过 vim 打开它它也有 inodeinode 里面也是指向一些块。和普通文件不同的是普通文件的块里面保存的是文件数据而目录文件的块里面保存的是目录里面一项一项的文件信息。在目录文件的块中最简单的保存格式就是列表就是一项一项地将目录下的文件信息如文件名、文件 inode、文件类型等列在表里。列表中每一项就代表该目录下的文件的文件名和对应的 inode通过这个 inode就可以找到真正的文件。目录格式哈希表通常第一项是「.」表示当前目录第二项是「..」表示上一级目录接下来就是一项一项的文件名和 inode。如果一个目录有超级多的文件我们要想在这个目录下找文件按照列表一项一项的找效率就不高了。于是保存目录的格式改成哈希表对文件名进行哈希计算把哈希值保存起来如果我们要查找一个目录下面的文件名可以通过名称取哈希。如果哈希能够匹配上就说明这个文件的信息在相应的块里面。Linux 系统的 ext 文件系统就是采用了哈希表来保存目录的内容这种方法的优点是查找非常迅速插入和删除也较简单不过需要一些预备措施来避免哈希冲突。目录查询是通过在磁盘上反复搜索完成需要不断地进行 I/O 操作开销较大。所以为了减少 I/O 操作把当前使用的文件目录缓存在内存以后要使用该文件时只要在内存中操作从而降低了磁盘操作次数提高了文件系统的访问速度。软链接和硬链接有时候我们希望给某个文件取个别名那么在 Linux 中可以通过硬链接Hard Link和软链接Symbolic Link的方式来实现它们都是比较特殊的文件但是实现方式也是不相同的。硬链接是多个目录项中的「索引节点」指向一个文件也就是指向同一个 inode但是 inode 是不可能跨越文件系统的每个文件系统都有各自的 inode 数据结构和列表所以硬链接是不可用于跨文件系统的。由于多个目录项都是指向一个 inode那么只有删除文件的所有硬链接以及源文件时系统才会彻底删除该文件。硬链接软链接相当于重新创建一个文件这个文件有独立的 inode但是这个文件的内容是另外一个文件的路径所以访问软链接的时候实际上相当于访问到了另外一个文件所以软链接是可以跨文件系统的甚至目标文件被删除了链接文件还是在的只不过指向的文件找不到了而已。软链接文件 I/O文件的读写方式各有千秋对于文件的 I/O 分类也非常多常见的有缓冲与非缓冲 I/O直接与非直接 I/O阻塞与非阻塞 I/O VS 同步与异步 I/O接下来分别对这些分类讨论讨论。缓冲与非缓冲 I/O文件操作的标准库是可以实现数据的缓存那么根据「是否利用标准库缓冲」可以把文件 I/O 分为缓冲 I/O 和非缓冲 I/O缓冲 I/O利用的是标准库的缓存实现文件的加速访问而标准库再通过系统调用访问文件。非缓冲 I/O直接通过系统调用访问文件不经过标准库缓存。这里所说的「缓冲」特指标准库内部实现的缓冲。比方说很多程序遇到换行时才真正输出而换行前的内容其实就是被标准库暂时缓存了起来这样做的目的是减少系统调用的次数毕竟系统调用是有 CPU 上下文切换的开销的。直接与非直接 I/O我们都知道磁盘 I/O 是非常慢的所以 Linux 内核为了减少磁盘 I/O 次数在系统调用后会把用户数据拷贝到内核中缓存起来这个内核缓存空间也就是「页缓存」只有当缓存满足某些条件的时候才发起磁盘 I/O 的请求。那么根据是「否利用操作系统的缓存」可以把文件 I/O 分为直接 I/O 与非直接 I/O直接 I/O不会发生内核缓存和用户程序之间数据复制而是直接经过文件系统访问磁盘。非直接 I/O读操作时数据从内核缓存中拷贝给用户程序写操作时数据从用户程序拷贝给内核缓存再由内核决定什么时候写入数据到磁盘。如果你在使用文件操作类的系统调用函数时指定了 O_DIRECT 标志则表示使用直接 I/O。如果没有设置过默认使用的是非直接 I/O。如果用了非直接 I/O 进行写数据操作内核什么情况下才会把缓存数据写入到磁盘以下几种场景会触发内核缓存的数据写入磁盘在调用 write 的最后当发现内核缓存的数据太多的时候内核会把数据写到磁盘上用户主动调用 sync内核缓存会刷到磁盘上当内存十分紧张无法再分配页面时也会把内核缓存的数据刷到磁盘上内核缓存的数据的缓存时间超过某个时间时也会把数据刷到磁盘上阻塞与非阻塞 I/O VS 同步与异步 I/O为什么把阻塞 / 非阻塞与同步与异步放一起说的呢因为它们确实非常相似也非常容易混淆不过它们之间的关系还是有点微妙的。先来看看阻塞 I/O当用户程序执行 read 线程会被阻塞一直等到内核数据准备好并把数据从内核缓冲区拷贝到应用程序的缓冲区中当拷贝过程完成read 才会返回。注意阻塞等待的是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程。过程如下图阻塞 I/O知道了阻塞 I/O 来看看非阻塞 I/O非阻塞的 read 请求在数据未准备好的情况下立即返回可以继续往下执行此时应用程序不断轮询内核直到数据准备好内核将数据拷贝到应用程序缓冲区read 调用才可以获取到结果。过程如下图非阻塞 I/O注意这里最后一次 read 调用获取数据的过程是一个同步的过程是需要等待的过程。这里的同步指的是内核态的数据拷贝到用户程序的缓存区这个过程。举个例子访问管道或 socket 时如果设置了 O_NONBLOCK 标志那么就表示使用的是非阻塞 I/O 的方式访问而不做任何设置的话默认是阻塞 I/O。应用程序每次轮询内核的 I/O 是否准备好感觉有点傻乎乎因为轮询的过程中应用程序啥也做不了只是在循环。为了解决这种傻乎乎轮询方式于是 I/O 多路复用技术就出来了如 select、poll它是通过 I/O 事件分发当内核数据准备好时再以事件通知应用程序进行操作。这个做法大大改善了应用进程对 CPU 的利用率在没有被通知的情况下应用进程可以使用 CPU 做其他的事情。下图是使用 select I/O 多路复用过程。注意read 获取数据的过程数据从内核态拷贝到用户态的过程也是一个同步的过程需要等待I/O 多路复用实际上无论是阻塞 I/O、非阻塞 I/O还是基于非阻塞 I/O 的多路复用都是同步调用。因为它们在 read 调用时内核将数据从内核空间拷贝到应用程序空间过程都是需要等待的也就是说这个过程是同步的如果内核实现的拷贝效率不高read 调用就会在这个同步过程中等待比较长的时间。而真正的异步 I/O 是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程都不用等待。当我们发起 aio_read 之后就立即返回内核自动将数据从内核空间拷贝到应用程序空间这个拷贝过程同样是异步的内核自动完成的和前面的同步操作不一样应用程序并不需要主动发起拷贝动作。过程如下图异步 I/O下面这张图总结了以上几种 I/O 模型在前面我们知道了I/O 是分为两个过程的数据准备的过程数据从内核空间拷贝到用户进程缓冲区的过程阻塞 I/O 会阻塞在「过程 1 」和「过程 2」而非阻塞 I/O 和基于非阻塞 I/O 的多路复用只会阻塞在「过程 2」所以这三个都可以认为是同步 I/O。异步 I/O 则不同「过程 1 」和「过程 2 」都不会阻塞。用故事去理解这几种 I/O 模型举个你去饭堂吃饭的例子你好比用户程序饭堂好比操作系统。阻塞 I/O 好比你去饭堂吃饭但是饭堂的菜还没做好然后你就一直在那里等啊等等了好长一段时间终于等到饭堂阿姨把菜端了出来数据准备的过程但是你还得继续等阿姨把菜内核空间打到你的饭盒里用户空间经历完这两个过程你才可以离开。非阻塞 I/O 好比你去了饭堂问阿姨菜做好了没有阿姨告诉你没你就离开了过几十分钟你又来饭堂问阿姨阿姨说做好了于是阿姨帮你把菜打到你的饭盒里这个过程你是得等待的。基于非阻塞的 I/O 多路复用好比你去饭堂吃饭发现有一排窗口饭堂阿姨告诉你这些窗口都还没做好菜等做好了再通知你于是等啊等select 调用中过了一会阿姨通知你菜做好了但是不知道哪个窗口的菜做好了你自己看吧。于是你只能一个一个窗口去确认后面发现 5 号窗口菜做好了于是你让 5 号窗口的阿姨帮你打菜到饭盒里这个打菜的过程你是要等待的虽然时间不长。打完菜后你自然就可以离开了。异步 I/O 好比你让饭堂阿姨将菜做好并把菜打到饭盒里后把饭盒送到你面前整个过程你都不需要任何等待。推荐阅读2019年中国IaaS公有云市场排名及份额出炉Tomcat 架构原理解析到架构设计借鉴CPU别再拿我当搬砖工苹果等多家美企抵制白宫封杀微信阿里成立新公司“京西”Apache Kafka 2.5.1发布| 极客头条马小峰金融科技界的区块链博士
http://www.sadfv.cn/news/359299/

相关文章:

  • 制作软件网站中国企业报集团简介
  • 帝国cms7.0模板 绿色企业网站模板(整站带数据)网站上线盈利
  • 做网站用什么语言制作最安全海外网络搭建
  • 2021没封的网站有人分享吗自己做的网站可以发布吗
  • 西宁哪里做网站品牌设计和广告设计
  • c 做的博客网站深圳网站关键词排名优化
  • 河口企业网站开发公司重庆市建设工程信息网查询人员
  • 66039域名查询网seo教程视频
  • 陕西做网站电话连云港东海网站建设
  • 宁乡网站建设uuv9苏州网站网站建设
  • 个人相册网站建设报告网站建设 课题研究的背景
  • 常平东站是东莞东站吗大连做网站公司排行榜
  • 网站商城开发中山火炬开发区建设局网站
  • 门户网站网站开发网络推广公司开业广告
  • 互动网络游戏公司网站建设网销具体怎么做网站
  • 温县住房与城乡建设局网站哪个网站做推广做的最好
  • asp.net做报名网站怎么选择合适的网站开发公司
  • 企业网站策划书宜宾seo网站建设
  • 贵阳市网站优化南昌网站设计制作
  • 海南网站建设有些网站域名解析错误
  • 长宁网站建设大连 建网站
  • 网站切片 做程序找黄岩做网站企业
  • 建设网站的方案品牌形象设计方案
  • 博客网站素材手机如何制作网站教程
  • 大型网站方案咨询企业网站模板
  • 在网站服务器上建立数据库wordpress 收费会员
  • 怎么改网站模板html开发工具
  • 自建网站 支付宝商城在线
  • 婚恋网网站架构商业招商网站
  • 长沙网站定制建设做淘客网站能干嘛