Le processus de transfert de fichiers dans le système d'exploitation

avant-propos

Récemment, j'ai passé en revue les connaissances liées au système d'exploitation, ce qui s'est passé pendant le processus de transfert de fichiers et comment le système d'exploitation a-t-il transféré le fichier ?

Brièvement

Le disque peut être considéré comme l'un des matériels les plus lents d'un système informatique. La vitesse de lecture et d'écriture est plus de 10 fois supérieure à celle de la mémoire. Par conséquent, il existe de nombreuses techniques d'optimisation des disques, telles que la copie zéro, l'E/S directe. O, E/S asynchrones, etc. Ces optimisations ont pour but d'améliorer le débit du système, et la zone de cache disque dans le noyau du système d'exploitation peut réduire efficacement le nombre d'accès au disque.

Pré-connaissance

espace utilisateur et espace noyau

  • L'espace mémoire utilisé par les fonctions centrales du système et les fonctions centrales du système d'exploitation exécutées dans l'espace noyau - l'espace noyau
  • Espace mémoire utilisé par les fonctions non essentielles, les applications et les fonctions non système s'exécutant dans l'espace utilisateur - espace utilisateur

appel système

Il est implémenté par le système d'exploitation et fourni au programme d'application pour accéder à la collection de toutes les interfaces de la fonction noyau.Pour comprendre simplement, l'appel système consiste à faire en sorte que le système d'exploitation complète certaines choses pour nous en appelant une méthode correspondante.

Qu'est-ce que le DMA

  • Technologie d'accès direct à la mémoire ( Direct Memory Access ) .
  • Une compréhension simple est que lorsque le transfert de données entre les périphériques d'E / S et la mémoire est effectué, le travail de transfert de données est entièrement transféré au contrôleur DMA, et le CPU ne participe plus aux questions liées au transfert de données, de sorte que le CPU peut s'occuper d'autres choses .

Processus IO sans participation du contrôleur DMA

Alors pourquoi utiliser la technologie DMA, avant qu'il n'y ait pas de technologie DMA, le processus d'E/S est comme ceci :

  • Le CPU envoie la commande correspondante au contrôleur de disque, puis revient ;
  • Une fois que le contrôleur de disque a reçu l'instruction, il commence à préparer les données, place les données dans la mémoire tampon interne du contrôleur de disque, puis génère une interruption ;
  • Une fois que la CPU a reçu le signal d'interruption, elle arrête le travail en cours, puis lit les données dans la mémoire tampon du contrôleur de disque dans son propre registre un octet à la fois, puis écrit les données dans le registre dans la mémoire, tandis que les données sont transmises. Pendant ce temps, la CPU ne peut pas effectuer d'autres tâches.

Impliqué avec le contrôleur DMA

  • 用户进程调用 read 方法,向操作系统发出 I/O 请求,请求读取数据到自己的内存缓冲区中,进程进入阻塞状态;
  • 操作系统收到请求后,进一步将 I/O 请求发送 DMA,然后让 CPU 执行其他任务;
  • DMA 进一步将 I/O 请求发送给磁盘;
  • 磁盘收到 DMA 的 I/O 请求,把数据从磁盘读取到磁盘控制器的缓冲区中,当磁盘控制器的缓冲区被读满后,向 DMA 发起中断信号,告知自己缓冲区已满;
  • DMA 收到磁盘的信号,将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中,此时不占用 CPU,CPU 可以执行其他任务
  • 当 DMA 读取了足够多的数据,就会发送中断信号给 CPU;
  • CPU 收到 DMA 的信号,知道数据已经准备好,于是将数据从内核拷贝到用户空间,系统调用返回;

可以看到, 整个数据传输的过程,CPU 不再参与数据搬运的工作,而是全程由 DMA 完成,但是 CPU 在这个过程中也是必不可少的,因为传输什么数据,从哪里传输到哪里,都需要 CPU 来告诉 DMA 控制器。

早期 DMA 只存在在主板上,如今由于 I/O 设备越来越多,数据传输的需求也不尽相同,所以每个 I/O 设备里面都有自己的 DMA 控制器。

零拷贝

开始回归正题,什么是零拷贝呢

传统文件传输

首先,期间共发生了 4 次用户态与内核态的上下文切换,因为发生了两次系统调用,一次是 read() ,一次是 write(),每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。

上下文切换到成本并不小,一次切换需要耗时几十纳秒到几微秒,虽然时间看上去很短,但是在高并发的场景下,这类时间容易被累积和放大,从而影响系统的性能。

其次,还发生了 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝的,下面说一下这个过程:

  • 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
  • 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。
  • 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。
  • 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

我们回过头看这个文件传输的过程,我们只是搬运一份数据,结果却搬运了 4 次,过多的数据拷贝无疑会消耗 CPU 资源,大大降低了系统性能。

这种简单又传统的文件传输方式,存在冗余的上文切换和数据拷贝,在高并发系统里是非常糟糕的,多了很多不必要的开销,会严重影响系统性能。

优化传输性能

减少「用户态与内核态的上下文切换」

要想提高文件传输的性能,就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数

读取磁盘数据的时候,之所以要发生上下文切换,这是因为用户空间没有权限操作磁盘或网卡,内核的权限最高,这些操作设备的过程都需要交由操作系统内核来完成,所以一般要通过内核去完成某些任务的时候,就需要使用操作系统提供的系统调用函数。

而一次系统调用必然会发生 2 次上下文切换:首先从用户态切换到内核态,当内核执行完任务后,再切换回用户态交由进程代码执行。

所以,要想减少上下文切换到次数,就要减少系统调用的次数

减少「数据拷贝」的次数

在前面我们知道了,传统的文件传输方式会历经 4 次数据拷贝,而且这里面,「从内核的读缓冲区拷贝到用户的缓冲区里,再从用户的缓冲区里拷贝到 socket 的缓冲区里」,这个过程是没有必要的。

因为文件传输的应用场景中,在用户空间我们并不会对数据「再加工」,所以数据实际上可以不用搬运到用户空间,因此用户的缓冲区是没有必要存在的

如何实现零拷贝

零拷贝技术实现的方式通常有 2 种:

  • mmap + write
  • sendfile

mmap + write

在前面我们知道,read() 系统调用的过程中会把内核缓冲区的数据拷贝到用户的缓冲区里,于是为了减少这一步开销,我们可以用 mmap() 替换 read() 系统调用函数。

mmap() 系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。

具体过程如下:

  • 应用进程调用了 mmap() 后,DMA 会把磁盘的数据拷贝到内核的缓冲区里。接着,应用进程跟操作系统内核「共享」这个缓冲区;
  • 应用进程再调用 write(),操作系统直接将内核缓冲区的数据拷贝到 socket 缓冲区中,这一切都发生在内核态,由 CPU 来搬运数据;
  • 最后,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程是由 DMA 搬运的。

我们可以得知,通过使用 mmap() 来代替 read(), 可以减少一次数据拷贝的过程。

但这还不是最理想的零拷贝,因为仍然需要通过 CPU 把内核缓冲区的数据拷贝到 socket 缓冲区里,而且仍然需要 4 次上下文切换,因为系统调用还是 2 次。

sendfile

在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile()

  • 它的前两个参数分别是目的端和源端的文件描述符,后面两个参数是源端的偏移量和复制数据的长度,返回值是实际复制数据的长度。
  • 首先,它可以替代前面的 read() 和 write() 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销。
  • 其次,该系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态,这样就只有 2 次上下文切换,和 3 次数据拷贝。如下图:

这就是所谓的零拷贝(Zero-copy)技术,因为我们没有在内存层面去拷贝数据,也就是说全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的。

零拷贝技术的文件传输方式相比传统文件传输的方式,减少了 2 次上下文切换和数据拷贝次数,只需要 2 次上下文切换和数据拷贝次数,就可以完成文件的传输,而且 2 次的数据拷贝过程,都不需要通过 CPU,2 次都是由 DMA 来搬运。

所以,总体来看,零拷贝技术可以把文件传输的性能提高至少一倍以上

Guess you like

Origin juejin.im/post/7157978128554557477