linux中
程序結構和進程結構
file 可執行文件
[root@centos1 c]# file getopt_long getopt_long: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
size 可執行程序
查看程序組成部分
[root@centos1 c]# size getopt_long text data bss dec hex filename 2037 508 56 2601 a29 getopt_long
代碼段:
text 主要存放 指令,操作以及只讀的(常量)數據(比如字符串常量)
通常是指用來存放程序執行代碼的一塊內存區域。
這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程序。
在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等
數據段:
data 全局或者靜態的已經初始化的變量 數據段屬於靜態內存分配
bss段:(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。
BSS 是英文Block Started by Symbol 的簡稱。BSS 段屬於靜態內存分配。
全局或者靜態的未初始化的變量
#include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[]){ printf("hello c\n"); return 0; } [root@centos1 c]# size mem text data bss dec hex filename 1151 492 16 1659 67b mem int i=10; int main(int argc,char *argv[]){ printf("hello c\n"); return 0; } [root@centos1 c]# size mem text data bss dec hex filename 1151 496 16 1663 67f mem data端增加了4 #include <stdio.h> #include <stdlib.h> int i=10; static int j; int main(int argc,char *argv[]){ printf("hello c\n"); return 0; } [root@centos1 c]# size mem text data bss dec hex filename 1151 496 24 1671 687 mem bss段增加到24
進程:linux操作系統最小的資源管理單元
一個進程時執行的程序段
程序在執行時,會動態的申請空間,執行子函數
Linux對一個進程管理采用以下方式
內核空間:
PCB(進程控制塊) 結構體 task struct,負責管理進程的所有資源
成員 mm_struct 指向這個進程相關的內存資源
mm_struct指向一個結構體
棧
堆
BSS段
數據段
代碼段
執行程序時,系統首先在內核空間中創建一個進程,為這個進程申請PCB(進程控制塊 task_struct)
用於管理整個進程的所有資源,其中mm_struct成員用來管理與當先進程相關的所有內存資源
1.代碼段,數據段,bss段,直接從磁盤拷貝到當前的內存空間,大小相等
2.動態空間
堆,棧空間,mmap段(映射其它庫相關的信息)
#include <stdio.h> #include <stdlib.h> int i=10; static int j; int main(int argc,char *argv[]){ printf("hello c\n"); while(1); return 0; } [root@centos1 ~]# ps -ef|grep mem root 902 2 0 May20 ? 00:00:02 [vmmemctl] root 28246 27937 98 22:20 pts/0 00:00:29 ./mem root 28271 28249 0 22:21 pts/1 00:00:00 grep mem
一個進程的內存虛擬地址信息列表 [root@centos1 ~]# cat /proc/28246/maps 00400000-00401000 r-xp 00000000 00:12 33 /mnt/hgfs/www/web/thread/process_thread_study/c/mem 00600000-00601000 rw-p 00000000 00:12 33 /mnt/hgfs/www/web/thread/process_thread_study/c/mem 3339e00000-3339e20000 r-xp 00000000 fd:00 2490830 /lib64/ld-2.12.so 333a020000-333a021000 r--p 00020000 fd:00 2490830 /lib64/ld-2.12.so 333a021000-333a022000 rw-p 00021000 fd:00 2490830 /lib64/ld-2.12.so 333a022000-333a023000 rw-p 00000000 00:00 0 333a200000-333a38a000 r-xp 00000000 fd:00 2490831 /lib64/libc-2.12.so 333a38a000-333a58a000 ---p 0018a000 fd:00 2490831 /lib64/libc-2.12.so 333a58a000-333a58e000 r--p 0018a000 fd:00 2490831 /lib64/libc-2.12.so 333a58e000-333a590000 rw-p 0018e000 fd:00 2490831 /lib64/libc-2.12.so 333a590000-333a594000 rw-p 00000000 00:00 0 7f605b8ff000-7f605b902000 rw-p 00000000 00:00 0 7f605b910000-7f605b912000 rw-p 00000000 00:00 0 7ffce591e000-7ffce5933000 rw-p 00000000 00:00 0 [stack] 7ffce59ac000-7ffce59ad000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] [root@centos1 ~]# pmap 28246 28246: ./mem 0000000000400000 4K r-x-- /mnt/hgfs/www/web/thread/process_thread_study/c/mem 0000000000600000 4K rw--- /mnt/hgfs/www/web/thread/process_thread_study/c/mem 0000003339e00000 128K r-x-- /lib64/ld-2.12.so 000000333a020000 4K r---- /lib64/ld-2.12.so 000000333a021000 4K rw--- /lib64/ld-2.12.so 000000333a022000 4K rw--- [ anon ] 000000333a200000 1576K r-x-- /lib64/libc-2.12.so 000000333a38a000 2048K ----- /lib64/libc-2.12.so 000000333a58a000 16K r---- /lib64/libc-2.12.so 000000333a58e000 8K rw--- /lib64/libc-2.12.so 000000333a590000 16K rw--- [ anon ] 00007f605b8ff000 12K rw--- [ anon ] 00007f605b910000 8K rw--- [ anon ] 00007ffce591e000 84K rw--- [ stack ] 00007ffce59ac000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 3924K 內存映射 寫時申請 32G平台,一個進程擁有自己的4G虛擬地址空間與其它進程無關 進程和進程之間是相互獨立的
進程地址空間的申請
1.代碼段,數據段,BSS段,這三個部分直接從磁盤拷貝到內存,
起始地址在當前32位平台linux下為0x08048000地址
2.堆段,動態變化 malloc系列。
3.mmap映射文件(普通文件,也可以是其它類型的文件) 庫,用戶自己調用mmap函數
4.棧段
5.高地址1G空間供內核映射處理,用戶空間不能直接處理
對和棧的其實地址默認是隨機產生的,其目的是避免安全漏洞,但是可以指定堆中申請的起始地址
brk(系統調用)/sbrk (庫函數)
#include <unistd.h>
int brk(void *addr); //指定下次申請堆空間的起始地址為addr
void *sbrk(intptr_t increment);//在當前的地址位置后移increment字節,如果為0返回當前值
#include <stdio.h> #include <stdlib.h> int i=10; int main(int argc,char *argv[]){ brk(0xc76000); printf("sbrk return:%p\n",sbrk(0)); char *ptr=malloc(32); printf("new malloc:%p\n",ptr); return 0; }
[root@centos1 c]# ./brk sbrk return:0xc76000 new malloc:0xc76010
布局