一、进程的概念
进程是程序的一次执行过程,它包含了程序执行所需的资源,如内存、CPU时间、文件等。每个进程都有自己独立的地址空间和执行上下文。
二、进程和程序的区别
- 程序:静态的,存储在硬盘中代码和数据的集合。
- 进程:动态的,程序执行的过程,包括进程的创建、调度、消亡。一个程序可以运行多次,变成多个进程。
- 程序是永存的,进程是暂时的。
- 进程有程序状态的变化,程序没有。
- 进程可以并发,程序无并发。
- 进程与进程会存在竞争计算机的资源。
- 一个程序可以运行一个或多个程序,内存分布为0 - 3G是进程的空间,3G - 4G是内核的空间,虚拟地址通过MMU(Memory Management Unit)进行物理内存和虚拟内存的地址映射,1 page = 4k。
三、进程的作用
进程的主要作用是实现并发,提高系统资源的利用率。例如在无人机系统中,通过进程可以同时实现控制、视频、传输、存储等多个任务的并发执行。
四、进程的状态
Linux中的进程状态有:
- R:运行或可运行状态,进程在就绪队列中等待CPU分配时间片。
- S:可中断睡眠状态,进程在等待某个事件完成。
- D:不可中断睡眠状态,通常是由于IO操作等原因导致的。
- T:停止状态,可能是由于作业控制信号或被跟踪等原因导致的。
- Z:僵尸状态,进程已经结束但未被父进程收尸。
五、进程的调度
内核的主要功能之一是完成进程调度,宏观上实现并行,微观上实现串行。调度算法包括LRU(最近最久未使用)等。
六、查询进程相关命令
ps aux | grep 进程名
:查看进程相关信息,包括就绪态、运行态(R)、睡眠态、等待态(可唤醒等待态S、不可唤醒等待态D)、停止态(T)、僵尸态(Z)等。top
:根据CPU占用率查看进程相关信息。kill
和killall
:发送信号来控制进程,kill PID
发送信号给指定PID的进程,默认接收者关闭;kill -9 进程PID号
发送强制终止信号;kill -l
查看信号列表;killall -9 进程名
发送信号给进程名对应的所有进程。pstree -sp [pid号]
:查看某个进程的父子关系。
七、进程的原语操作
fork()
:一次调用会返回两次,在父进程中成功返回子进程的PID号(大于0),失败返回-1;在子进程中成功返回0,失败无返回值。子进程复制父进程的0到3G空间和父进程内核中的PCB,但ID号不同,变量不共享。子进程与父进程具有相同的代码逻辑,子进程的执行过程是从fork
函数之后执行。getpid()
:获得调用该函数进程的PID。getppid()
:获得调用该函数进程的父进程PID号。
八、应用场合
- 一个进程希望复制自己,使父子进程同时执行相同的代码段,例如网络服务中,服务器程序(如淘宝)接收登录和购物操作等。
- 一个进程需要执行一个不同的程序,使用
fork + exec
,例如minishell
,父进程fork
出一个子进程,子进程执行与父进程完全不同的程序。
九、进程与文件操作
- 如果打开文件的操作在
fork
之前,则子进程会继承父进程已打开的文件的相关信息(文件表项),此时父子进程共享文件表项,实现对同一个文件的操作,但会影响同一个offset值。 - 如果
fork
之后各自打开文件,则父子进程各自拥有各自的文件描述符及对应的文件表项,各自独立操作该文件,可能存在文件内容被覆盖。