Adalah penting untuk memahami butiran peruntukan memori Linux, terutamanya dalam seni bina kernel dan sistem. Mari kita mendalami peruntukan memori Linux dan fahami apa yang berlaku di sebalik tabir.
Dalam komputer, untuk proses boleh dilaksanakan, ia perlu diletakkan dalam ingatan. Untuk melakukan ini, medan mesti diperuntukkan kepada proses dalam ingatan. Peruntukan memori merupakan isu penting untuk diberi perhatian, terutamanya dalam seni bina kernel dan sistem.
Mari kita lihat lebih dekat peruntukan memori Linux dan fahami apa yang berlaku di sebalik tabir.
Kebanyakan jurutera perisian tidak mengetahui butiran proses ini. Tetapi jika anda seorang calon pengaturcara sistem, anda harus mengetahui lebih lanjut mengenainya. Apabila melihat proses peruntukan, adalah perlu untuk membuat butiran kecil tentang Linux dan perpustakaan glibc.
Apabila aplikasi memerlukan memori, mereka mesti memintanya daripada sistem pengendalian. Permintaan dari kernel ini secara semula jadi memerlukan panggilan sistem. Anda tidak boleh memperuntukkan memori sendiri dalam mod pengguna.
**malloc()** siri fungsi bertanggungjawab untuk peruntukan memori dalam bahasa C. Soalan untuk ditanya di sini ialah sama ada malloc() sebagai fungsi glibc membuat panggilan sistem terus.
Tiada panggilan sistem yang dipanggil malloc dalam kernel Linux. Walau bagaimanapun, terdapat dua panggilan sistem untuk keperluan memori aplikasi, iaitu brk dan mmap.
Memandangkan anda akan meminta memori dalam aplikasi anda melalui fungsi glibc, anda mungkin ingin mengetahui panggilan sistem yang digunakan glibc pada masa ini. Jawapannya ialah kedua-duanya.
Setiap proses mempunyai medan data yang berterusan. Melalui panggilan sistem brk, nilai gangguan program yang menentukan had medan data dinaikkan dan proses peruntukan dilakukan.
Walaupun memperuntukkan memori menggunakan kaedah ini sangat pantas, ia tidak selalu mungkin untuk mengembalikan ruang yang tidak digunakan kepada sistem.
Sebagai contoh, katakan anda memperuntukkan lima medan dengan setiap saiz medan 16KB melalui fungsi malloc() untuk panggilan sistem brk. Apabila anda melengkapkan bahagian kedua daripada medan ini, sumber yang berkaitan tidak boleh dikembalikan (diuntukkan) supaya sistem boleh menggunakannya. Kerana jika anda mengurangkan nilai alamat untuk menunjukkan tempat medan kedua bermula, dan memanggil brk, anda akan melengkapkan pembebasan medan ketiga, keempat dan kelima.
Untuk mengelakkan kehilangan ingatan dalam kes ini, pelaksanaan malloc dalam glibc memantau lokasi yang diperuntukkan dalam medan data proses dan kemudian mengembalikannya kepada sistem seperti yang ditentukan oleh fungsi free() supaya sistem boleh menggunakan ruang kosong untuk ingatan selanjutnya mengedarkan.
Dalam erti kata lain, selepas memperuntukkan 5 kawasan 16KB, jika anda menggunakan fungsi free() untuk mengembalikan kawasan kedua, dan kemudian meminta kawasan 16KB yang lain selepas beberapa ketika, bukannya mengembangkan kawasan data melalui panggilan sistem brk, The sebelumnya alamat kembali.
Namun, jika wilayah yang baru diminta lebih besar daripada 16KB, wilayah data akan diperbesarkan dengan memperuntukkan wilayah baharu melalui panggilan sistem brk kerana wilayah 2 tidak boleh digunakan. Walaupun kawasan nombor dua tidak digunakan, aplikasi tidak boleh menggunakannya kerana saiz yang berbeza. Disebabkan senario seperti ini, terdapat satu perkara yang dipanggil pemecahan dalaman, dan anda jarang boleh menggunakan sepenuhnya semua bahagian memori.
Untuk pemahaman yang lebih baik, cuba susun dan jalankan contoh aplikasi berikut:
#include #include #include int main(int argc, char* argv[]) { char *ptr[7]; int n; printf("Pid of %s: %d", argv[0], getpid()); printf("Initial program break : %p", sbrk(0)); for(n=0; nprintf("After 5 x 16kB malloc : %p", sbrk(0)); free(ptr[1]); printf("After free of second 16kB : %p", sbrk(0)); ptr[5] = malloc(16 * 1024); printf("After allocating 6th of 16kB : %p", sbrk(0)); free(ptr[5]); printf("After freeing last block : %p", sbrk(0)); ptr[6] = malloc(18 * 1024); printf("After allocating a new 18kB : %p", sbrk(0)); getchar(); return 0; }
Apabila anda menjalankan aplikasi, anda akan mendapat output yang serupa dengan yang berikut:
Pid of ./a.out: 31990 Initial program break : 0x55ebcadf4000 After 5 x 16kB malloc : 0x55ebcadf4000 After free of second 16kB : 0x55ebcadf4000 After allocating 6th of 16kB : 0x55ebcadf4000 After freeing last block : 0x55ebcadf4000 After allocating a new 18kB : 0x55ebcadf4000
Keluaran brk dengan strace adalah seperti berikut:
brk(NULL) = 0x5608595b6000 brk(0x5608595d7000) = 0x5608595d7000
Seperti yang anda lihat, 0x21000 telah ditambahkan pada alamat akhir medan data. Anda boleh memahami ini dari nilai 0x5608595d7000. Jadi lebih kurang 0x21000 atau 132KB memori diperuntukkan.
Terdapat dua perkara yang perlu dipertimbangkan di sini. Yang pertama adalah untuk memperuntukkan lebih daripada yang dinyatakan dalam kod contoh. Satu lagi ialah baris kod yang menyebabkan panggilan brk yang menyediakan peruntukan.
Apabila anda menjalankan aplikasi sampel di atas satu demi satu, anda akan melihat nilai alamat yang berbeza setiap kali. Mengubah ruang alamat secara rawak dengan cara ini sangat merumitkan kerja serangan keselamatan dan meningkatkan keselamatan perisian.
但是,在 32 位架构中,通常使用 8 位来随机化地址空间。增加位数将不合适,因为剩余位上的可寻址区域将非常低。此外,仅使用 8 位组合不会使攻击者的事情变得足够困难。
另一方面,在 64 位体系结构中,由于可以为 ASLR 操作分配的位太多,因此提供了更大的随机性,并且提高了安全程度。
Linux 内核还支持基于 Android 的设备,并且 ASLR 功能在 Android 4.0.3 及更高版本上完全激活。即使仅出于这个原因,也可以说 64 位智能手机比 32 位版本具有显着的安全优势。
通过使用以下命令暂时禁用 ASLR 功能,之前的测试应用程序每次运行时都会返回相同的地址值:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
要将其恢复到以前的状态,在同一个文件中写入 2 而不是 0 就足够了。
mmap 是 Linux 上用于内存分配的第二个系统调用。通过 mmap 调用,内存中任何区域的空闲空间都映射到调用进程的地址空间。
在以这种方式完成的内存分配中,当您想使用前面 brk 示例中的 free() 函数返回第二个 16KB 分区时,没有机制可以阻止此操作。从进程的地址空间中删除相关的内存段。它被标记为不再使用并返回系统。
因为与使用 brk 相比,使用 mmap 的内存分配非常慢,所以需要分配 brk。
使用 mmap,内存的任何空闲区域都映射到进程的地址空间,因此在该进程完成之前,已分配空间的内容被重置。如果没有以这种方式进行重置,则属于先前使用相关内存区域的进程的数据也可以被下一个不相关的进程访问。这样就不可能谈论系统中的安全性。
内存分配非常重要,尤其是在优化和安全问题上。如上面的示例所示,不完全理解此问题可能意味着破坏系统的安全性。
甚至许多编程语言中存在的类似于 push 和 pop 的概念也是基于内存分配操作的。能够很好地使用和掌握系统内存对于嵌入式系统编程和开发安全和优化的系统架构都是至关重要的。
如果您还想涉足 Linux 内核开发,请考虑首先掌握 C 编程语言。
综上所述,Linux 中的内存分配是一个需要注意和理解的重要问题,特别是对于程序员、内核开发人员和系统架构师而言。熟练掌握内存分配可以提高软件性能和安全性,并在嵌入式系统编程和系统架构方面提供更好的支持。同时,C 编程语言的掌握也是涉足 Linux 内核开发的关键。
Atas ialah kandungan terperinci Cara peruntukan memori berfungsi pada Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!