可以通過調用系統命令free。
獲取free命令的輸出值。
比如 system("free > tmp.txt");
然後fopen打開tmp.txt 獲取輸出,然後處理回free的結果答得到未使用內存大小。
也可以直接打開/proc/meminfo
第二行MemFree後面的數字就是free內存大小。
第二種更常用一些。
❷ 在linux寫的C語言程序,使用top查看內存的使用率不斷的增加,直到程序死機
根據你的描述,我判斷很有可能是你的程序中有死循環造成的,是不是內回存泄露還需要進一步判答斷。 linux的內存管理和windows不同,linux的內存分配原則是優先使用物理內存,只有在物理內存滿足不了需要時,才進行物理內存和虛擬內存的交換;windows則是根據一定的比例進行虛擬內存和物理內存的交換;因此,linux系統的物理內存使用量是不斷增減,指導95%以上才會穩定,其實是linux為提高系統性內進行的物理內存使用優化,這樣能夠提高物理內存使用率,提高性能。 如果你的進程關閉,linux系統也不會馬上釋放內存,等到其他進程請求內存而且物理內存不足時才去釋放。 這里linux的內存管理機制。
❸ Linux下使用能否使用C共享內存存放指針
共享內存指在多處理器的計算機系統中,可以被不同中央處理器(CPU)訪問的大容量內存。由於多個CPU需要快速訪問存儲器,這樣就要對存儲器進行緩存(Cache)。任何一個緩存的數據被更新後,由於其他處理器也可能要存取,共享內存就需要立即更新,否則不同的處理器可能用到不同的數據。共享內存 (shared memory)是 Unix下的多進程之間的通信方法 ,這種方法通常用於一個程序的多進程間通信,實際上多個程序間也可以通過共享內存來傳遞信息。
共享內存的創建
共享內存是存在於內核級別的一種資源,在shell中可以使用ipcs命令來查看當前系統IPC中的狀態,在文件系統/proc目錄下有對其描述的相應文件。函數shmget可以創建或打開一塊共享內存區。函數原型如下: #include <sys/shm.h> int shmget( key_t key, size_t size, int flag ); 函數中參數key用來變換成一個標識符,而且每一個IPC對象與一個key相對應。當新建一個共享內存段時,size參數為要請求的內存長度(以位元組為單位)。 注意:內核是以頁為單位分配內存,當size參數的值不是系統內存頁長的整數倍時,系統會分配給進程最小的可以滿足size長的頁數,但是最後一頁的剩餘部分內存是不可用的。 當打開一個內存段時,參數size的值為0。參數flag中的相應許可權位初始化ipc_perm結構體中的mode域。同時參數flag是函數行為參數,它指定一些當函數遇到阻塞或其他情況時應做出的反應。shmid_ds結構初始化如表14-4所示。
編輯本段初始化
shmid_ds結構數據 初 值 shmid_ds結構數據 初 值
shm_lpid 0 shm_dtime 0
shm_nattach 0 shm_ctime 系統當前值
shm_atime 0 shm_segsz 參數 size
下面實例演示了使用shmget函數創建一塊共享內存。程序中在調用shmget函數時指定key參數值為IPC_PRIVATE,這個參數的意義是創建一個新的共享內存區,當創建成功後使用shell命令ipcs來顯示目前系統下共享內存的狀態。命令參數-m為只顯示共享內存的狀態。 (1)在vi編輯器中編輯該程序如下: 程序清單14-8 create_shm.c 使用shmget函數創建共享內存 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #define BUFSZ 4096 int main ( void ) printf ( "successfully created segment : %d \n", shm_id ) ; system( "ipcs -m"); /*調用ipcs命令查看IPC*/ exit( 0 ); } (2)在shell中編譯該程序如下: $gcc create_shm.c–o create_shm (3)在shell中運行該程序如下: $./ create_shm successfully created segment : 2752516 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 0 上述程序中使用shmget函數來創建一段共享內存,並在結束前調用了系統shell命令ipcs –m來查看當前系統IPC狀態。
編輯本段共享內存的操作
由於共享內存這一特殊的資源類型,使它不同於普通的文件,因此,系統需要為其提供專有的操作函數,而這無疑增加了程序員開發的難度(需要記憶額外的專有函數)。使用函數shmctl可以對共享內存段進行多種操作,其函數原型如下: #include <sys/shm.h> int shmctl( int shm_id, int cmd, struct shmid_ds *buf ); 函數中參數shm_id為所要操作的共享內存段的標識符,struct shmid_ds型指針參數buf的作用與參數cmd的值相關,參數cmd指明了所要進行的操作,其解釋如表14-5所示。
編輯本段cmd參數詳解
cmd的值 意 義
IPC_STAT 取shm_id所指向內存共享段的shmid_ds結構,對參數buf指向的結構賦值
IPC_SET 使用buf指向的結構對sh_mid段的相關結構賦值,只對以下幾個域有作用,shm_perm. uid shm_perm.gid以及shm_perm.mode 注意此命令只有具備以下條件的進程才可以請求: 1.進程的用戶ID等於shm_perm.cuid或者等於shm_perm.uid 2.超級用戶特權進程
IPC_RMID 刪除shm_id所指向的共享內存段,只有當shmid_ds結構的shm_nattch域為零時,才會真正執行刪除命令,否則不會刪除該段 注意此命令的請求規則與IPC_SET命令相同
SHM_LOCK 鎖定共享內存段在內存,此命令只能由超級用戶請求
SHM_UNLOCK 對共享內存段解鎖,此命令只能由超級用戶請求
使用函數shmat將一個存在的共享內存段連接到本進程空間,其函數原型如下: #include <sys/shm.h> void *shmat( int shm_id, const void *addr, int flag ); 函數中參數shm_id指定要引入的共享內存,參數addr與flag組合說明要引入的地址值,通常只有2種用法,addr為0,表明讓內核來決定第1個可以引入的位置。addr非零,並且flag中指定SHM_RND,則此段引入到addr所指向的位置(此操作不推薦使用,因為不會只對一種硬體上運行應用程序,為了程序的通用性推薦使用第1種方法),在flag參數中可以指定要引入的方式(讀寫方式指定)。 %說明:函數成功執行返回值為實際引入的地址,失敗返回–1。shmat函數成功執行會將shm_id段的shmid_ds結構的shm_nattch計數器的值加1。 當對共享內存段操作結束時,應調用shmdt函數,作用是將指定的共享內存段從當前進程空間中脫離出去。函數原型如下: #include <sys/shm.h> int shmdt( void *addr); 參數addr是調用shmat函數的返回值,函數執行成功返回0,並將該共享內存的shmid_ds結構的shm_nattch計數器減1,失敗返回–1。 下面實例演示了操作共享內存段的流程。程序的開始部分先檢測用戶是否有輸入,如出錯則列印該命令的使用幫助。接下來從命令行讀取將要引入的共享內存ID,使用shmat函數引入該共享內存,並在分離該內存之前睡眠3秒以方便查看系統IPC狀態。 (1)在vi編輯器中編輯該程序如下: 程序清單14-9 opr_shm.c 操作共享內存段 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> int main ( int argc, char *argv[] ) shm_id = atoi(argv[1]); /*得到要引入的共享內存段*/ /*引入共享內存段,由內核選擇要引入的位置*/ if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ) printf ( " segment attached at %p\n", shm_buf ); /*輸出導入的位置*/ system("ipcs -m"); sleep(3); /* 休眠 */ if ( (shmdt(shm_buf)) < 0 ) printf ( "segment detached \n" ); system ( "ipcs -m " ); /*再次查看系統IPC狀態*/ exit ( 0 ); } (2)在shell中編譯該程序如下: $gcc opr_shm.c–o opr_shm (3)在shell中運行該程序如下: $./ opr_shm 2752516 segment attached at 0xb7f29000 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 1 segment detached ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 0 上述程序中從命令行中讀取所要引入的共享內存ID,並使用shmat函數引入該內存到當前的進程空間中。注意在使用shmat函數時,將參數addr的值設為0,所表達的意義是由內核來決定該共享內存在當前進程中的位置。由於在編程的過程中,很少會針對某一個特定的硬體或系統編程,所以由內核決定引入位置也就是shmat推薦的使用方式。在導入後使用shell命令ipcs –m來顯示當前的系統IPC的狀態,可以看出輸出信息中nattch欄位為該共享內存時的引用值,最後使用shmdt函數分離該共享內存並列印系統IPC的狀態。
編輯本段共享內存使用注意事項
共享內存相比其他幾種方式有著更方便的數據控制能力,數據在讀寫過程中會更透明。當成功導入一塊共享內存後,它只是相當於一個字元串指針來指向一塊內存,在當前進程下用戶可以隨意的訪問。缺點是,數據寫入進程或數據讀出進程中,需要附加的數據結構控制,共享內存通信數據結構示意如圖14-9所示。
編輯本段結構示意
%說明:圖中兩個進程同時遵循一定的規則來讀寫該內存。同時,在多進程同步或互斥上也需要附加的代碼來輔助共享內存機制。 在共享內存段中都是以字元串的默認結束符為一條信息的結尾。每個進程在讀寫時都遵守這個規則,就不會破壞數據的完整性。
另外,站長團上有產品團購,便宜有保證
❹ linux c內存溢出的core mp bug怎麼跟
淺析Linux下core文件
當我們的程序崩潰時,內核有可能把該程序當前內存映射到core文件里,方便程序員找到程序出現問題的地方。最常出 現的,幾乎所有C程序員都出現過的錯誤就是「段錯誤」了。也是最難查出問題原因的一個錯誤。下面我們就針對「段錯誤」來分析core文件的產生、以及我們 如何利用core文件找到出現崩潰的地方。
何謂core文件
當一個程序崩潰時,在進程當前工作目錄的core文件中復制了該進程的存儲圖像。core文件僅僅是一個內存映象(同時加上調試信息),主要是用來調試的。
當程序接收到以下UNIX信號會產生core文件:
名字
說明
ANSI C POSIX.1
SVR4 4.3+BSD
預設動作
SIGABRT
異常終止(abort)
. .
. .
終止w/core
SIGBUS
硬體故障
.
. .
終止w/core
SIGEMT
硬體故障
. .
終止w/core
SIGFPE
算術異常
. .
. .
終止w/core
SIGILL
非法硬體指令
. .
. .
終止w/core
SIGIOT
硬體故障
. .
終止w/core
SIGQUIT
終端退出符
.
. .
終止w/core
SIGSEGV
無效存儲訪問
. .
. .
終止w/core
SIGSYS
無效系統調用
. .
終止w/core
SIGTRAP
硬體故障
. .
終止w/core
SIGXCPU
超過CPU限制(setrlimit)
. .
終止w/core
SIGXFSZ
超過文件長度限制(setrlimit)
. .
終止w/core
在系統默認動作列,「終止w/core」表示在進程當前工作目錄的core文件中復制了該進程的存儲圖像(該文件名為core,由此可以看出這種功能很久之前就是UNIX功能的一部分)。大多數UNIX調試程序都使用core文件以檢查進程在終止時的狀態。
core文件的產生不是POSIX.1所屬部分,而是很多UNIX版本的實現特徵。UNIX第6版沒有檢查條件 (a)和(b),並且其源代碼中包含如下說明:「如果你正在找尋保護信號,那麼當設置-用戶-ID命令執行時,將可能產生大量的這種信號」。4.3 + BSD產生名為core.prog的文件,其中prog是被執行的程序名的前1 6個字元。它對core文件給予了某種標識,所以是一種改進特徵。
表中「硬體故障」對應於實現定義的硬體故障。這些名字中有很多取自UNIX早先在DP-11上的實現。請查看你所使用的系統的手冊,以確切地確定這些信號對應於哪些錯誤類型。
下面比較詳細地說明這些信號。
• SIGABRT 調用abort函數時產生此信號。進程異常終止。
• SIGBUS 指示一個實現定義的硬體故障。
• SIGEMT 指示一個實現定義的硬體故障。
EMT這一名字來自PDP-11的emulator trap 指令。
• SIGFPE 此信號表示一個算術運算異常,例如除以0,浮點溢出等。
• SIGILL 此信號指示進程已執行一條非法硬體指令。
4.3BSD由abort函數產生此信號。SIGABRT現在被用於此。
• SIGIOT 這指示一個實現定義的硬體故障。
IOT這個名字來自於PDP-11對於輸入/輸出TRAP(input/output TRAP)指令的縮寫。系統V的早期版本,由abort函數產生此信號。SIGABRT現在被用於此。
• SIGQUIT 當用戶在終端上按退出鍵(一般採用Ctrl-\)時,產生此信號,並送至前台進
程組中的所有進程。此信號不僅終止前台進程組(如SIGINT所做的那樣),同時產生一個core文件。
• SIGSEGV 指示進程進行了一次無效的存儲訪問。
名字SEGV表示「段違例(segmentation violation)」。
• SIGSYS 指示一個無效的系統調用。由於某種未知原因,進程執行了一條系統調用指令,
但其指示系統調用類型的參數卻是無效的。
• SIGTRAP 指示一個實現定義的硬體故障。
此信號名來自於PDP-11的TRAP指令。
• SIGXCPU SVR4和4.3+BSD支持資源限制的概念。如果進程超過了其軟C P U時間限制,則產生此信號。
• SIGXFSZ 如果進程超過了其軟文件長度限制,則SVR4和4.3+BSD產生此信號。
摘自《UNIX環境高級編程》第10章 信號。
使用core文件調試程序
看下面的例子:
/*core_mp_test.c*/
#include
const char *str = "test";
void core_test(){
str[1] = 'T';
}
int main(){
core_test();
return 0;
}
編譯:
gcc –g core_mp_test.c -o core_mp_test
如果需要調試程序的話,使用gcc編譯時加上-g選項,這樣調試core文件的時候比較容易找到錯誤的地方。
執行:
./core_mp_test
段錯誤
運行core_mp_test程序出現了「段錯誤」,但沒有產生core文件。這是因為系統默認core文件的大小為0,所以沒有創建。可以用ulimit命令查看和修改core文件的大小。
ulimit -c 0
ulimit -c 1000
ulimit -c 1000
-c 指定修改core文件的大小,1000指定了core文件大小。也可以對core文件的大小不做限制,如:
ulimit -c unlimited
ulimit -c unlimited
如果想讓修改永久生效,則需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。
再次執行:
./core_mp_test
段錯誤 (core mped)
ls core.*
core.6133
可以看到已經創建了一個core.6133的文件.6133是core_mp_test程序運行的進程ID。
調式core文件
core文件是個二進制文件,需要用相應的工具來分析程序崩潰時的內存映像。
file core.6133
core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'core_mp_test'
在Linux下可以用GDB來調試core文件。
gdb core_mp_test core.6133
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show ing" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
Core was generated by `./core_mp_test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x080482fd in core_test () at core_mp_test.c:7
7 str[1] = 'T';
(gdb) where
#0 0x080482fd in core_test () at core_mp_test.c:7
#1 0x08048317 in main () at core_mp_test.c:12
#2 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6
GDB中鍵入where,就會看到程序崩潰時堆棧信息(當前函數之前的所有已調用函數的列表(包括當前函數),gdb只顯示最近幾個),我們很容易找到我們的程序在最後崩潰的時候調用了core_mp_test.c 第7行的代碼,導致程序崩潰。注意:在編譯程序的時候要加入選項-g。您也可以試試其他命令,如fram、list等。更詳細的用法,請查閱GDB文檔。
core文件創建在什麼位置
在進程當前工作目錄的下創建。通常與程序在相同的路徑下。但如果程序中調用了chdir函數,則有可能改變了當前工 作目錄。這時core文件創建在chdir指定的路徑下。有好多程序崩潰了,我們卻找不到core文件放在什麼位置。和chdir函數就有關系。當然程序 崩潰了不一定都產生core文件。
什麼時候不產生core文件
在下列條件下不產生core文件:
( a )進程是設置-用戶-ID,而且當前用戶並非程序文件的所有者;
( b )進程是設置-組-ID,而且當前用戶並非該程序文件的組所有者;
( c )用戶沒有寫當前工作目錄的許可權;
( d )文件太大。core文件的許可權(假定該文件在此之前並不存在)通常是用戶讀/寫,組讀和其他讀。
利用GDB調試core文件,當遇到程序崩潰時我們不再束手無策。
❺ 怎麼減少 linux c程序內存佔用
1. 在linux下,查看一個運行中的程序, 佔用了多少內存, 一般的命令有
(1). ps aux:
其中 VSZ(或VSS)列 表示,程序佔用了多少虛擬內存。
RSS列 表示, 程序佔用了多少物理內存。
虛擬內存可以不用考慮,它並不佔用實際物理內存。
(2). top 命令也可以
其中 VIRT(或VSS)列 表示,程序佔用了多少虛擬內存。 同 ps aux 中的 VSZ列
RES列 表示, 程序佔用了多少物理內存。同 ps aux 中的RSS列
2.在linux下, 查看當前系統佔用了多少內存, 一般的命令是 free
其中, free就是系統還有多少內存可以使用。
但由於 linux 系統對內存使用有一個原則, 就是, 內存是寶貴的, 能使用多少就使用多少。 所以, linux會把已經調用過的包緩存起來,放在內存里。
這樣,實際上,可以使用的內存,就可以理解為, free+buffers+cached
❻ Linux用戶空間內存動態申請
在用戶空間中動態申請內存的函數為malloc (),這個函數在各種操作系統上的使用都是一致的,malloc ()申請的內存的釋放函數為free()。對於Linux而言,C庫的malloc ()函數一般通過brk ()和mmap ()兩個系統調用從內核申請內存。
由於用戶空間C庫的malloc演算法實際上具備一個二次管理能力,所以並不是每次申請和釋放內存都一定伴隨著對內核的系統調用。比如,代碼清單11.2的應用程序可以從內核拿到內存後,立即調用free(),由於free()之前調用了mallopt(M_TRIM_THRESHOLD,一1)和mallopt (M_MMAP_MAX,0),這個free ()並不會把內存還給內核,而只是還給了C庫的分配演算法(內存仍然屬於這個進程),因此之後所有的動態內存申請和釋放都在用戶態下進行。另外,Linux內核總是採用按需調頁(Demand Paging),因此當malloc ()返回的時候,雖然是成功返回,但是內核並沒有真正給這個進程內存,這個時候如果去讀申請的內存,內容全部是0,這個頁面的映射是只讀的。只有當寫到某個頁面的時候,內核才在頁錯誤後,真正把這個頁面給這個進程。
在Linux內核空間中申請內存涉及的函數主要包括kmalloc( ) 、get free pages ( )和vmalloc ()
等。kmalloc ()和_get_free pages ()(及其類似函數)申請的內存位於DMA和常規區域的映射區,而且在物理上也是連續的,它們與真實的物理地址只有一個固定的偏移,因此存在較簡單的轉換關系。而vmalloc()在虛擬內存空間給出一塊連續的內存區,實質上,這片連續的虛擬內存在物理內存中並不一定連續,而vmalloc ()申請的虛擬內存和物理內存之間也沒有簡單的換算關系。