Linux的奇妙冒险——进程PCB第一讲
进程
- 1.进程的基本概念
- 2.进程的描述
- 3.查看进程
- 4.通过系统调用获得pid和ppid
- 5.通过fork()系统调用创建子进程
- 6.进程状态
- 1.浅度睡眠 S
- 2.深度睡眠 D
- 3 暂停状态T
- 4.僵尸状态 Z
- 5.死亡状态 X
- 7.僵尸进程
- 8.孤儿进程
- 9.进程优先级
1.进程的基本概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:
- 内核:内存管理,文件管理,进程管理,驱动管理
- 其他程序:函数库,shell程序等
计算机的一切都要被操作系统管理起来,而重要的理解就是六个字“先描述,在组织”
进程是什么呢
- 课本概念:程序的一个执行实例,正在执行的程序等
- 内核观点:担当分配系统资源(CPU时间,内存)的实体。
通常来说,linux下一切皆文件,当我们调度一个可执行文件时,系统先将其从磁盘中加载出来,进入到内存,分配一系列属性,内存,地址,数据等等,这是我们并不在将这个程序简单定义为程序了,而是称作进程。
2.进程的描述
首先一个操作系统无时无刻不在运行进程,通过
ps aux
可以查看系统正在运行的进程
当进入操作系统后第一个运行的进程就是操作系统内核,操作系统引导程序(BIOS或UEFI)在开机时首先执行,并将控制权转交给操作系统内核,操作系统对于进程管理进行“先描述,后组织”,对每一个进程分开描述,在进行统一管理,每一个进程被使用STRUCT_PCB,进行描述
进程 PCB(Process Control Block)是操作系统用于管理每个进程的一个数据结构。它包含了进程相关的各种信息和状态,操作系统通过这个数据结构来对进程进行调度、控制和管理。
PCB 中主要包含以下信息:
-
进程标识符(PID):唯一标识每个进程的ID号。
-
程序计数器(PC):记录进程下一条要执行的指令地址。
-
处理器寄存器:进程执行时使用的各种寄存器的值。
-
进程状态:如就绪、运行、阻塞等。
-
优先级:确定进程的调度优先级。
-
内存管理信息:如页表基址、限制等。
-
资源清单:进程拥有或申请的资源列表。
-
I/O状态信息:进程的I/O状态。
-
审计信息:如CPU时间、时间片使用情况等。
操作系统将一个个进程块管理起来,对其进行增删改查,这便是进程管理。
3.查看进程
在linux中,有这样一个文件proc
这些便是系统正在运行的进程,这些数字就是某些进程的进程标识符pid,通过ps指令可以进行查看
ps与grep配合可以查看某些特定进程
ps -aux | head -1 && ps aux | grep mytest | grep -v grep
4.通过系统调用获得pid和ppid
PID唯一标识一个进程,PPID描述了进程的父子关系。
以下程序通过,getpid,getppid,系统调用函数,可以获取到进程id,通过fork可以产生新的子进程
我们可以通过ps查看pid,ppid,可以看到除了12919的父进程为12053,其他都为12919的子进程
5.通过fork()系统调用创建子进程
-
创建新进程: fork()函数用于创建一个新的子进程,该子进程是原进程(即父进程)的副本。新创建的子进程与父进程拥有相同的代码、数据和打开的文件描述符。
-
返回值: fork()函数在父进程中返回子进程的进程ID(PID),在子进程中返回0。这样可以让进程区分它是父进程还是子进程。
-
资源共享: 父进程和子进程共享内存空间、打开的文件等资源,但对资源的修改不会相互影响。两个进程可以独立地执行,并且拥有各自的进程ID。
-
进程切换: 操作系统会在父进程和子进程之间切换执行,根据各自的优先级和系统调度策略进行调度。
-
用途: fork()函数通常用于创建新的并发进程,以实现多任务处理。子进程可以执行不同的任务,增加系统的并行性和可靠性。
每出现一个进程,操作系统都会为其创建pcb,fork()也是这样
子进程在fork()之后会与父进程共用一份代码和数据,如果存在数据被修改的需求时,会使用写时拷贝为子进程单独开一份空间,具体原理在以后虚拟内存和物理内存讲解,这里不过多讲解。
6.进程状态
在 Linux 中,进程可以处于以下几种主要状态:
-
Running (运行中):进程正在使用 CPU 资源执行。并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列
里。 -
Waiting (等待):进程正等待某种资源(如 I/O 操作、信号等)而暂时挂起。这个状态又可以进一步分为:
-
Interruptible (可中断): 进程可以被信号中断唤醒。
-
Uninterruptible (不可中断): 进程等待某些特殊的事件而不能被信号唤醒。
-
Stopped (停止):进程已经停止执行,通常是因为收到了 SIGSTOP、* SIGTSTP 等信号。
-
Zombie (僵尸):进程已经终止,但父进程还没有回收它的资源和状态信息。
-
Dead (死亡):进程已经终止并且资源已经全部释放。
进程状态在linux某版本中是这样定义的
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char *task_state_array[] = {
"R (running)", /* 0*/
"S (sleeping)", /* 1*/
"D (disk sleep)", /* 2*/
"T (stopped)", /* 4*/
"T (tracing stop)", /* 8*/
"Z (zombie)", /* 16*/
"X (dead)" /* 32*/
};
1.浅度睡眠 S
通过系统命令可以查看进程状态,如程序,当程序运行后进程就进入了可中断睡眠中了
浅度睡眠可以使用kill命令终止
2.深度睡眠 D
不可中断睡眠也叫深度睡眠,Linux 中不可中断睡眠(Disk Sleep)进程状态指的是一种特殊的系统进程状态。这种状态的进程无法被中断或唤醒,除非等待它所依赖的某些资源可用。
不可中断睡眠状态的主要特点包括:
- 无法被信号唤醒
这些进程即使收到中断信号也无法响应,无法被终止或切换到其他状态。
- 依赖某些硬件资源
进程被阻塞在等待某些硬件资源(如磁盘 I/O)的状态中。只有等到这些资源可用,进程才能继续运行。
- 容易引起系统假死
如果大量进程进入不可中断睡眠状态,可能会导致整个系统无法响应,出现假死现象。
- 无法被调度
由于无法被中断,这些进程也无法被正常的进程调度机制调度。
3 暂停状态T
在 Linux 中,进程状态中的暂停状态 (T) 表示进程已被暂停或停止。这通常发生在以下几种情况:
-
进程收到 SIGSTOP 信号: 当进程收到 SIGSTOP 信号时,它会进入暂停状态。这可能是由用户或程序发送的。通常可以使用 kill 命令来发送 SIGSTOP 信号。
-
进程处于调试模式: 当进程被调试器(如 gdb)附加或控制时,它会进入暂停状态,以便调试器检查和控制进程的执行。
-
进程被其父进程暂停: 如果进程的父进程使用 ptrace() 系统调用暂停了子进程,则子进程也会进入暂停状态。这通常发生在调试器控制进程时。
-
进程被 shell 暂停: 在 shell 中运行的进程可以使用 Ctrl+Z 命令被暂停,进入暂停状态。此时可以使用 fg 命令将进程恢复到前台执行。
要恢复处于暂停状态的进程,通常可以使用 kill -SIGCONT 命令将其重新唤醒并继续执行。了解进程状态的暂停状态有助于更好地管理和控制 Linux 系统中的进程。
4.僵尸状态 Z
在 Linux 操作系统中,僵尸状态(Zombie state)指的是一种特殊的进程状态。当一个子进程终止运行时,它会进入僵尸状态。这意味着该进程已经结束执行,但它的父进程还没有收集它的退出状态信息。
进程在终止时会向它的父进程发送一个信号,通知父进程自己已经结束运行。然而,如果父进程没有及时处理这个信号,子进程就会进入僵尸状态。
僵尸进程不会占用系统资源,因为它们已经不再运行了。但是它们会一直保留在进程表中,直到父进程调用 wait() 系统调用来获取子进程的退出状态信息。
如果父进程没有及时处理子进程的退出状态,就会产生大量的僵尸进程,这可能会影响系统的整体性能。
5.死亡状态 X
死亡状态只是进程正常结束后的说法,当一个进程的死亡信息被读取后,该进程所申请的内存资源将会被释放。
7.僵尸进程
当一个子进程结束后,没有父进程读取他的退出信息时,子进程不会退出,将会一直处于僵尸状态,我们称之为僵尸进程。
以下的简单程序,通过父进程通过fork创建了子进程并让子进程先走完代码,父进程未结束,可以模拟子进程进入僵尸状态
僵尸进程危害
-
资源占用:僵尸进程会占用系统资源,如CPU、内存等,从而影响其他正常进程的运行。长时间积累下来会造成系统性能下降。
-
安全隐患:僵尸进程可能被利用进行恶意操作,如黑客攻击、植入后门等,危害系统安全。
-
错误信息:僵尸进程的存在会给系统管理员或监控系统带来错误的信息,影响对系统状态的判断。
-
系统崩溃:在某些情况下,大量僵尸进程的存在可能导致系统崩溃或死机。
8.孤儿进程
孤儿进程是指当一个父进程终止或退出,而它的子进程仍在运行的情况。这种子进程就称为孤儿进程。在这种情况下,子进程会被init进程(系统的第一个进程)收养,作为它的子进程。
孤儿进程的特点有:
-
当父进程终止时,子进程不会终止,而是被init进程接管。
-
init进程会等待并处理孤儿进程的退出,以防止它们成为僵尸进程。
-
孤儿进程会继续执行,直到它们自己终止或被杀死。
-
孤儿进程不会受到父进程终止的影响,可以独立执行。
以下程序可以模拟孤儿进程的产生
通过以下脚本监视进程产生过程
while :; do ps axj | head -1 && ps axj | grep orphan | grep -v grep;echo "###########################";sleep 1;done
9.进程优先级
由于计算机的cpu资源是有限的,所以对资源分配也极为关键
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
1.查看系统进程
在linux或者unix系统中,使用ps -l
则会类似输出以下几个内容:
- UID : 代表执行者的身份
- PID : 代表这个进程的代号
- PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
- PRI :代表这个进程可被执行的优先级,其值越小越早被执行
- NI :代表这个进程的nice值
所谓的优先级主要指的是 PRI&&NI
PRI是当前运行队列里所使用的优先级,PRI越小优先级越高,若要修改优先级,即要修改NI值,加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice,这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行,nice其取值范围是-20至19,一共40个级别。
2.查看进程的优先级
top
用top命令更改已存在进程的nice:
进入top后按“r”–>输入进程PID–>输入要修改的NI