Unix/Linux-03

回顾

1. 错误处理

C程序员一般对错误有4种处理方式 (void、-1、指针+ -1、NULL)

C官方 提供了errno记录错误的编号,
用perror显示错误信息
strerror(errno)
printf("%m")

2. 环境表

int main(int argc, char** argv, char** env){}
extern char** environ;
environ == env
getenv/setenv/putenv/unsetenv/clearenv

3. 内存管理(偏理论)

Unix的内存管理 使用虚拟内存地址空间,程序员 接触的都是虚拟内存地址。虚拟内存地址必须 映射到物理内存才能使用。内存管理最小单位 是内存页,4096 字节(4K)。
windows xp 一簇(一内存页)

今天 : 内存管理

liujing@ubuntu:/$ cd proc
liujing@ubuntu:/proc$ ls
1     1703  194   2093  234    30     53698  99           modules
10    1708  195   21    235    31     55     acpi         mounts
100   1714  196   210   236    310    55110  asound       mpt
1000  1719  1968  2103  2364   311    55161  buddyinfo    mtrr
101   1722  1969  2105  237    32     55192  bus          net
...
...

其中数字代表活跃的正在运行的进程ID

运行a.out(其中加入while(1),不让其运行结束)
ps 只能看当前终端的
pa -aux
找到a.out进程

liujing   56455  0.0  0.0   4352   636 pts/8    S+   09:28   0:00 ./a.out

liujing@ubuntu:/proc$ cd 56455
liujing@ubuntu:/proc/56455$ ls -al
total 0
dr-xr-xr-x   9 liujing liujing 0 Aug 11 09:28 .
dr-xr-xr-x 260 root    root    0 Jul 31 17:07 ..
dr-xr-xr-x   2 liujing liujing 0 Aug 11 09:32 attr
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 autogroup
-r--------   1 liujing liujing 0 Aug 11 09:32 auxv
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 cgroup
--w-------   1 liujing liujing 0 Aug 11 09:32 clear_refs
-r--r--r--   1 liujing liujing 0 Aug 11 09:28 cmdline
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 comm
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 coredump_filter
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 cpuset
lrwxrwxrwx   1 liujing liujing 0 Aug 11 09:32 cwd -> /home/liujing/projects/ConsoleApplication1/bin/x64/Debug
-r--------   1 liujing liujing 0 Aug 11 09:32 environ
lrwxrwxrwx   1 liujing liujing 0 Aug 11 09:32 exe -> /home/liujing/projects/ConsoleApplication1/bin/x64/Debug/ConsoleApplication1.out
dr-x------   2 liujing liujing 0 Aug 11 09:28 fd
dr-x------   2 liujing liujing 0 Aug 11 09:32 fdinfo
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 gid_map
-r--------   1 liujing liujing 0 Aug 11 09:32 io
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 limits
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 loginuid
dr-x------   2 liujing liujing 0 Aug 11 09:32 map_files
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 maps
-rw-------   1 liujing liujing 0 Aug 11 09:32 mem
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 mountinfo
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 mounts
-r--------   1 liujing liujing 0 Aug 11 09:32 mountstats
dr-xr-xr-x   5 liujing liujing 0 Aug 11 09:32 net
dr-x--x--x   2 liujing liujing 0 Aug 11 09:32 ns
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 numa_maps
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 oom_adj
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 oom_score
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 oom_score_adj
-r--------   1 liujing liujing 0 Aug 11 09:32 pagemap
-r--------   1 liujing liujing 0 Aug 11 09:32 patch_state
-r--------   1 liujing liujing 0 Aug 11 09:32 personality
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 projid_map
lrwxrwxrwx   1 liujing liujing 0 Aug 11 09:32 root -> /
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 sched
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 schedstat
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 sessionid
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 setgroups
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 smaps
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 smaps_rollup
-r--------   1 liujing liujing 0 Aug 11 09:32 stack
-r--r--r--   1 liujing liujing 0 Aug 11 09:28 stat
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 statm
-r--r--r--   1 liujing liujing 0 Aug 11 09:28 status
-r--------   1 liujing liujing 0 Aug 11 09:32 syscall
dr-xr-xr-x   3 liujing liujing 0 Aug 11 09:32 task
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 timers
-rw-rw-rw-   1 liujing liujing 0 Aug 11 09:32 timerslack_ns
-rw-r--r--   1 liujing liujing 0 Aug 11 09:32 uid_map
-r--r--r--   1 liujing liujing 0 Aug 11 09:32 wchan

// 所有的文件大小都为0
// 原因是因为它们都存储在内存里,而不是硬盘中
liujing@ubuntu:/proc/56751$ cat maps
00400000-00401000 r-xp 00000000 08:01 175585 a.out
00600000-00601000 r--p 00000000 08:01 175585 a.out
00601000-00602000 rw-p 00001000 08:01 175585 a.out
00602000-00623000 rw-p 00000000 00:00 0      [heap]
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]

用 cat /proc/进程id/maps 可以查看进程的内存空间情况
进程ID 用ps -aux 查看a.out
cd /proc/进程ID
cat maps

new

  • 会在分配内存(调用malloc)后 自动执行构造代码

delete

  • 会在free之前 执行 析构函数的代码

malloc

  • 底层需要维护 双向链表,记录一些关于内存信息。
    如果该链表被破坏,在free时引发段错误。
    在使用时其实非常简便,用malloc返回值(指针地址)存东西,用free释放。
    malloc 一次分配33个内存页(一次性映射33页物理内存)。使用完毕后 再次映射时,不确定 分配多少。
    33 * 4096 = 135168(0x21000)
    cat maps时 会发现
    无论malloc 一次还是多次,只要大小没有超过33个内存页, malloc会一次分配33个内存页给我们使用
    每次malloc都会多出16个字节,记录malloc信息,双向链表等信息

free

  • 不一定真正的释放内存(解除映射),在函数/程序结束之前,free 不会 释放最后 33个内存页的内存(不解除映射)。
    从cat maps上看,如果申请的内存页多于33个,则释放时按分配的大小释放,直到其小于等于33个,之后再怎么释放,系统还是会一直保留这33个内存页,直到进程结束

如果malloc的内存超过了33个内存页,会 映射 比申请内存稍多的内存页。(实测68页)

malloc的用法

申请多少就malloc(size),用完了调用free()释放。
getpagesize() 可以取得内存页的大小。
不同的进程 即使内存地址(虚拟地址)相同,存的东西也不一样,因为映射的物理内存不同。

brk和sbrk

brk和sbrk底层由 系统维系一个 位置(position),内存的分配和回收都参考这个位置。
void sbrk(int size)
size=0 返回sbrk/brk上次的末尾地址
size>0 分配内存空间,返回上一次末尾地址
size<0 释放空间
返回 内存的首地址。
int brk(void
ptr)
直接修改访问的有效范围的末尾地址
释放空间形成一个完整的page,则该页影射被解除
返回: -1:失败
sbrk一般用于内存的申请,brk一般用于内存的释放。
mmap/munmap 内存映射/解除映射
void* mmap(void* addr, size_t size, int prot,int flags,
int fd, off_t offset)
addr 可以指定首地址,一般为NULL,由操作系统指定
size 分配内存的大小,会补齐为内存页的整数倍
prot 是内存的访问权限,一般PROT_READ|PROT_WRITE
flags 是一个标识,可以设置映射 物理内存/文件,以及是否 被其它进程共享。 映射物理内存时,flags必须写上
MAP_ANONYMOUS
fd 是文件描述符,映射文件时使用
offset 是映射文件时的 指针偏移量
返回 分配内存的首地址
munmap 内存的释放
int i = 128 的 二进制
0000 0000 0000 0000 0000 0000 1000 0000
存入时:
1000 0000 -> -128
0000 0000
0000 0000
0000 0000
1000 0001 -> -127

你可能感兴趣的:(Linux,C,linux,C)