程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Linux进程

balukai 2025-05-26 13:48:34 文章精选 15 ℃

Linux 操作系统中的进程是其核心概念之一,理解进程对于系统管理、程序开发和故障排查都至关重要。下面我们将详细解析 Linux 进程的相关知识点。

1. 什么是进程?

在 Linux(及其他类 Unix 系统)中,进程是程序执行的一个实例。当你在终端输入一个命令或双击一个应用程序图标时,操作系统就会创建一个或多个进程来执行相应的程序。

一个进程通常包括:

* 程序代码: 正在执行的指令。

* 数据: 进程使用的变量、堆栈等。

* 资源: 进程正在使用的文件、内存、网络连接等。

* 执行上下文: 包含了进程的当前状态,例如寄存器值、程序计数器等,以便在进程切换时能够恢复执行。

2. 进程的状态

进程在其生命周期中会经历多种状态,这些状态反映了它是否在运行、等待资源或已被终止。常见的进程状态包括:

* 运行 (Running / R): 进程正在 CPU 上执行,或者已经准备好在 CPU 上执行(等待调度器分配 CPU 时间片)。

* 可中断睡眠 (Interruptible Sleep / S): 进程正在等待某个事件发生(如 I/O 操作完成、某个信号的到来),在此期间它可以被信号唤醒。大多数在等待 I/O 的进程都处于此状态。

* 不可中断睡眠 (Uninterruptible Sleep / D): 进程正在等待一个非常重要的事件发生(通常是硬件 I/O),在此期间它不能被信号唤醒。处于 D 状态的进程很难被杀死,除非它等待的事件发生或者系统重启。

* 停止 (Stopped / T): 进程被暂停执行,通常是由于接收到 SIGSTOP、SIGTSTP、SIGTTIN 或 SIGTTOU 信号。进程可以通过 SIGCONT 信号继续执行。

* 僵尸 (Zombie / Z): 进程已经终止,但其父进程尚未读取其退出状态。僵尸进程本身不占用内存和 CPU 资源,只占用进程表中的一个条目。如果父进程没有处理,它们会一直存在直到父进程终止。

* 死亡 (Dead / X): 进程已终止且其父进程已读取其退出状态。此状态非常短暂,通常在 ps 命令中不常见。

可以使用 ps aux 或 top 命令查看进程状态。

3. 进程的属性

每个进程都有一些关键属性,用于标识和管理:

* PID (Process ID): 进程的唯一标识符。

* PPID (Parent Process ID): 创建当前进程的父进程的 ID。每个进程(除了 PID 为 1 的 init 或 systemd 进程)都有一个父进程。

* UID (User ID): 运行该进程的用户 ID。

* EUID (Effective User ID): 进程实际执行时所具有的权限的用户 ID。

* GID (Group ID): 运行该进程的组 ID。

* EGID (Effective Group ID): 进程实际执行时所具有的权限的组 ID。

* TTY: 进程控制终端的名称(如果有)。

* CPU 使用率 (%CPU): 进程占用 CPU 的百分比。

* 内存使用量 (%MEM, VSZ, RSS): 进程占用的虚拟内存、常驻内存等。

* 优先级 (PRI, NI):

* PRI (Priority): 进程的调度优先级,值越小优先级越高。

* NI (Nice Value): 用户可以调整的优先级,范围从 -20(最高优先级)到 19(最低优先级)。默认是 0。nice 命令用于启动时设置,renice 用于运行时修改。

4. 进程的生命周期

* 创建 (Creation):

* fork() 系统调用: 创建一个子进程,它是父进程的精确副本(除了 PID 和 PPID)。子进程继承父进程的大部分资源,但拥有独立的内存空间。

* exec() 系统调用: 在现有进程的上下文中加载并执行一个新的程序。exec 系列函数会替换当前进程的代码、数据和堆栈,但 PID 不变。通常,一个新进程的创建流程是 fork() 后立即 exec()。

* 执行 (Execution): 进程在 CPU 上执行指令,根据其代码逻辑进行操作。

* 终止 (Termination): 进程完成任务或发生错误时会终止。

* 正常终止: 进程执行完毕,或者调用 exit() 系统调用。

* 异常终止: 进程收到终止信号(如 SIGTERM、SIGKILL)或发生未处理的错误(如段错误)。

* 僵尸进程: 当子进程终止后,如果父进程没有及时调用 wait() 或 waitpid() 系统调用来回收其资源和获取其退出状态,子进程就会成为僵尸进程。

5. 进程的类型

* 前台进程 (Foreground Process): 与终端交互的进程,可以直接接收用户输入,并将输出显示在终端上。当终端关闭时,前台进程通常也会终止。

* 后台进程 (Background Process): 在后台运行的进程,不与终端交互。可以使用 & 符号在命令末尾启动后台进程。

./my_script.sh &


可以使用 jobs 命令查看当前终端的后台作业。

* fg [job_id]: 将后台进程切换到前台。

* bg [job_id]: 将停止的前台进程切换到后台。

* 守护进程 (Daemon Process): 一种特殊的后台进程,它在后台运行,不与任何终端关联。通常在系统启动时启动,并在系统关闭时终止。它们执行系统级任务,如 web 服务器 (httpd)、数据库服务器 (mysqld) 等。守护进程的父进程通常是 init (PID 1)。

6. 进程间通信 (IPC - Inter-Process Communication)

进程之间需要共享数据或进行协作时,就需要 IPC 机制。常见的 IPC 方式包括:

* 管道 (Pipes):

* 匿名管道 (|): 只能在具有亲缘关系的进程(父子进程)之间使用,通常用于命令行中的命令连接。

* 命名管道 (FIFOs): 可以在不相关进程之间使用,通过文件系统中的特殊文件进行通信。

* 信号 (Signals): 软件中断,用于通知进程发生了特定事件(如终止、挂起、继续等)。

* 消息队列 (Message Queues): 进程可以将消息放入队列,其他进程可以从队列中读取消息。

* 共享内存 (Shared Memory): 多个进程映射同一块物理内存区域,从而实现高速数据共享。需要同步机制(如信号量)来避免数据冲突。

* 信号量 (Semaphores): 用于同步进程对共享资源的访问,防止竞态条件。

* 套接字 (Sockets): 最通用的 IPC 机制,可以在同一台机器上的进程间通信,也可以在网络上的不同机器间通信。

7. 进程管理命令

* ps: 显示当前正在运行的进程。

* ps aux: 显示所有用户的所有进程,包含详细信息。

* ps -ef: 以完整格式显示所有进程。

* ps -eLf: 显示所有线程。

* top: 实时显示进程信息,按 CPU 或内存使用率排序。

* 在 top 界面中,可以按 M (内存), P (CPU) 进行排序。

* 按 k 杀死进程。

* htop: 交互式进程查看器,比 top 更用户友好。

* pgrep: 根据名称或其他属性查找进程 ID。

* pgrep firefox: 查找 firefox 进程的 PID。

* pkill: 根据名称或其他属性发送信号给进程。

* pkill firefox: 杀死所有 firefox 进程。

* kill: 向指定 PID 的进程发送信号。

* kill <PID>: 默认发送 SIGTERM (终止信号)。

* kill -9 <PID>: 发送 SIGKILL (强制终止信号,不可被捕获或忽略)。

* killall: 根据进程名称发送信号给所有匹配的进程。

* killall nginx: 杀死所有 nginx 进程。

* nice: 以指定的优先级启动命令。

* nice -n 10 my_command: 以较低优先级启动 my_command。

* renice: 改变已运行进程的优先级。

* renice -n 5 <PID>: 提高进程优先级。

* nohup: 即使终端关闭,也让命令在后台继续运行。

* nohup my_command &: 运行 my_command,并将其输出重定向到 nohup.out。

* jobs: 列出当前 shell 中的后台作业。

* fg: 将后台作业切换到前台。

* bg: 将停止的前台作业切换到后台。

* pstree: 以树状结构显示进程关系。

* /proc 文件系统: 这是一个虚拟文件系统,提供了对内核数据结构的接口。每个进程在 /proc 目录下都有一个以其 PID 命名的子目录,其中包含该进程的详细信息(如 /proc/<PID>/status、/proc/<PID>/cmdline、/proc/<PID>/fd 等)。

8. 线程 (Threads)

* 进程 vs. 线程:

* 进程是操作系统资源分配的最小单位,拥有独立的地址空间、文件描述符等资源。

* 线程是 CPU 调度的最小单位,是进程内的一个执行流。同一个进程中的所有线程共享该进程的地址空间和大部分资源,但每个线程有独立的程序计数器、栈和寄存器。

* 优点: 线程比进程更轻量级,创建和销毁的开销更小,线程间通信更高效。

* 管理: 在 Linux 中,线程通常被称为“轻量级进程”(LWP - Light-Weight Process)。ps -eLf 命令可以查看线程信息。

9. 进程调度

Linux 内核的调度器负责在多个进程之间分配 CPU 时间。其目标是:

* 公平性: 确保所有进程都能获得 CPU 时间。

* 响应性: 确保交互式进程能够及时响应用户输入。

* 吞吐量: 最大化 CPU 利用率,完成更多工作。

调度器会根据进程的优先级、历史行为(如是否是 I/O 密集型或 CPU 密集型)来决定哪个进程在何时运行。

10. 系统启动中的进程

* init (System V init) 或 systemd (现代 Linux): PID 为 1 的进程是所有其他用户空间进程的祖先。它负责初始化系统、启动服务(守护进程),并回收孤儿进程(父进程先于子进程终止的子进程会被 init/systemd 收养)。

理解这些进程相关的知识点,能够帮助你更好地诊断系统问题、优化程序性能,并编写更健壮的 Shell 脚本。

最近发表
标签列表