本文已参与「新人创作礼」活动,一起开启掘金创作之路。
进程的概念
一、冯·诺依曼体系结构
根据冯·诺依曼体系结构,计算机由五大基本部分组成,其中:
输入设备包括:键盘、鼠标、网卡等
输出设备包括:显示器、打印机、网卡等
存储器一般认为是内存
运算器和控制器集成在中央处理器(Central Processing Unit, CPU)中
二、什么是进程
进程是一个程序执行的实例,是系统分配资源和执行任务的基本单位,更是操作系统结构的基础。
进程能够成为操作系统结构的基础,主要在于它提供的两类关键的假象:
1、“独占CPU”
计算机上的所有进程都是不间断地在运行,给我们的感觉就像是每个进程都在独占CPU资源,但事实上,每个进程的执行流都是交错的:
进程A运行一段时间,接着进程B运行一段时间,然后是进程C,最后又轮到进程A...
操作系统如此往复地进行进程切换(或称“进程调度”),让所有进程轮流执行。
- 在一个CPU下,多个进程互不干扰、轮流推进的现象称为“并发”,每个进程执行的时间段称为“时间片”;
- 在多个CPU下,多个进程同时推进的现象称为“并行”。
2、“独占内存”
根据冯诺依曼体系结构的规定,所有的程序都要从磁盘加载到内存才能被操作系统包装成进程在计算机上运行。而一台计算机上往往运行着大量的进程,这就意味着内存需要被所有进程共享,而非进程独占内存。
为了让每个进程都能使用到内存资源且进程之间不会相互影响,操作系统提供了进程虚拟地址空间的概念使得每个进程都能拥有自己独立的内存空间。
3、进程的特性
根据上述两个假象,总结出进程的三大特性:
- 独立性:进程是程序运行的基本单位,运行时独享资源,进程之间互不干扰;
- 并发性:操作系统采用时间分片的方式轮流切换多个进程使它们都得以推进;
- 竞争性:进程数量往往多于资源数量(如CPU),因此需要竞争资源的使用权。但是为了合理竞争以高效完成任务,会有“优先级”的概念从中制约。
三、进程管理
进程属于操作系统的进程管理部分,其中描述一个进程相关信息的属性集合称为PCB(Process Control Block, 进程控制块)。
task_struct
Linux下的PCB是一个名为task_struct
的结构体,其描述的属性包括:
1、标识符
即pid
,是用来区分进程的唯一标识;
2、进程调度信息
包括进程状态,进程的优先级等;
3、记账信息
包括进程创建的时间、运行的时间等;
4、IO状态信息
包括分配给进程的IO设备、进程打开的文件等;
5、上下文信息
上下文信息保证了进程下一次切换回来的时候还能继续进行未完成的工作,是内核重新启动一个被调度的进程必需的状态信息,通常包括:
- 寄存器上下文
与进程相关的寄存器信息,如程序计数器(或称PC计数器,用来保存程序中即将被执行的下一条指令的地址,相当于图中的EIP):
- 用户级上下文
包括指向程序代码、数据、进程共享区的指针。
- 内核级上下文
包括指向内核相关数据结构的指针。
四、进程状态
1、R状态(Running)
Linux中创建了“运行队列”(双向循环链表)来调度(scheduling)进程。在该队列中的进程都是R状态,即:可运行状态;
该状态有两种情况:
- 进程正在运行
- 进程正在运行队列中等待被调度。
2、S状态(Sleeping)
Linux中创建了“等待队列”(双向循环链表)来维护正在休眠(或者说被挂起)的进程。
当进程正在等待某事件完成时(比如等待文件有数据可读),OS就会将它标记成S状态,将其从运行队列移除并加入等待队列。
当事件完成后,OS用信号将其唤醒并重新将它加入等待队列。
由于休眠状态的进程可以通过信号kill
掉,因此该状态又被称为“可中断睡眠状态”。
3、D状态(Disk Sleep)
处于该状态的进程同样是在休眠,但是与S状态不同,D状态的进程不能被信号中断,也同样不能被kill,因此该状态又被称为”不可中断睡眠状态“。
注:当进程正在等待设备IO时(磁盘IO、网卡IO等),操作系统为了保护它而将其设为D状态,避免进程IO被中断。
4、T状态(Stopped)
通过SIGSTOP
发送停止信号可以将某一进程设为T状态,此时该进程会停止运行,直到使用SIGCONT
信号将其唤醒。
5、T状态(Tracing Stop)
又称为t状态,进程在调试断点处停止时会处于该状态。
6、Z状态(Zombie)
当进程退出时,会自动将自己退出时的相关信息写入PCB中,供操作系统或父进程进行读取。
在Linux下,对于一般的进程,其退出信息会由bash进程自动读取。
但是对于用户进程中创建的子进程,如果它先于父进程退出而父进程没有进行等待来读取子进程的退出信息,那么子进程就会处于Z状态,该子进程又被称为“僵尸进程”。
僵尸进程无法被kill,因为它是已死亡的进程。
Z状态的子进程需要父进程读取它的退出信息后才会释放PCB(即真正的死亡)。如果父进程创建了大量子进程而不进行等待,那么这些没有被释放的PCB就可能造成资源浪费。
7、X状态(Dead)
进程在真正死亡之前会处于X状态,接着就会被操作系统释放PCB,该过程非常短暂,很难被ps
命令捕捉到。
五、特殊进程
1、孤儿进程
当父进程退出,而子进程依然在运行或者处于僵尸状态,那么这些子进程就被称为“孤儿进程”。
2、init进程
init进程的pid为1,是在系统启动时由内核创建的,它不会终止,是所有进程的祖先。
孤儿进程会被init进程“领养”:
- 对于非僵尸孤儿进程,它们运行结束后会由init进程负责等待;
- 对于僵尸孤儿进程,init会在适当的时侯统一进行清理(比如系统资源非常短缺或者僵尸进程积累过多时)。
3、守护进程
守护进程,也被称为精灵进程(Daemon),是Linux下运行于后台的进程,一般在系统开机时通过启动脚本启动。
守护进程的命名一般以d结尾,常见的如:mysqld、httpd
守护进程的特点包括:
- 长时间运行于后台,不受终端控制。
- 开机自启,关机结束。
- 父进程是init进程,因此守护进程也是孤儿进程。
六、进程优先级
1、优先级的概念
优先级是系统用来衡量进程重要性和按序分配资源的重要标准。
优先级越高,进程就会越早得到资源。
使用top
命令查看进程优先级:
其中,
PR
:优先级值(Priority),PR值越低说明优先级越高。
NI
:nice值,取值范围[-20,19],用来在PR基准值的基础上调整进程的优先级。
PR = PR基准值 + NI,其中基准值为80,NI默认为0。
2、调整优先级的方式
- 运行
top
命令时,按下R,输入进程pid加回车,再输入要调整的nice值加回车,就可以调整指定进程的nice值; renice val -p pid
:将正在运行的某一进程的nice值修改成val;nice -val 命令
:以nice=val来启动某一进程,如nice --20 ./proc
以-20的nice值启动proc;
注:修改nice值可能需要root权限。
七、进程相关命令
1、ps
ps
命令是linux下用于查看进程相关信息的命令,常用的参数搭配:
ps -axj
:以作业格式显示所有进程的详细信息
ps -aux
:用户名在第一列显示所有进程的详细信息
ps -al
:查看进程的优先级信息
ps -axj | grep 'xxx'
:按关键字搜索进程并显示详细信息
ps -axj | head -1 && grep 'xxx'
:按关键字搜索同时显示列信息
注:UID是操作系统标识用户的数字id。
补充:前台进程和后台进程
进程状态后面的'+'号表明该进程是前台进程;
前台进程会占据终端界面,受用户输入的控制;
后台进程独立于终端运行,不受终端输入的控制,但是可以通过kill命令杀死后台进程。
命令 &
就可以让该命令放到后台执行,比如./test &
就是让test以后台进程的方式运行。
2、top
用来监视Linux系统的状况,实时显示各进程的优先级和资源占用情况,类似于windows下的资源管理器。
按上下键可以滚动式地查看,q退出。
常用选项:
top -d num
:每num秒更新一次top的显示页面;
top -p pid
:监视指定pid的进程
注:top
命令显示的PR是nice值+20,而ps -al
命令显示的PRI是nice值+80。