程序运行的马甲:进程(1/7)

一个可执行文件被加载到内存中运行时,它在内存空间的分布如图所示:

在这里插入图片描述
在内存中有专门的堆栈空间,函数的局部变量是保存在栈中的,使用 malloc 申请的动态内存是在堆空间中分配的,它们是程序运行时比较特殊的两块内存区域:一块由系统维护,一块由用户自己申请和释放。

无论多么简单或者复杂的程序,一般都会封装成进程的形式,由操作系统管理、调度和运行。当我们在 shell 交互环境下运行应用程序时, bash 会解析我们的命令和参数,调用 fork 创建一个子进程,接着调用 exec() 函数将 hello 可执行文件的代码段、数据段加载到内存,替换掉子进程的代码段和数据段。然后 bash 会解析我们在交互环境下输入的参数,将解析的参数列表 argv 传递给 main,最后跳到 main() 函数执行。

在 Linux 系统中,每个进程都使用一个 task_struct 结构体表示,各个 task_struct 构成一个链表,由操作系统的调度器管理和维护,每一个进程都会接受操作系统的任务调度,轮流占用 CPU 去运行。

程序是安装在磁盘上某个路径下的二进制文件,而进程则是一个程序运行的实例:操作系统会从磁盘上加载这个程序到内存,分配相应的资源、初始化相关的环境,然后调度运行。程序和进程的关系就好比出租车和顾客打车的关系。出租车只是一个交通工具,停在马路旁,而顾客打车则是一个出租车运行实例,需要软件调度运行,分配相关资源,如司机、汽油、马路等,然后出租车才能完成这次任务。一个进程实例不仅包括汇编指令代码、数据,还包括进程上下文环境、CPU 寄存器状态、打开的文件描述符、信号、分配的物理内存等相关资源。

在一个进程的地址空间中,代码段、数据段、BSS 段在程序加载运行后,地址就已经固定了,在整个程序运行期间不再发生变化,这部分内存一般也称为静态内存。而在程序中使用 malloc 申请的内存、函数调用过程中的栈在程序运行期间是不断变化的,这部分内存一般也称为动态内存。用户使用 malloc 申请的内存一般称为堆内存(leap),函数调用过程中使用的内存一般被称为栈内存(stack)。

猜你喜欢

转载自blog.csdn.net/weixin_39541632/article/details/132273993