进程是正在执行(已经开始执行但还没终止的)的程序实例,执行程序时,内核会将程序载入虚拟内存,为程序变量分配空间,建立内核记账(bookkeeping)数据结构,以记录与进程有关的各种信息(比如,进程ID,用户ID,组ID以及终止状态等)。
1.进程和程序的区别
程序是一个静态的代码集合,是一组指令的集合,用于执行特定的任务。程序通常以文件的形式存在,存储在硬盘、闪存或其他存储介质上。程序是静态的,不占用系统资源,只有在被执行时才会转换为进程。
程序通常有多种表现形式,常见的表现形式如下
源代码形式:使用编程语言(如:C语言)写成的一系列语句组成,是人类可以阅读的文本文件;想要执行程序,需要将源码转换为计算机可以理解的二进制机器语言指令。
解释型脚本形式:脚本是包含命令的文本文件,可以由shell或者其他命令解释器之类的程序直接处理。(如:python、Bash)等脚本语言通过解释器执行脚本
可执行文件:源代码通过编译、链接等步骤生成可执行文件;解释型脚本本身不需要编译,相当于可执行文件。
进程是程序的动态执行实例,是程序在执行时所占用的资源集合。每个进程都有自己的内存空间、系统资源和执行状态。进程是一个活动的实体,可以看作是程序在某一时刻的状态,包括程序计数器、栈、堆和数据段等。
一句话来概括就是;程序是永久的、静态的的可执行文件,而进程是动态的、暂时存在的运行过程。
2.程序的开始和结束
在 Linux 操作系统中,程序是静态的可执行文件,而进程是动态的实体。从程序变为进程的过程涉及多个步骤,其中还包括系统资源的管理和初始化。
1.当用户在 Shell 中输入命令时,Shell 会解析命令并查找对应的可执行文件位置,通常在系统的 PATH 环境变量中指定的目录中。
2.Shell 使用 fork() 函数创建一个新进程。操作系统在内核中为新进程分配一个唯一的进程 ID,并复制父进程(Shell)的内存空间和上下文,形成一个新的执行环境。
3.在新进程中,Shell 调用 exec 族函数来替换当前进程的内存空间为指定的可执行文件。操作系统将可执行文件从硬盘加载到内存中,并为程序分配必要的内存空间,包括代码段、数据段、堆和栈等。
4.操作系统会设置程序的环境变量,以便程序在运行时可以访问。如果程序需要接收命令行参数,操作系统将这些参数准备好,并传递给 main 函数。
5.全局变量和静态变量会被初始化为零(或空指针),以确保程序在开始执行时有一个已知的状态。程序的栈也会被初始化,为函数调用和局部变量分配空间。
6.在调用 main 函数之前,操作系统会执行额外的启动代码(如 crt0 或 crt1),该代码负责完成以下任务:
⚫设置异常处理机制。
⚫调用 C 语言库的初始化函数(如标准库函数的设置)。
⚫将命令行参数和环境变量传递给 main 函数。
7.完成所有初始化操作后,控制权会转移到用户定义的 main 函数,程序的实际执行从这里开始。
8.当 main 函数执行完毕后,程序返回一个退出状态(通常通过 return 语句返回)。操作系统接收这个状态,并进行相应的资源清理工作。
283