Analisis ringkas teknologi salinan sifar dalam Linux

Lepaskan: 2023-08-04 16:23:14
ke hadapan
710 orang telah melayarinya

Artikel ini membincangkan teknologi sifar-salinan utama dan senario yang berkenaan teknologi sifar-salinan dalam Linux. Untuk mewujudkan konsep salinan sifar dengan cepat, kami memperkenalkan senario yang biasa digunakan:

Citation

Apabila menulis program pelayan (Pelayan Web atau pelayan fail), muat turun fail adalah fungsi asas . Pada masa ini, tugas pelayan adalah untuk menghantar fail dalam cakera hos pelayan dari soket yang disambungkan tanpa pengubahsuaian Kami biasanya menggunakan kod berikut untuk melengkapkannya:

while((n = read(diskfd, buf, BUF_SIZE)) > 0)
    write(sockfd, buf , n);
Salin selepas log masuk

Operasi asas adalah untuk membaca fail dari fail. cakera dalam kandungan gelung ke penimbal, dan kemudian hantar kandungan penimbal ke soket. Walau bagaimanapun, operasi I/O Linux lalai kepada I/O buffer. Dua panggilan sistem utama yang digunakan di sini ialah baca dan tulis Kami tidak tahu apa yang dilakukan oleh sistem pengendalian di dalamnya. Malah, berbilang salinan data berlaku semasa operasi I/O di atas.

Apabila aplikasi mengakses sekeping data tertentu, sistem pengendalian akan terlebih dahulu menyemak sama ada fail telah diakses baru-baru ini dan sama ada kandungan fail dicache dalam penimbal kernel Jika ya, sistem pengendalian akan menggunakan buf secara langsung disediakan oleh alamat panggilan sistem baca, salin kandungan penimbal kernel ke penimbal ruang pengguna yang ditentukan oleh buf. Jika tidak, sistem pengendalian mula-mula menyalin data pada cakera ke penimbal kernel Langkah ini pada masa ini bergantung terutamanya pada DMA untuk penghantaran, dan kemudian menyalin kandungan penimbal kernel kepada penimbal pengguna.

Seterusnya, panggilan sistem tulis menyalin kandungan penimbal pengguna ke penimbal kernel yang berkaitan dengan timbunan rangkaian, dan akhirnya soket menghantar kandungan penimbal kernel ke kad rangkaian. Setelah bercakap banyak, mari lihat gambar untuk menjadikannya lebih jelas:

Analisis ringkas teknologi salinan sifar dalam Linux

Salinan data

从上图中可以看出,共产生了四次数据拷贝,即使使用了DMA来处理了与硬件的通讯,CPU仍然需要处理两次数据拷贝,与此同时,在用户态与内核态也发生了多次上下文切换,无疑也加重了CPU负担。

在此过程中,我们没有对文件内容做任何修改,那么在内核空间和用户空间来回拷贝数据无疑就是一种浪费,而零拷贝主要就是为了解决这种低效性。

什么是零拷贝技术(zero-copy)?

零拷贝主要的任务就是避免CPU将数据从一块存储拷贝到另外一块存储,主要就是利用各种零拷贝技术,避免让CPU做大量的数据拷贝任务,减少不必要的拷贝,或者让别的组件来做这一类简单的数据传输任务,让CPU解脱出来专注于别的任务。这样就可以让系统资源的利用更加有效。

我们继续回到引文中的例子,我们如何减少数据拷贝的次数呢?一个很明显的着力点就是减少数据在内核空间和用户空间来回拷贝,这也引入了零拷贝的一个类型:

让数据传输不需要经过 user space。

使用 mmap

我们减少拷贝次数的一种方法是调用mmap()来代替read调用:

buf = mmap(diskfd, len);
write(sockfd, buf, len);
Salin selepas log masuk

应用程序调用mmap(),磁盘上的数据会通过DMA被拷贝的内核缓冲区,接着操作系统会把这段内核缓冲区与应用程序共享,这样就不需要把内核缓冲区的内容往用户空间拷贝。应用程序再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态,最后,socket缓冲区再把数据发到网卡去。同样的,看图很简单:

Analisis ringkas teknologi salinan sifar dalam Linux

mmap

Menggunakan mmap dan bukannya membaca jelas mengurangkan satu salinan Apabila jumlah data yang disalin adalah besar, ia sudah pasti meningkatkan kecekapan. Tetapi menggunakan mmap memerlukan kos. Apabila anda menggunakan mmap, anda mungkin menghadapi beberapa perangkap tersembunyi. Sebagai contoh, apabila program anda memetakan fail, tetapi apabila fail itu dipotong (dipotong) oleh proses lain, panggilan sistem tulis akan ditamatkan oleh isyarat SIGBUS kerana ia mengakses alamat yang tidak sah. Isyarat SIGBUS akan mematikan proses anda secara lalai dan menghasilkan coredump Jika pelayan anda dihentikan dengan cara ini, ia akan menyebabkan kerugian.

Biasanya kami menggunakan penyelesaian berikut untuk mengelakkan masalah ini:

1 Bina pengendali isyarat untuk isyarat SIGBUS

Apabila isyarat SIGBUS ditemui, pengendali isyarat hanya akan kembali. ialah Bilangan bait yang ditulis sebelum diganggu akan dikembalikan, dan errno akan ditetapkan kepada kejayaan, tetapi ini adalah pendekatan yang lemah kerana anda tidak menyelesaikan inti masalah sebenar.

2. Gunakan kunci pajakan fail

Biasanya kami menggunakan kaedah ini untuk menggunakan kunci pajakan pada deskriptor fail , Kernel akan menghantar isyarat RTSIGNALLEASE masa nyata kepada kami untuk memberitahu kami bahawa kernel memusnahkan kunci baca-tulis yang telah anda letakkan pada fail. Dengan cara ini, panggilan sistem tulis anda akan terganggu sebelum program mengakses memori haram dan dibunuh oleh SIGBUS. write akan mengembalikan bilangan bait yang ditulis dan menetapkan errno kepada kejayaan.

Kita harus mengunci fail mmap sebelum dan membuka kuncinya selepas mengendalikan fail:

if(fcntl(diskfd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
    perror("kernel lease set signal");
return -1;
}
/* l_type can be F_RDLCK F_WRLCK  加锁*/
/* l_type can be  F_UNLCK 解锁*/
if(fcntl(diskfd, F_SETLEASE, l_type)){
    perror("kernel lease set type");
return -1;
}
Salin selepas log masuk

使用sendfile

从2.1版内核开始,Linux引入了sendfile来简化操作:

#include<sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
Salin selepas log masuk

系统调用sendfile()在代表输入文件的描述符infd和代表输出文件的描述符outfd之间传送文件内容(字节)。描述符outfd必须指向一个套接字,而infd指向的文件必须是可以mmap的。这些局限限制了sendfile的使用,使sendfile只能将数据从文件传递到套接字上,反之则不行。

使用sendfile不仅减少了数据拷贝的次数,还减少了上下文切换,数据传送始终只发生在kernel space。

Analisis ringkas teknologi salinan sifar dalam Linux

sendfile系统调用过程

在我们调用sendfile时,如果有其它进程截断了文件会发生什么呢?假设我们没有设置任何信号处理程序,sendfile调用仅仅返回它在被中断之前已经传输的字节数,errno会被置为success。如果我们在调用sendfile之前给文件加了锁,sendfile的行为仍然和之前相同,我们还会收到RTSIGNALLEASE的信号。

目前为止,我们已经减少了数据拷贝的次数了,但是仍然存在一次拷贝,就是页缓存到socket缓存的拷贝。那么能不能把这个拷贝也省略呢?

借助于硬件上的帮助,我们是可以办到的。之前我们是把页缓存的数据拷贝到socket缓存中,实际上,我们仅仅需要把缓冲区描述符传到socket缓冲区,再把数据长度传过去,这样DMA控制器直接将页缓存中的数据打包发送到网络中就可以了。

总结一下,sendfile系统调用利用DMA引擎将文件内容拷贝到内核缓冲区去,然后将带有文件位置和长度信息的缓冲区描述符添加socket缓冲区去,这一步不会将内核中的数据拷贝到socket缓冲区中,DMA引擎会将内核缓冲区的数据拷贝到协议引擎中去,避免了最后一次拷贝。

Analisis ringkas teknologi salinan sifar dalam Linux

带DMA的sendfile

不过这一种收集拷贝功能是需要硬件以及驱动程序支持的。

使用splice

sendfile只适用于将数据从文件拷贝到套接字上,限定了它的使用范围。Linux在2.6.17版本引入splice系统调用,用于在两个文件描述符中移动数据:

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include<fcntl.h>
ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsignedint flags);
Salin selepas log masuk

splice调用在两个文件描述符之间移动数据,而不需要数据在内核空间和用户空间来回拷贝。他从fdin拷贝len长度的数据到fdout,但是有一方必须是管道设备,这也是目前splice的一些局限性。flags参数有以下几种取值:

  • SPLICEFMOVE :尝试去移动数据而不是拷贝数据。这仅仅是对内核的一个小提示:如果内核不能从pipe移动数据或者pipe的缓存不是一个整页面,仍然需要拷贝数据。Linux最初的实现有些问题,所以从2.6.21开始这个选项不起作用,后面的Linux版本应该会实现。

  • SPLICEFNONBLOCK :splice 操作不会被阻塞。然而,如果文件描述符没有被设置为不可被阻塞方式的 I/O ,那么调用 splice 有可能仍然被阻塞。

  • SPLICEFMORE: Akan ada lebih banyak data dalam panggilan splice berikutnya.

Panggilan splice menggunakan mekanisme penimbal paip yang dicadangkan oleh Linux, jadi sekurang-kurangnya satu deskriptor mestilah paip.

Teknologi salinan sifar di atas semuanya dilaksanakan dengan mengurangkan penyalinan data antara ruang pengguna dan ruang kernel, tetapi kadangkala, data mesti disalin antara ruang pengguna dan ruang kernel. Pada masa ini, kami hanya boleh bekerja pada masa penyalinan data dalam ruang pengguna dan ruang kernel. Linux biasanya menggunakan copy on write untuk mengurangkan overhead sistem Teknologi ini sering dipanggil COW.

Atas sebab ruang, artikel ini tidak memperkenalkan copy-on-write secara terperinci. Penerangan kasar ialah: Jika berbilang program mengakses sekeping data yang sama pada masa yang sama, maka setiap program mempunyai penunjuk ke sekeping data ini Dari perspektif setiap program, ia memiliki sekeping data ini secara bebas perlu Apabila kandungan data diubah suai, kandungan data akan disalin ke ruang aplikasi program sendiri Pada masa ini, data akan menjadi data peribadi program. Jika program tidak perlu mengubah suai data, maka ia tidak perlu menyalin data ke ruang aplikasinya sendiri. Ini mengurangkan penyalinan data. Kandungan yang disalin semasa menulis boleh digunakan untuk menulis artikel lain. . .

Selain itu, terdapat beberapa teknologi salinan sifar, seperti menambahkan tanda O_DIRECT pada I/O Linux tradisional untuk mendayakan I/O terus, mengelakkan caching automatik dan teknologi fbufs yang tidak matang, yang belum ada pada artikel ini. dilindungi. Semua teknologi salinan sifar hanyalah sebahagian daripada teknologi biasa Jika anda berminat, anda boleh mengkajinya sendiri Secara amnya, projek bahagian pelayan yang matang juga akan mengubah suai bahagian kernel yang berkaitan dengan I/O kadar penghantaran data mereka.

Atas ialah kandungan terperinci Analisis ringkas teknologi salinan sifar dalam Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:Linux中文社区
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan