日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 跟踪内存,用strace跟踪malloc内存分配

發布時間:2023/12/2 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 跟踪内存,用strace跟踪malloc内存分配 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

strace介紹

strace是一個非常有用的命令,它用于記錄和跟蹤程序運行期間收到的信號和調用的系統調用。

strace的簡單使用

ubuntu64:~$ strace cat /dev/null

execve("/bin/cat", ["cat", "/dev/null"], [/* 32 vars */]) = 0

brk(NULL) = 0x112e000

access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)

. . .

read(3, "", 131072) = 0

munmap(0x7f19a65be000, 139264) = 0

close(3) = 0

close(1) = 0

close(2) = 0

exit_group(0) = ?

+++ exited with 0 +++

每一行表示一個系統調用, 左邊為系統調用的名稱和參數, 右邊為系統調用返回的結果。

參數

-c 統計每一系統調用的所執行的時間,次數和出錯的次數等.

-d 輸出strace關于標準錯誤的調試信息.

-f 跟蹤由fork調用所產生的子進程.

-ff 如果提供-o filename,則所有進程的跟蹤結果輸出到相應的filename.pid中,pid是各進程的進程號.

-F 嘗試跟蹤vfork調用.在-f時,vfork不被跟蹤.

-h 輸出簡要的幫助信息.

-i 輸出系統調用的入口指針.

-q 禁止輸出關于脫離的消息.

-r 打印出相對時間關于,,每一個系統調用.

-t 在輸出中的每一行前加上時間信息.

-tt 在輸出中的每一行前加上時間信息,微秒級.

-ttt 微秒級輸出,以秒了表示時間.

-T 顯示每一調用所耗的時間.

-v 輸出所有的系統調用.一些調用關于環境變量,狀態,輸入輸出等調用由于使用頻繁,默認不輸出.

-V 輸出strace的版本信息.

-x 以十六進制形式輸出非標準字符串

-xx 所有字符串以十六進制形式輸出.

-a column

設置返回值的輸出位置.默認 為40.

-e expr

指定一個表達式,用來控制如何跟蹤.格式如下:

[qualifier=][!]value1[,value2]...

qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用來限定的符號或數字.默認的 qualifier是 trace.感嘆號是否定符號.例如:

-eopen等價于 -e trace=open,表示只跟蹤open調用.而-etrace!=open表示跟蹤除了open以外的其他調用.有兩個特殊的符號 all 和 none.

注意有些shell使用!來執行歷史記錄里的命令,所以要使用\\.

-e trace=set

只跟蹤指定的系統 調用.例如:-e trace=open,close,rean,write表示只跟蹤這四個系統調用.默認的為set=all.

-e trace=file

只跟蹤有關文件操作的系統調用.

-e trace=process

只跟蹤有關進程控制的系統調用.

-e trace=network

跟蹤與網絡有關的所有系統調用.

-e strace=signal

跟蹤所有與系統信號有關的 系統調用

-e trace=ipc

跟蹤所有與進程通訊有關的系統調用

-e abbrev=set

設定 strace輸出的系統調用的結果集.-v 等與 abbrev=none.默認為abbrev=all.

-e raw=set

將指 定的系統調用的參數以十六進制顯示.

-e signal=set

指定跟蹤的系統信號.默認為all.如 signal=!SIGIO(或者signal=!io),表示不跟蹤SIGIO信號.

-e read=set

輸出從指定文件中讀出 的數據.例如:

-e read=3,5

-e write=set

輸出寫入到指定文件中的數據.

-o filename

將strace的輸出寫入文件filename

-p pid

跟蹤指定的進程pid.

-s strsize

指定輸出的字符串的最大長度.默認為32.文件名一直全部輸出.

-u username

以username 的UID和GID執行被跟蹤的命令

用strace查看malloc內存分配

我在博客 c語言內存無法釋放 中曾經提到過 :malloc采用了兩中不同的方式來處理內存申請。

1. 若分配內存小于 128k ,調用 sbrk() ,將堆頂指針向高地址移動,獲得新的虛存空間。

2. 若分配內存大于 128k ,調用 mmap() ,在文件映射區域中分配匿名虛存空間。

現在我們就strace 跟蹤在那篇博客中的 Case #3, 在這之前我先修改 Case #3的代碼,添加代碼(完整的代碼在博客尾部):

int *list;

list = malloc(1024*1024);

free(list);

這段代碼用于查看當申請的內存大于128k時, malloc的處理方法。

strace 跟蹤結果如下:

ubuntu64:~$ strace ./test_mem

execve("./test_mem", ["./test_mem"], [/* 32 vars */]) = 0

. . .

brk(0xd0e000) = 0xd0e000 //通過將堆頂向高地址移動到0xd0e000為進程分配內存

write(1, "before malloc, the top of heap i"..., 43before malloc, the top of heap is 0xced000) = 43

write(1, "address of a is 0xced420 top of "..., 62address of a is 0xced420 top of heap after malloc is 0xd0e000) = 62

brk(0xd40000) = 0xd40000 // 同樣通過移動堆頂分配內存

write(1, "address of a is 0xd06430 top of "..., 62address of a is 0xd06430 top of heap after malloc is 0xd40000) = 62

write(1, "address of a is 0xd1f440 top of "..., 62address of a is 0xd1f440 top of heap after malloc is 0xd40000) = 62

brk(0xd72000) = 0xd72000 // 同樣通過移動堆頂分配內存

write(1, "address of a is 0xd38450 top of "..., 62address of a is 0xd38450 top of heap after malloc is 0xd72000) = 62

write(1, "address of a is 0xd51460 top of "..., 62address of a is 0xd51460 top of heap after malloc is 0xd72000) = 62

brk(0xda4000) = 0xda4000 // 同樣通過移動堆頂分配內存

write(1, "address of a is 0xd6a470 top of "..., 62address of a is 0xd6a470 top of heap after malloc is 0xda4000) = 62

write(1, "address of a is 0xd83480 top of "..., 62address of a is 0xd83480 top of heap after malloc is 0xda4000) = 62

brk(0xdd6000) = 0xdd6000 // 同樣通過移動堆頂分配內存

write(1, "address of a is 0xd9c490 top of "..., 62address of a is 0xd9c490 top of heap after malloc is 0xdd6000) = 62

write(1, "address of a is 0xdb54a0 top of "..., 62address of a is 0xdb54a0 top of heap after malloc is 0xdd6000) = 62

brk(0xe08000) = 0xe08000 // 同樣通過移動堆頂分配內存

write(1, "address of a is 0xdce4b0 top of "..., 62address of a is 0xdce4b0 top of heap after malloc is 0xe08000) = 62

//用mmap在文件映射區為進程分配內存

mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0cd5140000

write(1, "malloc end\n", 11malloc end) = 11

write(1, "before free, the top of heap is "..., 41before free, the top of heap is 0xe08000) = 41

brk(0xd0e000) = 0xd0e000 //釋放通過brk移動堆頂分配的內存

write(1, "after free, the top of heap is "..., 41after free, the top of heap is 0xd0e000) = 41

munmap(0x7f0cd5140000, 1052672) = 0 //釋放mmap分配的內存

exit_group(0) = ?

+++ exited with 0 +++

結果中省略了程序加載部分內容,從輸出結果可以看出:

1. 在為鏈表申請節點時, 因為每個節點size小于128k(128k是可以調整的),?malloc直接通過brk()函數在堆上分配內存。

2. 為list分配內存時,因為它需要1M內存, 所以malloc通過mmap()函數在在文件映射區域分配內存。

附錄

1. 32位系統中進程虛擬空間布局

2. Case #3代碼

#include

#include

#include

#include

typedef struct node

{

char a[1024*100];

struct node *next;

}node;

int main()

{

node *node_first = NULL, *node_now;

node *a;

int i;

char s_cmd[100];

sprintf(s_cmd, "pmap -d %lu | grep mapped", getpid());

printf("before malloc, the top of heap is 0x%lx\n", sbrk(0));

for(i=0;i<10;i++){

a=(node *)malloc(sizeof(node));

a->next=NULL;

if(node_first==NULL) node_first=a;

else node_now->next=a;

node_now=a;

printf("address of a is 0x%lx ", a);

printf("top of heap after malloc is 0x%lx\n", sbrk(0));

}

int *list;

list = malloc(1024*1024);

printf("malloc end\n");

printf("before free, the top of heap is 0x%lx\n", sbrk(0));

while(node_first!=NULL)

{

node_now=node_first->next;

free(node_first);

node_first=node_now;

}

printf("after free, the top of heap is 0x%lx\n", sbrk(0));

free(list);

return 0;

}

參考

總結

以上是生活随笔為你收集整理的linux 跟踪内存,用strace跟踪malloc内存分配的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。