linux 进程含义,简单进程理解

在学完了「计算机组成原理」之后,开始学习操作系统,这一篇博文主要讲讲简单的进程原理理解。

当我们把可执行文件执行的时候,就是创建了一个「进程」。其中背后的原理十分繁琐复杂,来吧让我们开始。

什么是进程

首先得搞清楚程序和进程的关系

程序就是静态的代码和数据

而进程就是程序的一次运行过程

进程有自己的生命周期,随着任务的启动而创建,随着任务的完成(或终止)而消亡,它所占用的资源也随着进程的终止而释放

一个可执行目标文件(即程序)可被加载执行多次,也就是说,一个程序可能对应多个不同的进程

进程在 Linux 中的表示

Linux 中:

所有的进程用一个双向循环列表(task list)描述,列表中的每一个元素就是一个进程

单个进程用进程描述符(process descriptor)的结构来描述,其结构类型定义为 task_struct,包含了一个进程的所有信息

166ea9d65938

现在具体说明 task_struct 是如何指向进程的虚拟内存的

166ea9d65938

在 task list 中有有很多个 task_struct,每个 task_struct 是一个进程描述符。

每一个进程描述符里面有一个 mm(memory map 内存映射) 指向 mm_struct (内存描述符 memory descriptor)

内存描述符存储了入上图所示中程序的每个段的开始(stary)与结束(end),权限(prot),flags(对象的类型)

进程的加载

现在我们已经简单的理解了,进程在 Linux 操作系统中是如何表现的了。现在我们来继续学习简单的进程加载:

假设我们有一个 hello world!的可执行文件

在 shell 中输入 ./hello [回车]

在 shell 命令行解释器里面构造 argv 和 envp

调用 fork() 函数,创建一个子进程,与父进程 shell 完全相同(只读/共享)包括,数据段,代码段,可读写段,堆及用户栈

调用 execve 函数。在当前进程中(新创建的子进程)的上下文中,加载运行 hello 程序,将 hello 程序中的 .text 节、.data 节、.bss 节等内容加载到当前进程的虚拟地址空间(仅仅修改当前进程上下文中关于存储器映射的数据结构,不从磁盘拷贝程序)

调用 hello 程序的 main 函数,hello 在一个进程的上下文运行

(整体过程如下)

166ea9d65938

上面的过程比较复杂,以我现在的水平还不能完全说清,只能对一些疑惑进行解答

argv 和 envp

假设我们有这样的代码:

#include

#include

int main(int argc, char *argv[], char *envp[])

{

char *home, *host;

home = getenv("HOME");

host = getenv("HOSTNAME");

printf("the args count %d \n", argc);

for (int i = 0; i < argc; i++)

{

printf("the args we have: %s \n", argv[i]);

}

printf("Your home directory is %s on %s.\n", home, host);

return 0;

}

生成可执行文件并运行:

g++ main.c -o main && ./main 1 2 3 4

166ea9d65938

main 函数的原型就是

int main(int argc, char *argv[], char *envp[]) {

}

那么在 shell 解释器中会构造这三个变量argc argv envp,存在主存中。

(像这样)

166ea9d65938

存储器映射(memory map)

之前我们说加载 hello 程序的时候,并不是真正把硬盘里面的内容加载到主存中,仅仅修改当前进程上下文中关于存储器映射的数据结构,不从磁盘拷贝程序

那么什么是存储器映射呢?

存储器映射就是:将虚拟地址空间的一个区域与硬盘上的一个对象建立关联(生成页表项),并初始化一个 vm_area_struct 结构信息

如何生成页表项的内容,暂且不说。。。(其实我也不会),先来说说如何生成 vm_area_struct

166ea9d65938

可通过 mmap 函数实现 vm_area_struct,下面说说 mmap 的功能以及参数的含义

功能

将指定文件 fd 中偏移量 offset 开始的长度为 length 的一块信息映射到虚拟空间中起始地址为 start,结尾地址为 end 的区域。并初始化相应页表项,建立文件地址和区域之间的映射关系。

port 参数

指定该段的访问权限,对应 vm_area_struct 中的 vm_prot,一共有这么几个值

166ea9d65938

flags 参数

指所映射对象的类型,对应 vm_area_struct 中的 vm_flags,一共有这么几个值

166ea9d65938

在 Linux 中:

一旦虚拟页被装入内存中,以后都是在主存页框和硬盘中的交换文件(swap file)之间调进调出。交换文件被内核维护,被称作交换分区(swap area)或者交换空间(swap space)

虚拟空间划分

根据上面的知识,我们可以把虚拟空间划分为:

166ea9d65938

同一个可执行文件被执行多次时

同一个可执行文件被执行多次时,也就是一个程序产生了多个进程。由于同一个可执行文件对应不同进程时

,只读代码区一样,可读可写数据区开始也一样,但属于私有对象为节省主存,多采用写时拷贝技术

166ea9d65938

假设进程 1 和进程 2 是同一个可执行文件:

进程 1 在运行过程中,内核为其分配若干个页框,并标记为只读

进程 2 在运行过程中,内核只需把给进程 1 的页框号填入进程 2 的页表项中,也标记为只读

如果进程 2 只是只读或者执行,那么就公用一块内存

如果进程 2 发生了写操作,就会发生因访问违例(写只读区),这时,内核就会重新分配页框(并拷贝),再将新内容写入。并修改进程 2 的页表项。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值