目录
一、进程的概念
我们都知道,程序的运行需要先加载到内存中。当一个程序运行加载到内存时,操作系统同时会为其创建一个进程控制块叫PCB,是进程属性的集合。每一个进程都有自己的PCB
所以进程是什么呢?进程=PCB+进程对应的代码和数据
在Linux系统中,进程控制块PCB具体叫做task_struct。
当多个程序同时运行时就会有多个进程,那么这些进程在访问系统资源时就会需要排队,因而它们会被存放在存放在task_queue队列中。同时操作系统中也会存在不同的task_queue,进程在不同的task_queue中排队可以访问不同的系统资源,这就是进程的动态运行。
二、Linux系统中查看进程
进程的名称就是对应程序的名称
ps ajx:查看当前系统所有进程的信息
ps ajx | head -1:显示进程的列属性
ps ajx | head -1 && ps ajx | grep 进程名:显示指定进程的信息
由于Linux系统中一切皆文件,包括使用的指令也是文件,即可执行程序。我们使用的指令就是在执行程序,所以使用 “grep 进程名” 时会多出一个grep进程,因此我们可以再加上 grep -v grep行文本反向过滤器
ps ajx | head -1 && ps ajx | grep 进程名 | grep -v grep:显示指定进程的信息(过滤grep进程)
三、进程ID
每个进程都有自己的ID,是一个无符号整型数,叫做pid
C语言中使用getpid获取当前进程的pid,使用getppid获得当前进程的父进程pid
通过多次启动进程发现,进程的PID总是变化的,但是其PPID不变,即父进程总是同一个进程。其父进程其实是bash程序,即命令行解释器,所以父进程总是同一个
四、进程信息保存的位置
进程的信息保存在/proc路径下,每当一个进程被创建时,操作系统会在/proc路径下新建一个与进程PID同名的目录文件,用于存放对应进程的信息。当进程结束时,该目录文件也会被同步删除
以可执行程序test2.exe为例,其PID为12830,在/proc路径下可以查找到以12830命名的目录文件
在该目录文件中存放着进程的诸多信息,其中
链接文件exe存放着的是进程对应的可执行程序的路径
链接文件cwd存放着的是进程的工作路径(进程需要新建文件等操作都会在该路径下进行,该工作路径可以手动修改)
修改进程工作路径:chdir
五、创建子进程
使用fork函数创建子进程,fork函数之后的代码父子进程共享,但是数据父子进程各自数据独立
fork函数的返回值:
在return语句结束函数之前,子进程就已经创建好了,所以父进程和子进程都会执行return语句
父进程fork函数返回新创建子进程的PID;子进程fork函数返回0;子进程创建失败返回一个负数
六、Linux系统中的进程状态
进程的状态本质是task_struct中一个属性的值
R(running):运行状态
S(sleeping):休眠状态
D(disk sleep):深度休眠状态
T/t(stopped/tracing stop):暂停状态
Z(zombie):僵尸状态
X(dead):死亡状态
1.R运行状态
进程正在运行就是运行状态
2.S休眠状态
进程在等待某个系统资源,则进入休眠状态
休眠状态又分为中断休眠S+和非中断休眠S:
S+:中断休眠S+在系统前台运行,进程在S+状态下可以被中断
S:非中断休眠S在系统后台运行,进程在S状态下不可被中断
一个奇怪的现象:
程序正在运行,但是查询到进程的状态却是S+而不是R,这是因为CPU运行速度很快,但是缓冲区冲刷数据到显示器需要一定时间,当前我们看到程序运行输出的数据其实是CPU很久之前执行的语句。所以查询到进程的状态是休眠状态,进程在等待数据输出到显示器。
3.T/t暂停状态
进程处于暂停状态,等待被唤醒。我们使用gdb调试器打断点,就是让进程在断点处暂停运行
在Linux系统中存在许多信号,使用kill -l来查看
kill -19:暂停进程
kill -18:唤醒进程,继续运行
4.D深度休眠状态
这是Linux系统进程特有的一种状态,全称为disk sleep,深度休眠状态不可被中断
深度休眠状态指的是进程需要向磁盘写入信息,等待磁盘信息拷贝时的休眠状态。当系统内存严重不足时,操作系统有权杀死一些进程,但如果操作系统杀死正在等待磁盘信息拷贝的进程则会导致数据丢失,因此操作系统不能杀死处于深度休眠状态的进程,即深度休眠状态不可中断。
5.Z状态(僵尸进程)
一个进程结束后,其在内存中的代码和数据会被清除,但是其task_struct会被保留,因为需要记录其结束信息,等待其父进程读取结束信息。如果一个进程结束了,但是其父亲进程一直不来读取该进程task_struct中的结束信息,那么该进程的task_struct就会一直存在,从而导致内存泄漏。这样的进程就是处于Z状态,叫做僵尸进程。
6.X状态
处理僵尸进程需要使用waitpid接口来读取其task_struct信息,随后僵尸进程就会从Z状态转变为X状态,这是一种消杀状态,僵尸进程就会被操作系统清理。
七、孤儿进程
当父亲进程比子进程先退出时,那么子进程就会成为孤儿进程。因为没了父进程,孤儿进程无法被父进程回收,所以孤儿进程通常会被1号进程(操作系统)领养。
八、进程的挂起态
当系统内存不足时,操作系统会将处于等待状态(等待某种资源)的进程的代码和数据转移到磁盘中,以此来释放更多的内存空间,这样的进程就是挂起态。当这些进程需要继续运行时,操作系统会从磁盘中将它们的代码和数据重新拷贝到内存中。