提交 3e64bfa4 编写于 作者: H hypox64

unit5 finished

上级 926a99db
文件模式从 100755 更改为 100644
# Linux修改时区的正确方法
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# centOS 7 gcc install
yum install gcc -y
# 编译和运行HelloWorld
gcc HelloWorld.c -o HelloWorld-getchar
HelloWorld-getchar
## Linux修改时区的正确方法
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
## centOS 7 gcc install
yum install gcc -y
## 编译和运行HelloWorld
gcc HelloWorld.c -o HelloWorld-getchar
HelloWorld-getchar
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
# 实验记录
### 2-1 察看HelloWorld-gechar 的三个进程<br>
```bash
ps -aux | grep HelloWorld
```
3个进程的PID分别是26608 26649 26689<br>
![image](./record/pic/2-1.jpg)
### 2-2 屏显 HelloWorld 可执行文件信息<br>
```bash
file HelloWorld
```
![image](./record/pic/2-2.png)
x86-64 平台上的ELF 格式可执行文件。
一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
由于ELF 文件内部包含了足够的信息,操作系统可以根据ELF 可执行文件创建出进程映像,进程映像以及各种管理数据结构构成了进程实体,另外进程还可能向系统申请各种资源——共同组成了进程实体的全部内涵。进程实体被调度运行就构成了进程的活动,如果系统中有多个活动的进程,那么它们各自有独立的进程空间(各自独立地使用自己的0~0xFFFFFFFF 虚存空间)。<br>
在Linux 中进程PCB 是task_struct 结构体,<br>
### 进程间组织关系<br>
Linux 系统中所有进程通过进程控制块PCB(struct task_struct)形成多种组织关系。根据
进程创建过程可以有亲缘关系,通过进程间的父子关系组织成一个进程树<br>
一个进程通过创建一个子进程则形成父子关系,如果创建多个子进程,那么这些新创建的
进程间属于兄弟关系<br>
### 2-3 pstree 输出
![image](./record/pic/2-3.png)
### 2-4 查看会话、进程组和控制终端的例子
![image](./record/pic/2-4.png)
### PPID(PPID,Parent PID) PID(进程ID) PGID(Process Group ID 进程组 ID号) SID(Session ID 会话ID) TTY TPGID(tty process group ID for the process group leader) STAT() UID TIME COMMAND<br>
STAT:D 无法中断的休眠状态(通常 IO 的进程);R 正在运行可中在队列中可过行的;S 处于休眠状态;T 停止或被追踪;W 进入内存交换(从内核2.6开始无效);X 死掉的进程(从来没见过);Z 僵尸进程;+ 位于后台的进程组<br>
“会话/进程组/线程组”几个概念呈现层级关系,Linux 系统中可以有多个会话(session),
每个会话可以包含多个进程组(process group),每个进程组可以包含多个进程,每个进程构
成一个线程组——一个线程组由一个进程内的一个或多个线程组成,这些对象都有各自的ID。会话是从用户登录系统到退出前的全部活动,不同帐户的登录属于不同会话,而同一帐户的多次登录也构成不同的会话。而进程组主要出于作业控制的目的,有些shell 没有作用控制能力,就将整个会话的所有进程构成一个进程组。
### 2-5 创建进程的命令
```bash
chmod a+x shell-script
shell-script
```
![image](./record/pic/2-5.png)
第一行用于指出该脚本需要用/usr/bin/bash 来解
释执行,第二行shell 内部命令echo 用来显示,第三行HelloWorld 是外部命令(磁盘上的可执
行文件)。
### 2-6 通过ps 查找进程的PID
1.查找进程的PID<br>
2.kill PID <br>
```bash
ps -ef | grep HelloWorld-getchar
```
![image](./record/pic/2-6.png)
### 2-7 fork-demo 的输出
![image](./record/pic/2-7.png)
fork 函数被成功调用后将按照父进程的样子复制出一个完全相同的子进程。父进程fork()
函数结束时的返回值是子进程的PID 编号。新创建的子进程则也是从fork()返回处开始执行,
但不同的是它获得的返回值是0。也就是说父子进程执行上几乎相同,<br>
* 唯一区别是子进程中返回0 值而父进程中返回子进程PID。<br>
* 如果fork()出错则只有父进程获得返回值-1 而子进程未能创建。<br>
### 2-8 fork-demo 的输出
![image](./record/pic/2-8.png)
### 2-9 fork-twice-demo 执行后的 输出
![image](./record/pic/2-9.png)
### 孤儿进程和僵尸进程
(1) 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init 进程(进程号为1)所收养,并由init 进程对它们完成状态收集工作。
(2) 僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。
子进程结束后大部分资源都将直接回收,但是还将在PCB(struct task_struct 和内核堆栈)中记录一些退出时的状态等信息,这些信息供父进程检查后才能销毁回收。因此,僵尸进程因相应的数据没有父进程处理并回收,将会导致资源浪费,而孤儿则不会有这样的问题。
* 孤儿进程
![image](./record/pic/孤儿进程.png)
* 僵尸进程
![image](./record/pic/僵尸进程.png)
### 2-10 fork-exec-demo 的执行结果
![image](./record/pic/2-10.png)
* 这里可以看到子进程通过execve()将自己变身为“/usr/bin/ls”,因此不再执行与父进程里的代——即后面的“printf("this printf()will not be executed, because …”是没有机会得到执行的。
* fork()和exec 函数族构成了创建新进程的完整操作,如果父子进程功能相同则只用fork(),如果父子进程不同则利用exec 函数族的来实现。
### 2-11 用ps –ajx 查看daemon-demo 守护进程
![image](./record/pic/2-11.png)
关闭daemon-demo运行终端后仍能找到daemon-demo进程,且PID为1
### 2-12 /etc/rsyslog.conf 中的内容
![image](./record/pic/2-12.png)
日志信息写入了/var/log/messages 文件中。
### 2-13 查看/var/log/messages
![image](./record/pic/2-13.png)
由于前后运行了多次,所以出现了3个。
### 2-14&2-15 pthread-demo 的输出及ps –aLf 的输出
![image](./record/pic/2-14&2-15.png)
两个线程公用一个PID号19392,但是LWP却不一样。
### 2-16&2-17 PCB 开销
```bash
cat /proc/slabinfo | grep task_struct
```
比较两者在进程控制块上的开销(包括 struct task_struct 和内核栈)
2-16 fork-100-demo 运行前后的/proc/slabinfo 中关于 task_struct 数量
![image](./record/pic/2-16.png)
2-17 pthread-100-demo 运行前后的/proc/slabinfo 中关于 task_struct 数量
![image](./record/pic/2-17.png)
两者在运行后的task_struct数量均增加100,说明线程作为调度执行单位,进程控制块PCB(task_struct)还是需要的,这是最小资源的一部分。因此这方面资源开销对进程和线程都是一样的。
### 2-18&2-19&2-20&2-21内存描述符开销
* 查看mm_struct数量
```bash
cat /proc/slabinfo | grep mm_struct
```
2-18 fork-100-demo 运行前后的/proc/slabinfo 中关于 mm_struct 数量
![image](./record/pic/2-18.png)
2-19 pthread-100-demo 运行前后的/proc/slabinfo 中关于 mm_struct 数量
![image](./record/pic/2-19.png)
前者运行时mm_struct数量增加了100,而后者没有变化,说明,pthread-100-demo 虽然创建了 100 个线程,但是用于共享进程空间,并没有增加一个 mm_struct
* 查看vm_area_struct数量
```bash
cat /proc/slabinfo | grep vm_area_struct
```
2-20 fork-100-demo 运行前后的/proc/slabinfo 中关于 vm_area_struct 数量
![image](./record/pic/2-20.png)
2-21 pthread-100-demo 运行前后的/proc/slabinfo 中关于 vm_area_struct 数量
![image](./record/pic/2-21.png)
可以发现pthread-100-demo需要新增大约 150 左右的使用量,而fork-100-demo需要约 1300 左右的使用量,故线程的开销确实比进程要小。
# 课后作业
### 1.编写 C 语言程序,利用 fork()创建子进程,形成以下父子关系:并通过 ps 命令检查进程的进程号 PID 和父进程号 PPID 证明你成功创建相应的父子关系,同时也用 pstree 输出进程树结构来验证其关系。
![image](./homework/pic/problem_1.png)
* 解答:
* (1).[code](./homework/code/1_topology_1.c)
![image](./homework/pic/1_topology_1.png)
可以看到父进程12232拥有10个子进程且满足题目的要求
* (2).[code](./homework/code/1_topology_2.c)
![image](./homework/pic/1_topology_2.png)
可以看到父进程13738拥有10个子进程且满足题目的要求
* (3).[code](./homework/code/1_topology_3.c)
![image](./homework/pic/1_topology_3.png)
可以看子进程结构满足题目要求。
### 3.创建多个线程,在各个线程中打印出堆栈变量的地址,大致标记出其位置,注意区分主线程的堆栈和其他线程堆栈位置的差异。
* 解答:[code](./homework/code/3_pthread.c)
注意:编译时需要链接文件-lpthread -rdynamic
```bash
gcc ./3_pthread.c -lpthread -rdynamic -o 3_pthread
```
![image](./homework/pic/3_pthread.png)
程序中有一个父线程以及3个子线程,可以发现子线程的偏移地址以及返回地址都是一样的,且斗与父线程不一样。
### 4.尝试自行设计一个 C 语言小程序,完成最基本的 shell 角色:给出命令行提示符、能够接受命令;对于命令分成三种,内部命令(例如 help 命令、exit 命令等)、外部命令(常见的 ls、cp 等,以及其他磁盘上的可执行程序 HelloWrold 等)以及无效命令(不是上述两种命令)。
* 解答:[code](./homework/code/shell.c)
![image](./homework/pic/4_shell.png)
捕获键盘输入->判断是那种命令->
* 1.内部命令:打印help文件或exit(0);退出<br>
* 2.外部命令,fork出新的进程并使用execvp函数执行
* 3.可执行程序,与外部命令方法相同
* 4.无效命令:打印无效警告
[toc]
## 实验目的
* 通过编程实践、观察,学习内存管理的方式。
## 实验环境
* 硬件
1.Intel(R) Xeon(R) Bronze 3104 CPU @ 1.70GHz
2.DDR4 16G
* 软件
1.CentOS 7
2.ubuntu 18.04
3.VMware Workstation Pro 15
## 实验记录
### 2-1 察看HelloWorld-gechar 的三个进程<br>
```bash
ps -aux | grep HelloWorld
```
3个进程的PID分别是26608 26649 26689<br>
![image](./record/pic/2-1.jpg)
### 2-2 屏显 HelloWorld 可执行文件信息<br>
```bash
file HelloWorld
```
![image](./record/pic/2-2.png)
x86-64 平台上的ELF 格式可执行文件。
一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。
ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
由于ELF 文件内部包含了足够的信息,操作系统可以根据ELF 可执行文件创建出进程映像,进程映像以及各种管理数据结构构成了进程实体,另外进程还可能向系统申请各种资源——共同组成了进程实体的全部内涵。进程实体被调度运行就构成了进程的活动,如果系统中有多个活动的进程,那么它们各自有独立的进程空间(各自独立地使用自己的0~0xFFFFFFFF 虚存空间)。<br>
在Linux 中进程PCB 是task_struct 结构体,<br>
### 进程间组织关系<br>
Linux 系统中所有进程通过进程控制块PCB(struct task_struct)形成多种组织关系。根据
进程创建过程可以有亲缘关系,通过进程间的父子关系组织成一个进程树<br>
一个进程通过创建一个子进程则形成父子关系,如果创建多个子进程,那么这些新创建的
进程间属于兄弟关系<br>
### 2-3 pstree 输出
![image](./record/pic/2-3.png)
### 2-4 查看会话、进程组和控制终端的例子
![image](./record/pic/2-4.png)
### PPID
PPID(PPID,Parent PID) PID(进程ID) PGID(Process Group ID 进程组 ID号) SID(Session ID 会话ID) TTY TPGID(tty process group ID for the process group leader) STAT() UID TIME COMMAND<br>
STAT:D 无法中断的休眠状态(通常 IO 的进程);R 正在运行可中在队列中可过行的;S 处于休眠状态;T 停止或被追踪;W 进入内存交换(从内核2.6开始无效);X 死掉的进程(从来没见过);Z 僵尸进程;+ 位于后台的进程组<br>
“会话/进程组/线程组”几个概念呈现层级关系,Linux 系统中可以有多个会话(session),
每个会话可以包含多个进程组(process group),每个进程组可以包含多个进程,每个进程构
成一个线程组——一个线程组由一个进程内的一个或多个线程组成,这些对象都有各自的ID。会话是从用户登录系统到退出前的全部活动,不同帐户的登录属于不同会话,而同一帐户的多次登录也构成不同的会话。而进程组主要出于作业控制的目的,有些shell 没有作用控制能力,就将整个会话的所有进程构成一个进程组。
### 2-5 创建进程的命令
```bash
chmod a+x shell-script
shell-script
```
![image](./record/pic/2-5.png)
第一行用于指出该脚本需要用/usr/bin/bash 来解
释执行,第二行shell 内部命令echo 用来显示,第三行HelloWorld 是外部命令(磁盘上的可执
行文件)。
### 2-6 通过ps 查找进程的PID
1.查找进程的PID<br>
2.kill PID <br>
```bash
ps -ef | grep HelloWorld-getchar
```
![image](./record/pic/2-6.png)
### 2-7 fork-demo 的输出
![image](./record/pic/2-7.png)
fork 函数被成功调用后将按照父进程的样子复制出一个完全相同的子进程。父进程fork()
函数结束时的返回值是子进程的PID 编号。新创建的子进程则也是从fork()返回处开始执行,
但不同的是它获得的返回值是0。也就是说父子进程执行上几乎相同,<br>
* 唯一区别是子进程中返回0 值而父进程中返回子进程PID。<br>
* 如果fork()出错则只有父进程获得返回值-1 而子进程未能创建。<br>
### 2-8 fork-demo 的输出
![image](./record/pic/2-8.png)
### 2-9 fork-twice-demo 执行后的 输出
![image](./record/pic/2-9.png)
### 孤儿进程和僵尸进程
(1) 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init 进程(进程号为1)所收养,并由init 进程对它们完成状态收集工作。
(2) 僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。
子进程结束后大部分资源都将直接回收,但是还将在PCB(struct task_struct 和内核堆栈)中记录一些退出时的状态等信息,这些信息供父进程检查后才能销毁回收。因此,僵尸进程因相应的数据没有父进程处理并回收,将会导致资源浪费,而孤儿则不会有这样的问题。
* 孤儿进程
![image](./record/pic/孤儿进程.png)
* 僵尸进程
![image](./record/pic/僵尸进程.png)
### 2-10 fork-exec-demo 的执行结果
![image](./record/pic/2-10.png)
* 这里可以看到子进程通过execve()将自己变身为“/usr/bin/ls”,因此不再执行与父进程里的代——即后面的“printf("this printf()will not be executed, because …”是没有机会得到执行的。
* fork()和exec 函数族构成了创建新进程的完整操作,如果父子进程功能相同则只用fork(),如果父子进程不同则利用exec 函数族的来实现。
### 2-11 用ps –ajx 查看daemon-demo 守护进程
![image](./record/pic/2-11.png)
关闭daemon-demo运行终端后仍能找到daemon-demo进程,且PID为1
### 2-12 /etc/rsyslog.conf 中的内容
![image](./record/pic/2-12.png)
日志信息写入了/var/log/messages 文件中。
### 2-13 查看/var/log/messages
![image](./record/pic/2-13.png)
由于前后运行了多次,所以出现了3个。
### 2-14&2-15 pthread-demo 的输出及ps –aLf 的输出
![image](./record/pic/2-14&2-15.png)
两个线程公用一个PID号19392,但是LWP却不一样。
### 2-16&2-17 PCB 开销
```bash
cat /proc/slabinfo | grep task_struct
```
比较两者在进程控制块上的开销(包括 struct task_struct 和内核栈)
2-16 fork-100-demo 运行前后的/proc/slabinfo 中关于 task_struct 数量
![image](./record/pic/2-16.png)
2-17 pthread-100-demo 运行前后的/proc/slabinfo 中关于 task_struct 数量
![image](./record/pic/2-17.png)
两者在运行后的task_struct数量均增加100,说明线程作为调度执行单位,进程控制块PCB(task_struct)还是需要的,这是最小资源的一部分。因此这方面资源开销对进程和线程都是一样的。
### 2-18&2-19&2-20&2-21内存描述符开销
* 查看mm_struct数量
```bash
cat /proc/slabinfo | grep mm_struct
```
2-18 fork-100-demo 运行前后的/proc/slabinfo 中关于 mm_struct 数量
![image](./record/pic/2-18.png)
2-19 pthread-100-demo 运行前后的/proc/slabinfo 中关于 mm_struct 数量
![image](./record/pic/2-19.png)
前者运行时mm_struct数量增加了100,而后者没有变化,说明,pthread-100-demo 虽然创建了 100 个线程,但是用于共享进程空间,并没有增加一个 mm_struct
* 查看vm_area_struct数量
```bash
cat /proc/slabinfo | grep vm_area_struct
```
2-20 fork-100-demo 运行前后的/proc/slabinfo 中关于 vm_area_struct 数量
![image](./record/pic/2-20.png)
2-21 pthread-100-demo 运行前后的/proc/slabinfo 中关于 vm_area_struct 数量
![image](./record/pic/2-21.png)
可以发现pthread-100-demo需要新增大约 150 左右的使用量,而fork-100-demo需要约 1300 左右的使用量,故线程的开销确实比进程要小。
## 课后作业
### 1.编写 C 语言程序,利用 fork()创建子进程,形成以下父子关系:并通过 ps 命令检查进程的进程号 PID 和父进程号 PPID 证明你成功创建相应的父子关系,同时也用 pstree 输出进程树结构来验证其关系。
![image](./homework/pic/problem_1.png)
* 解答:
* (1).[code](./homework/code/1_topology_1.c)
![image](./homework/pic/1_topology_1.png)
可以看到父进程12232拥有10个子进程且满足题目的要求
* (2).[code](./homework/code/1_topology_2.c)
![image](./homework/pic/1_topology_2.png)
可以看到父进程13738拥有10个子进程且满足题目的要求
* (3).[code](./homework/code/1_topology_3.c)
![image](./homework/pic/1_topology_3.png)
可以看子进程结构满足题目要求。
### 3.创建多个线程,在各个线程中打印出堆栈变量的地址,大致标记出其位置,注意区分主线程的堆栈和其他线程堆栈位置的差异。
* 解答:[code](./homework/code/3_pthread.c)
注意:编译时需要链接文件-lpthread -rdynamic
```bash
gcc ./3_pthread.c -lpthread -rdynamic -o 3_pthread
```
![image](./homework/pic/3_pthread.png)
程序中有一个父线程以及3个子线程,可以发现子线程的偏移地址以及返回地址都是一样的,且斗与父线程不一样。
### 4.尝试自行设计一个 C 语言小程序,完成最基本的 shell 角色:给出命令行提示符、能够接受命令;对于命令分成三种,内部命令(例如 help 命令、exit 命令等)、外部命令(常见的 ls、cp 等,以及其他磁盘上的可执行程序 HelloWrold 等)以及无效命令(不是上述两种命令)。
* 解答:[code](./homework/code/shell.c)
![image](./homework/pic/4_shell.png)
捕获键盘输入->判断是那种命令->
* 1.内部命令:打印help文件或exit(0);退出<br>
* 2.外部命令,fork出新的进程并使用execvp函数执行
* 3.可执行程序,与外部命令方法相同
* 4.无效命令:打印无效警告
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
#include<stdio.h>
#include<malloc.h>
#define kB 1024
void *p;
int main()
{
int i = 8;
while(1)
{
p = malloc(i*kB);
free(p);
printf("%d,succeed,%s\n",i,p);
i++;
}
return 0;
}
#include <stdio.h>
#include <malloc.h>
#define kb 1024
void *bufs[134]; //1+1+1+2+1+4+1+8+1+16+1+32+1+64 = 134
// int list[]={0,2,5,10,19,36,69};
int main(){
int i;
for (i = 0; i < 134; ++i){
bufs[i] = malloc(1*kb);
}
for (i = 0; i < 134; ++i){
if (i==0)
printf("<1kb pre-addr:%p\n",bufs[i+1] );
else if (i == 2)
printf("1~2kb pre-addr:%p\n",bufs[i+1] );
else if (i == 5)
printf("2~4kb pre-addr:%p\n",bufs[i+1] );
else if (i == 10)
printf("4-8kb pre-addr:%p\n",bufs[i+1] );
else if (i == 19)
printf("8-16kb pre-addr:%p\n",bufs[i+1] );
else if (i == 36)
printf("16-32kb pre-addr:%p\n",bufs[i+1] );
else if (i == 69)
printf("32-64kb pre-addr:%p\n",bufs[i+1] );
else
free(bufs[i]);
}
while(1){
int size;
printf("input size(<64kb):\n");
scanf("%d",&size);
void *ptr;
ptr = malloc(size*kb);
printf("true:addr:%p\n",ptr );
}
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#define MB (1024*1024)
int main()
{
int pid,i;
char *buf;
pid = getpid();
printf("PID:%d\n",pid );
buf=(char*)malloc(1024*MB);
printf("addr_start:%p\n",buf);
for(i=0;i<1024*MB;i++)
{
buf[i]=0xaa;
}
printf("addr_end:%p\n",&buf[i]);
long size = &buf[i]-&buf[0];
printf("malloc size:%dMB\n", size/MB);
printf("please run pages-blackhole-demo\n");
getchar();
free(buf);
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#define MB 1024*1024
int main()
{
int i,j;
char temp;
int fd= -1;
char * filemap_buf;
char * anon_buf;
anon_buf=(char *)malloc(1000*MB);
while(1)
{
for(i=0;i<1000*MB;i+=4096)
anon_buf[i]=0xaa;
sleep(1);
}
return 0;
}
\ No newline at end of file
# 实验记录
### 5.1.1 进程映像
* 屏显 5-1 HelloWorld-getchar 的内存布局
![image](./record/pic/5-1.png)
每一行是一个具有特定属性的连续的内存区,每行的开头是该区间的地址范围。后面的 rxwp 分别代表:r=可读、w=可写、x=可执行、s=共享以及 p=私有,再后面一列的数字用于表示文件映射内存对应于文件中的起始位置(如果不是文件映射区则为 0)。
* 屏显 5-2 ELF 可执行文件的节
```bash
(base) hypo@hypo-CW65S$ readelf -S HelloWorld-getchar
There are 29 section headers, starting at offset 0x1968:
节头:
[号] 名称 类型 地址 偏移量
大小 全体大小 旗标 链接 信息 对齐
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
......
[14] .text PROGBITS 0000000000000580 00000580
00000000000001a2 0000000000000000 AX 0 0 16
[16] .rodata PROGBITS 0000000000000730 00000730
0000000000000010 0000000000000000 A 0 0 4
......
[23] .data PROGBITS 0000000000201000 00001000
0000000000000010 0000000000000000 WA 0 0 8
[24] .bss NOBITS 0000000000201010 00001010
0000000000000008 0000000000000000 WA 0 0 1
......
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
```
1.其中编号为 13 的.text 节是 Helloworld-getchar.c 编译后的 x86-64 平台上的可执行二进制代码
2.编号为 23 的.data是用于保存已初始化的全局变量和局部静态变量
3.编号为 16 的.rodata 是编译器识别出来的只读数据
* 屏显 5-3 ELF 段以及段-节映射关系
ELF 可执行文件的程序头(Program Header)里面描述了与装入过程有关的信息,告知操作系统如何将它们映射到虚拟空间中。我们用 readelf -l 命令查看这些信息
![image](./record/pic/5-3.png)
02 段所对应的节装入到虚存空间VirtAddr=0x0000000000000000 的区域中,而且此虚存空间区域的属性需要设置为“R E”——表示只读和可执行(包括了代码段和只读数据)。
03 段所对应的节装入到虚存空间VirtAddr=0x0000000000200db0 的区域内,并且其属性 Flags 为“RW”表示可读可写,但不可执行(因为它们都是数据)
### 5.1.2 堆区
在堆区分配内存可以用 malloc()等函数来完成,用完后需要用 free()进行释放。malloc()函数的原型如下:
```c
#include <malloc.h>
void *malloc(unsigned int num_bytes);
```
该函数将分配长度为 num_bytes 字节的内存块,如果分配成功则返回指向被分配内存的指针,否则返回空指针 NULL。当内存不再使用时,应使用 free()函数将内存块释放。
* 屏显 5-4 执行 malloc()之前的内存布局
![image](./record/pic/5-4.png)
* 屏显 5-5 执行 5 次 malloc()之后的内存布局
![image](./record/pic/5-5.png)
* 屏显 5-6 执行 2 次 free()之后的内存布局
![image](./record/pic/5-6.png)
观察[heap]区,由于将 5 次分配的内存释放掉第 2/4 次分配的空间,原来的空间将被分割成多段,但是 Linux 操作系统似乎并没有将这两段区间回收。
原因:1)malloc()作为 C 语言库对进程用户空间的管理和 2)操作系统对进程用户空间管理两级机制的问题了。C 语言库向操作系统申请可用的合法空间,并预留给变量或缓冲区来使用。然后用户进程通过 free()回收则代表这些区间不再用于原来的用途,但仍可能是合法空间(还能访问到原来该空间上的数据)。除非 C 语言库决定将某些内存区间向操作系统申请释放掉,这些区间才会称为非法空间。
但是如果分配的空间较大,malloc()回收空间时会向操作系统申请释放相应的空间。
* 屏显 5-7 Mem-malloc-8M 运行后的进程布局
```bash
564c4c575000-564c4c596000 rw-p 00000000 00:00 0 [heap]
.....
564c4c575000-564c4c596000 rw-p 00000000 00:00 0 [heap]
7fcd72fa8000-7fcd757ad000 rw-p 00000000 00:00 0
......
564c4c575000-564c4c596000 rw-p 00000000 00:00 0 [heap]
7fcd72fa8000-7fcd737a9000 rw-p 00000000 00:00 0
7fcd73faa000-7fcd747ab000 rw-p 00000000 00:00 0
7fcd74fac000-7fcd757ad000 rw-p 00000000 00:00 0
```
* 表 5-1 /proc/PID/status 中关于 VM 的项
```bash
# 初始状态
VmPeak: 4504 kB
VmSize: 4504 kB
VmData: 176 kB
.....
#分配 5 个 8MB 空间
VmPeak: 45484 kB
VmSize: 45484 kB
VmData: 41156 kB
......
#释放 2 个 8MB
VmPeak: 45484 kB
VmSize: 29092 kB
VmData: 24764 kB
```
VmSize:虚存总量 的变化——从少到多然后再下降
VmPeak:记录着该进程历史上曾获得的最高虚存总量
VmData:数据区
### 5.1.3 文件映射区
mmap()可以完成内存映射文件的操作
解除映射的函数为 munmap()
```c
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *start, size_t length);
```
* 屏显 5-8 mmap-demo 的输出
![image](./record/pic/5-8.png)
* 屏显 5-9 /proc/PID/maps 中的文件映射信息
```bash
hypo@hypo-CW65S:$ ps -aux | grep mmap
hypo 3076 0.0 0.0 4508 740 pts/0 S+ 20:52 0:00 ./mmap-demo
hypo 3115 0.0 0.0 21532 1012 pts/1 S+ 20:53 0:00 grep --color=auto mmap
hypo@hypo-CW65S:$ cat /proc/3076/maps
.....
7f2c49815000-7f2c49816000 rw-s 00000000 08:01 615399 file-mapped.txt
......
(hypo@hypo-CW65S:$ ls -i file-mapped.txt
615399 file-mapped.txt
```
* 屏显 5-10 被修改后的 file-mmaped.txt 文件内容
```bash
hypo@hypo-CW65S:$ cat file-mapped.txt
Modification in the memory---------e-mmapped buffer!
And this is the second line.
This is the last line!
```
### 5.1.4 栈区
#### 主线程栈区
每一次函数调用所扩展出来的堆栈空间被称为一个栈帧,因此随着函数的调用层次加深,堆栈的栈顶会随着栈帧的叠加而逐步扩展。函数调用时的返回地址、栈帧指针和函数内部的局部数据(也称堆栈变量、自动变量)都保存在堆栈中的某个栈帧结构上。
* 屏显 5-11 stack-demo 运行输出
![image](./record/pic/5-11.png)
* 屏显 5-12 /proc/PID/maps 展示的堆栈变化
```bash
#begin
7ffe5f0e5000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 1 层调用
7ffe5f0c3000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 2层调用
7ffe5f083000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 3层调用
7ffe5f043000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 3层调用
7ffe5f043000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 2层调用
7ffe5f043000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
#第 1 层调用
7ffe5f043000-7ffe5f106000 rw-p 00000000 00:00 0 [stack]
```
#### 线程栈
* 屏显 5-13 pthread-stack-demo 的运行结果
![image](./record/pic/5-13.png)
* 屏显 5-14 创建线程后的内存布局
```bash
#线 程 创 建 前
7ff695103000-7ff695104000 rw-p 00000000 00:00 0
7ffd7f003000-7ffd7f024000 rw-p 00000000 00:00 0 [stack]
#线 程 创 建 后
7ff695103000-7ff695104000 rw-p 00000000 00:00 0
7ffd7f003000-7ffd7f024000 rw-p 00000000 00:00 0 [stack]
#在ubuntu18.04中并没有观察到出现两个stack
```
### 5.1.4 访问任意进程的虚存
系统中有多个并发的进程存在,每个进程的虚存空间是独立的,除非映射了共享内存否则无法相互访问。进程通常只能通过/proc/self/mem 读取本进程内存的数据,但。 root 用户启动的进程可以不需要通过 ptrace 也能查看其他进程的内存空间,只要求被查看的进程处于不运行状态。
* 屏显 5-15 /proc/PID/mem 访问权限
![image](./record/pic/5-15.png)
* 屏显 5-16 show-var-addr 的输出
![image](./record/pic/5-16.png)
* 屏显 5-17 read-proc-mem 的输出
![image](./record/pic/5-17.png)
在16gb内存的ubuntu18.04操作系统下原代码运行失败,lseek64函数无法定位文件
### 5.1.6 虚存使用的物理页帧
```bash
cat /proc/PID/smaps #给出了 HelloWorld-gechar 进程各个虚存段使用物理页帧的情况
```
* 屏显 5-18 /proc/PID/smaps 的部分内容
```bash
hypo@hypo-CW65S:$ cat /proc/19361/smaps
55a323dda000-55a323ddb000 r-xp 00000000 08:01 615382 HelloWorld-getchar
Size: 4 kB
......
SwapPss: 0 kB
Locked: 0 kB
THPeligible: 0
VmFlags: rd ex
```
### 5.2.1 分页机制
1.每个处理器核上运行的进程使用的是虚地址,每次取指令或数据都需要将程序虚地址转换成物理地址,这需要借助于页表信息来转换.
### 5.2.2 进程页表
* 屏显 5-19 show-virt-addr 的输出
![image](./record/pic/5-19.png)
译后运行 show-virt-addr,打印出“Hello world!”字符串的虚地址 0x561a250f1754
* 屏显 5-20 crash 启动信息
```bash
```
# 课后作业
#### 1.设计编写以下程序,着重考虑其通信和同步问题:
```
```
\ No newline at end of file
00400000-00401000 r-xp 00000000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
00600000-00601000 r--p 00000000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
00601000-00602000 rw-p 00001000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
7fe7196da000-7fe7196df000 rw-p 00000000 00:00 0
7fe7196df000-7fe71a6db000 rw-p 00000000 00:00 0
7fe71a6db000-7fe71a6dd000 rw-s 00000000 fd:00 244 /home/hypo/tempfile
7fe71a6dd000-7fe71aedb000 rw-s 00002000 fd:00 244 /home/hypo/tempfile
7fe71aedb000-7fe71b09d000 r-xp 00000000 fd:00 364328 /usr/lib64/libc-2.17.so
7fe71b09d000-7fe71b29d000 ---p 001c2000 fd:00 364328 /usr/lib64/libc-2.17.so
7fe71b29d000-7fe71b2a1000 r--p 001c2000 fd:00 364328 /usr/lib64/libc-2.17.so
7fe71b2a1000-7fe71b2a3000 rw-p 001c6000 fd:00 364328 /usr/lib64/libc-2.17.so
7fe71b2a3000-7fe71b2a8000 rw-p 00000000 00:00 0
7fe71b2a8000-7fe71b2ca000 r-xp 00000000 fd:00 2765112 /usr/lib64/ld-2.17.so
7fe71b4b1000-7fe71b4b4000 rw-p 00000000 00:00 0
7fe71b4c7000-7fe71b4c9000 rw-p 00000000 00:00 0
7fe71b4c9000-7fe71b4ca000 r--p 00021000 fd:00 2765112 /usr/lib64/ld-2.17.so
7fe71b4ca000-7fe71b4cb000 rw-p 00022000 fd:00 2765112 /usr/lib64/ld-2.17.so
7fe71b4cb000-7fe71b4cc000 rw-p 00000000 00:00 0
7ffdd65ed000-7ffdd660e000 rw-p 00000000 00:00 0 [stack]
7ffdd664c000-7ffdd664e000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
MemTotal: 1863248 kB
MemFree: 1151560 kB
MemAvailable: 1170196 kB
Buffers: 0 kB
Cached: 217140 kB
SwapCached: 90124 kB
Active: 137548 kB
Inactive: 340016 kB
Active(anon): 124936 kB
Inactive(anon): 218736 kB
Active(file): 12612 kB
Inactive(file): 121280 kB
Unevictable: 28 kB
Mlocked: 28 kB
SwapTotal: 2097148 kB
SwapFree: 1441364 kB
Dirty: 4 kB
Writeback: 0 kB
AnonPages: 200360 kB
Mapped: 107548 kB
Shmem: 83192 kB
Slab: 93800 kB
SReclaimable: 31668 kB
SUnreclaim: 62132 kB
KernelStack: 10192 kB
PageTables: 37436 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 3028772 kB
Committed_AS: 4616544 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 215276 kB
VmallocChunk: 34359277564 kB
HardwareCorrupted: 0 kB
AnonHugePages: 32768 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 153472 kB
DirectMap2M: 1943552 kB
DirectMap1G: 0 kB
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#define MB 1024*1024
int main()
{
int i,j;
char temp;
int fd= -1;
char * filemap_buf;
char * anon_buf;
anon_buf=(char *)malloc(2000*MB);
while(1)
{
for(i=0;i<2000*MB;i+=4096)
anon_buf[i]=0xaa;
sleep(1);
}
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#define MB 1024*1024
#define KB 1024
int main()
{
int i,j;
char temp;
int fd= -1;
char * filemap_buf;
char * anon_buf;
printf("-----\n");
getchar(); // checkpoint 1 initial state
//第二步将在进程初始布局之上,创建两个新的内存区间,一个是8MB 的文件映射,一个是16MB 的非文件映射(匿名)区间。
if((fd=open("/home/hypo/tempfile",O_RDWR))<0)
printf("open tmpfile err!\n");
if((filemap_buf=(char*)mmap(NULL,8*MB,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))==MAP_FAILED)
printf("mmap fail!\n");
anon_buf=(char *)malloc(16*MB);
printf("allocated/mmapped\n");
printf("filemapped @ %p \n",filemap_buf);
printf("anon @ %p \n",anon_buf);
getchar(); // checkpoint 2 allocation
//第三步将在上述进程布局之上,对文件映射区间的前4MB 和匿名区间的前8MB 进行读操作。
for (i=0;i<4*MB;i+=4096)
temp=filemap_buf[i];
for(i=0;i<8*MB;i+=4096)
temp=*(anon_buf+i);
printf("read finish\n ");
getchar(); // checkpoint 3 read finish
//第四步在上述进程布局之上,对文件映射区间的前2MB 和匿名区间的前4MB 进行写操作
for(i=0;i<2*MB;i+=4096)
filemap_buf[i]=temp;
for(i=0;i<4*MB;i+=4096)
anon_buf[i]=0xaa;
printf("write finish \n");
getchar(); // checkpoint 4 write finish/make the pageframes dirty
//最后将通过unmap()和free()释放文件映射区和匿名内存区。
munmap(filemap_buf,8*MB);
free(anon_buf);
printf("all done \n");
getchar(); // checkpoint 5
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#define MB 1024*1024
#define KB 1024
int main()
{
int i,pid;
char temp;
int fd= -1;
char *filemap_buf;
char command_smaps[100];
char command_status[100];
char command_meminfo[100];
char command_maps[100];
char * anon_buf;
pid=getpid();
sprintf(command_smaps,"cat /proc/%d/smaps > smaps-check",pid);
sprintf(command_status,"cat /proc/%d/status > status-check",pid);
sprintf(command_meminfo,"cat /proc/meminfo >meminfo-check");
sprintf(command_maps,"cat /proc/%d/maps >maps-check",pid);
//在进程初始布局之上,创建两个新的内存区间,一个是8MB 的文件映射,一个是16MB 的非文件映射(匿名)区间。各自用mlock()函数锁定8KB 和16KB 的空间(不可换出)
if((fd=open("/home/hypo/tempfile",O_RDWR))<0)
printf("open tmpfile err!\n");
if((filemap_buf=(char *) mmap(NULL, 8*MB, PROT_READ|PROT_WRITE, MAP_SHARED,fd,0)) ==MAP_FAILED )
printf("mmap fail!\n");
mlock(filemap_buf,8*KB);
anon_buf=(char *)malloc(16*MB);
mlock(anon_buf,16*KB);
printf("allocated/mmapped\n");
printf("filemapped @ %p \n",filemap_buf);
printf("anon @ %p \n",anon_buf);
system(command_maps);
system(command_smaps);
system(command_status);
system(command_meminfo);
getchar(); // checkpoint 1 allocation
//对文件映射区间的前4MB 和匿名区间的前8MB 进行读和写操作各一遍。
for(i=0;i<4*MB;i+=4096)
filemap_buf[i]=temp;
for(i=0;i<8*MB;i+=4096)
anon_buf[i]=0xaa;
printf("write finish \n");
system(command_smaps);
system(command_status);
system(command_meminfo);
getchar(); // checkpoint 2 write finish/make the pageframes dirty
//run pages-blackhole-demo.c
//该pagesblackhole-demo 进程将大量消耗物理页帧,因此会引起reclaim-swap-writeback-demo进程的页帧被回收
printf("please run pages-blackhole-demo\n");
getchar(); // checkpoint 3 be swapped out
system(command_smaps);
system(command_status);
system(command_meminfo);
getchar();
//最后将通过对文件映射区间的前4MB 和匿名区间的前8MB 进行反复的读写操作。可以检查该进程重新获得物理页帧的现象。
printf("compete for the page frames\n");
while(1) //compete for the page frames, by writing
{
for(i=0;i<1*MB;i+=4096)
filemap_buf[i]=temp;
for(i=0;i<2*MB;i+=4096)
anon_buf[i]=0xaa;
}
getchar(); // checkpoint 4 will never get to this point
munmap(filemap_buf,8*MB);
free(anon_buf);
return 0;
}
\ No newline at end of file
00400000-00401000 r-xp 00000000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
Size: 4 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 4 kB
Private_Dirty: 0 kB
Referenced: 4 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex mr mp me dw sd
00600000-00601000 r--p 00000000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd mr mp me dw ac sd
00601000-00602000 rw-p 00001000 fd:00 52072941 /home/hypo/linux-homework/5.内存管理/record/code/reclaim-swap-writeback-demo
Size: 4 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 4 kB
Private_Dirty: 0 kB
Referenced: 4 kB
Anonymous: 4 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me dw ac sd
7fe7196da000-7fe7196df000 rw-p 00000000 00:00 0
Size: 20 kB
Rss: 20 kB
Pss: 20 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 20 kB
Referenced: 20 kB
Anonymous: 20 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 20 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me lo ac sd
7fe7196df000-7fe71a6db000 rw-p 00000000 00:00 0
Size: 16368 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 9348 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7fe71a6db000-7fe71a6dd000 rw-s 00000000 fd:00 244 /home/hypo/tempfile
Size: 8 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 8 kB
Private_Dirty: 0 kB
Referenced: 8 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 8 kB
ProtectionKey: 0
VmFlags: rd wr sh mr mp me ms lo sd
7fe71a6dd000-7fe71aedb000 rw-s 00002000 fd:00 244 /home/hypo/tempfile
Size: 8184 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr sh mr mp me ms sd
7fe71aedb000-7fe71b09d000 r-xp 00000000 fd:00 364328 /usr/lib64/libc-2.17.so
Size: 1800 kB
Rss: 48 kB
Pss: 9 kB
Shared_Clean: 40 kB
Shared_Dirty: 0 kB
Private_Clean: 8 kB
Private_Dirty: 0 kB
Referenced: 48 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex mr mp me sd
7fe71b09d000-7fe71b29d000 ---p 001c2000 fd:00 364328 /usr/lib64/libc-2.17.so
Size: 2048 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: mr mp me sd
7fe71b29d000-7fe71b2a1000 r--p 001c2000 fd:00 364328 /usr/lib64/libc-2.17.so
Size: 16 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 16 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd mr mp me ac sd
7fe71b2a1000-7fe71b2a3000 rw-p 001c6000 fd:00 364328 /usr/lib64/libc-2.17.so
Size: 8 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Referenced: 4 kB
Anonymous: 4 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7fe71b2a3000-7fe71b2a8000 rw-p 00000000 00:00 0
Size: 20 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 4 kB
Private_Dirty: 4 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7fe71b2a8000-7fe71b2ca000 r-xp 00000000 fd:00 2765112 /usr/lib64/ld-2.17.so
Size: 136 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex mr mp me dw sd
7fe71b4b1000-7fe71b4b4000 rw-p 00000000 00:00 0
Size: 12 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 12 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7fe71b4c6000-7fe71b4c9000 rw-p 00000000 00:00 0
Size: 12 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Referenced: 4 kB
Anonymous: 4 kB
AnonHugePages: 0 kB
Swap: 8 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7fe71b4c9000-7fe71b4ca000 r--p 00021000 fd:00 2765112 /usr/lib64/ld-2.17.so
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd mr mp me dw ac sd
7fe71b4ca000-7fe71b4cb000 rw-p 00022000 fd:00 2765112 /usr/lib64/ld-2.17.so
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me dw ac sd
7fe71b4cb000-7fe71b4cc000 rw-p 00000000 00:00 0
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me ac sd
7ffdd65ed000-7ffdd660e000 rw-p 00000000 00:00 0 [stack]
Size: 132 kB
Rss: 12 kB
Pss: 12 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 4 kB
Private_Dirty: 8 kB
Referenced: 12 kB
Anonymous: 12 kB
AnonHugePages: 0 kB
Swap: 4 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mp me gd ac
7ffdd664c000-7ffdd664e000 r-xp 00000000 00:00 0 [vdso]
Size: 8 kB
Rss: 4 kB
Pss: 0 kB
Shared_Clean: 4 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 4 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex mr mp me de sd
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex
Name: reclaim-swap-wr
Umask: 0002
State: S (sleeping)
Tgid: 9093
Ngid: 0
Pid: 9093
PPid: 8915
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 1000
VmPeak: 28796 kB
VmSize: 28796 kB
VmLck: 28 kB
VmPin: 0 kB
VmHWM: 13996 kB
VmRSS: 56 kB
RssAnon: 24 kB
RssFile: 32 kB
RssShmem: 0 kB
VmData: 16444 kB
VmStk: 132 kB
VmExe: 4 kB
VmLib: 1936 kB
VmPTE: 60 kB
VmSwap: 9440 kB
Threads: 1
SigQ: 0/7144
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000010000
SigIgn: 0000000000000006
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000001fffffffff
CapAmb: 0000000000000000
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
Cpus_allowed_list: 0-127
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 17
nonvoluntary_ctxt_switches: 2
5.内存管理/record/pic/5-19.png

20.6 KB | W: | H:

5.内存管理/record/pic/5-19.png

5.9 KB | W: | H:

5.内存管理/record/pic/5-19.png
5.内存管理/record/pic/5-19.png
5.内存管理/record/pic/5-19.png
5.内存管理/record/pic/5-19.png
  • 2-up
  • Swipe
  • Onion skin
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册