歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux教程

Linux下的內存使用技巧點滴

任何語言編程中,最核心的問題都會包括內存的管理。我認為,從性能上來說,任何系統提供高性能的關鍵都是緩存的有效利用,在本機編程上,RAM內存則是最有效的CACHE。從代碼到程序到進程,編譯環境和運行環境在其中對內存的管理起到至關重要的作用。即使如JAVA這種平台無關的語言,它同樣通過參數受限於實際環境的限制,它在操作系統平台中的內存布局,同樣是按照內核的規矩來的。

當前Linux由於是免費的,所以大部分SERVER類程序都運行在Linux上,弄清楚Linux關於內存的管理是有實用價值的,Linux2.6內核是當前主流的Linux內核,所以下面僅談Linux2.6內核中的內存管理一些編程技巧,但是對使用跨平台語言或者中間件編程來說,還是有參考意義的。

我們在使用內存時,最關心的是:無錯、高效。無錯,是程序的健壯性要求,高效,是對程序性能的要求,這兩點都需要對內核管理內存有了解才能做到。下面重點說下為了保證無錯和高效需要了解的基本原理。

首先舉幾個例子說下我們常見的內存錯誤或者低效使用導致的問題。

1、我們在寫服務器端程序時,通常喜歡用多線程實現(在Linux上用輕量級進程實現)高效的並發,並且為了提高效率習慣每個線程都會在初始化時就預分配大塊內存,這樣可以在運行過程中長期復用。在運行過程中每個線程也會有動態堆內存的分配。因為不同的硬件配置和操作系統設置,會導致不同的線程數帶來不一樣的性能,所以這個線程數通常是可配的。那麼,如果我們的預分配內存需要大容量時,同時我們為了提高性能把線程數提高後,可能會帶來進程崩潰甚至數據變亂(32位Linux不打開PAE擴展時,支持的最大進程地址空間是3G)。

2、復雜的程序常常有幾十次的方法調用,如果不是很注重的在方法中分配了過大的棧內存,超過了系統允許的最大值(Linux默認為8M),同樣引發進程崩潰。

3、內存越界,C/C++中常見。一些攻擊程序常利用棧地址空間越界,拿到指令寄存器裡的地址,將代碼執行到任意的線性地址中,比如具備ROOT權限的父進程的代碼段。

4、調用mmap系統調用來映射內存時,進程會新分配一個線性區給這段映射。那麼這塊線性區的大小是有限制的,而且內存向磁盤中刷數據時是重量級系統調用,必須慎重設計。

了解Linux內存,我認為最快的方式是了解主流體系架構下的分頁機制以及進程的地址空間。

Linux進程的地址空間,是由許多組線性地址組成的,默認情況下,最多可以擁有65536組線性地址。Linux2.6內核通過一個雙向鏈表和紅黑樹(2.6內核前沒有,普通進程只有幾十組線性地址,這時是高效的,但線性區很多時沒有紅黑樹是很低效的)作為全部進程線性區的容器。這些線性區用來存儲代碼段,數據段,棧,堆,文件內存映射,IPC共享線性區等等。這些線性區,在進程生命周期內可能被增加、刪除、修改。我們需要清楚,代碼和運行時分配的對象存儲在哪些線性區中,以及這些線性區的限制和如何有效的使用它們。

用戶態下的進程啟動時,會復制父進程的地址空間的指針,如果進程不會修改父進程地址空間中的頁,則父進程的頁將永遠不會復制到當前進程的地址空間中。早期的Linux版本沒有這種寫時復制的機制,效率低下,目前的Linux內核都支持這種,效率有很大提高。

Copyright © Linux教程網 All Rights Reserved