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
.