Linux系统编程Day11 -- 进程属性和常见进程
往期内容回顾
进程管理
理解计算机的软硬件管理
前言
在现代操作系统中,进程管理是核心模块之一。它负责调度和控制计算机中的所有程序执行,确保多任务环境下系统资源的合理分配和高效利用。理解进程管理对于深入掌握操作系统原理、提升编程技能以及系统优化都有重要意义。
大纲
本文将围绕进程管理的基本属性和常见进程类型展开介绍,帮助读者系统了解操作系统中进程的运行机制和管理方法。
一、进程管理的属性
进程是程序的一次执行实例,是系统进行资源分配和调度的基本单位。一个进程通常包含以下几个关键属性:
-
进程标识符(PID)
每个进程都有唯一的PID,用于操作系统跟踪和管理。利用getpid()可以获取对应进程的PID。
getppid则获取对应进程的父进程的PPID。
-
进程状态
进程在执行过程中会处于不同状态,常见状态包括
1. 新建(New)
-
定义:进程刚被创建,还没有准备好执行。
-
说明:在这个阶段,操作系统为进程分配必要的资源(如进程控制块PCB、内存空间等),还没有被加入到就绪队列中。
2. 就绪(Ready)
-
定义:进程已准备好执行,等待CPU分配。
-
说明:进程拥有所有必需资源,但当前CPU被其他进程占用,暂时处于等待状态。就绪队列中可能有多个进程,调度程序根据调度算法选择其中一个进入运行状态。
3. 运行(Running)
-
定义:进程正在CPU上执行指令。
-
说明:此时进程占用CPU资源,执行其程序代码。只有一个进程能在单核CPU上处于运行状态,多核CPU则允许多个进程同时运行(各占一个CPU核)。
4. 阻塞(Blocked / Waiting)
-
定义:进程等待某些事件(如I/O完成、信号量释放)而无法继续执行。
-
说明:当进程执行到需要等待外部资源(如磁盘读写、用户输入、网络数据)时,它会主动放弃CPU,进入阻塞状态。阻塞的进程不参与CPU调度。
5. 终止(Terminated / Exit)
-
定义:进程执行完毕或被操作系统/用户强制结束。
-
说明:进程释放所占用的所有资源,操作系统清理其进程控制块。若父进程未回收该进程的退出状态,会暂时形成僵尸进程。
6. 挂起(Suspended)
挂起状态是指进程暂时被操作系统从内存中“挂起”,即暂停执行且不占用CPU时间,同时其内存可能被换出到磁盘(交换空间)。挂起通常用于:
-
系统内存紧张时,将某些就绪或阻塞进程挂起,以释放内存。
-
用户或管理员手动暂停某个进程。
挂起分为两种:
-
挂起就绪(Suspended Ready):进程在就绪队列中,但不在内存,等待被重新调入内存后进入就绪状态。
-
挂起阻塞(Suspended Blocked):进程在阻塞队列中,但也被换出内存。
7. 僵尸进程(Zombie)
操作系统角度
僵尸进程是已经执行完毕(退出)的进程,但其父进程尚未读取子进程的退出状态,因此操作系统保留了该进程的PCB,便于父进程调用wait()回收资源。僵尸进程:
-
不占用CPU和内存资源,只占用进程表项。
-
如果父进程不回收,僵尸进程会一直存在,导致进程表资源浪费。
数据结构角度
-
僵尸状态在PCB中的状态字段标记为ZOMBIE。
-
PCB中保存的资源几乎全部释放,但保留了少量信息(如退出码、PID等),以便父进程获取。
-
进程表中占据一个条目,但不会出现在就绪或阻塞队列
8. 停止(Stopped)
定义:停止状态指进程被暂停执行,通常是由用户信号(如SIGSTOP)或调试器发出暂停指令引起。与挂起不同,停止状态的进程仍驻留内存,但CPU不调度其运行。
-
说明:进程处于停止状态时不会占用CPU资源,但保留所有资源。
-
可以通过信号(如SIGCONT)恢复运行。
-
Linux
常见状态有:R (Running or Runnable)、S (Sleeping)、D (Uninterruptible sleep)、Z (Zombie)、T (Stopped)、X(dead)等。
进程状态查看:
1、Running 运行状态
写一个死循环脚本
#include<stdio.h> #include<unistd.h> int main(){while (1) {int a = 2;a += 1;} }
root 590 1 590 0 0 Ss ?? 10:23.38 /usr/libexec/runningboardd
junye 11968 10590 11968 0 1 R+ s001 0:03.03 ./running
junye 11970 11662 11969 0 2 S+ s006 0:00.00 grep running
显示的进程状态为 Running 状态 。
2、sleep 休眠状态
#include<stdio.h> #include<unistd.h> int main(){while (1) {printf("hello my pid is %d!\n", getpid());sleep(2);} }
查看进程
root 590 1 590 0 0 Ss ?? 10:21.32 /usr/libexec/runningboardd
junye 11786 10590 11786 0 1 S+ s001 0:00.01 ./running
junye 11791 11662 11790 0 2 S+ s006 0:00.00 grep running
显示的进程状态为 sleep 状态 。
S 表示你的进程当前处于睡眠状态 --> 阻塞状态的一种,即进程正在等待某个事件(比如I/O完成、信号等),因此暂时没有占用CPU。这里使用printf访问外设,很慢所以在休眠状态。带+表示前台进程组可以被 ctrl+c终止。
3、暂停状态Stopped
当某个程序在运行时,使用kill -19 暂停其进程,此进程显示为T。
背景知识:前台进程组 vs 后台进程组
-
在 Unix/Linux 系统中,进程是以**进程组(process group)**组织的,方便终端控制和信号管理。
-
前台进程组是当前终端正在交互的进程组,它可以接收来自终端的信号(如 Ctrl+C 的 SIGINT,Ctrl+Z 的 SIGTSTP)。
-
后台进程组是非交互运行的进程组,不直接接受终端信号。
-
带 + 号 表示这个进程是前台进程组(foreground process group)的成员。
-
不带 + 号 表示这个进程不在前台进程组,通常是后台进程或守护进程。
状态转换示意
新建 → 就绪 → 运行 → 阻塞 → 就绪 → 运行 → 终止
-
新建 → 就绪:进程创建完成,准备好执行。
-
就绪 → 运行:调度器分配CPU给进程。
-
运行 → 阻塞:进程等待I/O或其他事件。
-
阻塞 → 就绪:等待事件完成,进程重新进入就绪队列。
-
运行 → 就绪:CPU时间片用完,进程让出CPU,回到就绪队列等待下次调度。
-
运行 → 终止:进程完成任务或被强制退出。
-
程序计数器(PC)
指示下一条要执行的指令地址。
-
寄存器内容
进程执行时CPU寄存器的值。
-
内存管理信息
包括代码段、数据段、堆栈等所在内存空间。
-
资源信息
如打开的文件、信号量、I/O设备等。
-
进程优先级
用于调度决策,优先级高的进程优先获得CPU时间。
-
父子关系
进程之间的创建关系,例如一个进程可以创建子进程。
二、常用的进程类型
根据不同的功能和生命周期,进程大致可以分为以下几类:
-
系统进程(System Processes)
负责操作系统核心功能的进程,如内核守护进程、调度器等,通常在后台运行,不直接与用户交互。
-
用户进程(User Processes)
由用户启动,执行用户应用程序。它们通过系统调用与操作系统交互。
-
守护进程(Daemon Processes)
一类特殊的后台进程,常驻内存,负责监控系统事件或提供服务,如网络服务守护进程sshd。
-
僵尸进程(Zombie Processes)
子进程结束后父进程未及时回收资源,保留少量进程信息的“死”进程。它们不占用CPU和内存,但占用进程表项。
-
孤儿进程(Orphan Processes)
父进程终止后,子进程依然运行,由操作系统将其“收养”并挂载到init进程下。
三、进程管理的核心机制
-
进程调度
操作系统根据一定策略(如先来先服务、时间片轮转、多级反馈队列等)分配CPU时间。
-
进程切换(上下文切换)
保存当前运行进程状态,恢复另一个进程状态,使多个进程能共享CPU。
-
进程同步与通信
通过信号量、管道、消息队列等机制,协调多个进程之间的合作与资源共享。
总结
进程管理是操作系统中最关键的部分之一,它通过维护进程的各种属性,合理调度和控制进程的运行,实现多任务的高效并发。掌握进程的基本属性和常用类型,能够帮助我们更深入理解操作系统底层原理,优化程序设计和系统性能。