【Linux】进程概念

【Linux】进程概念

本文基于Linux内核核心知识,系统讲解进程相关核心概念、底层实现机制及实战操作,涵盖进程管理、状态切换、优先级调度、虚拟地址空间等关键内容,适合Linux编程入门及进阶开发者参考。

一、计算机系统基础:冯诺依曼体系结构

1.1 核心组成与数据流向

现代计算机(笔记本、服务器)均遵循冯诺依曼体系结构,核心组件包括:

  • 输入设备:键盘、鼠标、扫描仪等
  • 中央处理器(CPU):包含运算器和控制器
  • 存储器:特指内存(而非硬盘等外部存储)
  • 输出设备:显示器、打印机等

关键原则:所有设备只能直接与内存交互,CPU仅能对内存进行读写操作,外设数据输入输出必须经过内存中转。

1.2 举例理解:QQ聊天的数据流动过程

以QQ聊天为例,数据流向如下:

  1. 输入阶段:通过键盘输入消息 → 写入内存
  2. 处理阶段:CPU从内存读取消息数据,进行协议封装等处理后写回内存
  3. 传输阶段:网卡从内存读取封装后的数据,通过网络发送
  4. 接收阶段:对方网卡接收数据 → 写入内存
  5. 输出阶段:CPU读取内存中的接收数据,处理后写回内存 → 显示器从内存读取数据并显示

发送文件时流程类似,仅数据规模更大,需经过分块、校验等额外处理步骤。

二、操作系统:进程管理的核心载体

2.1 操作系统的定位与组成

  • 狭义OS:内核(Kernel),负责进程管理、内存管理、文件管理、驱动管理
  • 广义OS:内核+外壳程序(shell)、函数库(glibc)、系统级软件等

核心功能:对下管理软硬件资源,对上为应用程序提供稳定的执行环境,是硬件与用户程序之间的中间层。

2.2 操作系统的"管理"本质

管理的核心逻辑可概括为两步:

  1. 描述被管理对象:通过结构体(如C语言struct)记录对象属性
  2. 组织被管理对象:通过链表、红黑树等数据结构高效组织对象

例如进程管理:先用task_struct结构体描述进程属性,再用双链表将所有进程组织起来便于调度。

2.3 系统调用与库函数

  • 系统调用:操作系统暴露的底层接口,功能基础,使用门槛高
  • 库函数:对系统调用的封装,简化开发,如printf封装write系统调用

三、进程核心概念与实战操作

3.1 进程的定义

  • 课本概念:程序的一个执行实例,正在执行的程序
  • 内核视角:分配系统资源(CPU时间、内存)的基本实体
  • 本质:进程 = 内核数据结构(task_struct) + 程序代码和数据

3.2 进程控制块(PCB):task_struct详解

进程的所有属性都保存在PCB中,Linux下的PCB具体表现为task_struct结构体,存储在内存中,核心内容包括:

  • 标识符(PID):进程唯一标识
  • 状态:进程当前运行状态(运行、睡眠等)
  • 优先级:进程抢占CPU的优先级别
  • 程序计数器:下一条要执行的指令地址
  • 内存指针:指向程序代码、数据及共享内存的指针
  • 上下文数据:CPU寄存器中的数据(进程切换时需保存)
  • I/O状态信息:已打开文件列表、I/O设备分配情况

所有运行中的进程通过task_struct双链表组织在了你内核中。

3.3 进程相关实战操作

3.3.1 查看进程信息
  1. 通过/proc文件系统:/proc/[PID]目录包含对应进程的详细信息

  2. 使用命令行工具:

    bash 复制代码
    # 查看所有进程详细信息
    ps aux
    # 查看进程组、会话ID等信息
    ps axj
    # 动态监控进程状态
    top
3.3.2 获取进程ID(PID/PPID)

通过getpid()和getppid()系统调用获取进程ID和父进程ID:

c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    printf("PID: %d\n", getpid());    // 当前进程ID
    printf("PPID: %d\n", getppid());  // 父进程ID
    return 0;
}
3.3.3 创建进程:fork系统调用

fork是创建进程的核心系统调用,具有以下特性:

  • 有两个返回值:子进程返回0,父进程返回子进程PID,出错返回-1
  • 父子进程代码共享,数据采用写时拷贝机制(修改时才复制)

基础用法:

c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t ret = fork();
    if (ret < 0) {
        perror("fork failed");
        return 1;
    } else if (ret == 0) {
        // 子进程逻辑
        printf("I am child, PID: %d\n", getpid());
    } else {
        // 父进程逻辑
        printf("I am father, PID: %d, Child PID: %d\n", getpid(), ret);
    }
    sleep(1);
    return 0;
}

四、进程状态与特殊进程

4.1 Linux进程状态分类

Linux内核定义的进程状态(task_state_array):

  • R(running):运行状态,进程正在运行或在运行队列中
  • S(sleeping):可中断睡眠状态,等待事件完成
  • D(disk sleep):不可中断睡眠状态,通常等待I/O完成
  • T(stopped):停止状态,可通过SIGSTOP/SIGCONT信号控制
  • t(tracing stop):追踪停止状态
  • X(dead):死亡状态,仅为返回状态,不会出现在任务列表
  • Z(zombie):僵尸状态,子进程退出后父进程未读取退出状态

4.2 特殊进程:僵尸进程与孤儿进程

4.2.1 僵尸进程
  • 产生原因:子进程退出,父进程未调用wait()读取其退出状态
  • 危害:占用PCB资源,导致内存泄漏
  • 示例代码:
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t id = fork();
    if (id < 0) {
        perror("fork");
        return 1;
    } else if (id > 0) {
        // 父进程睡眠30秒,不读取子进程状态
        printf("Parent PID: %d, sleeping...\n", getpid());
        sleep(30);
    } else {
        // 子进程睡眠5秒后退出
        printf("Child PID: %d, will exit...\n", getpid());
        sleep(5);
        exit(EXIT_SUCCESS);
    }
    return 0;
}
4.2.2 孤儿进程
  • 产生原因:父进程提前退出,子进程仍在运行
  • 处理机制:孤儿进程会被1号init/systemd进程领养并回收
  • 示例代码:
c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t id = fork();
    if (id < 0) {
        perror("fork");
        return 1;
    } else if (id == 0) {
        // 子进程运行10秒
        printf("Child PID: %d, running...\n", getpid());
        sleep(10);
    } else {
        // 父进程运行3秒后退出
        printf("Parent PID: %d, will exit...\n", getpid());
        sleep(3);
        exit(0);
    }
    return 0;
}

五、进程优先级与调度

5.1 优先级核心概念

  • 作用:决定进程获取CPU资源的先后顺序
  • 核心参数:
    • PRI:进程基础优先级,值越小优先级越高
    • NI(nice值):优先级修正值,范围-20~19
    • 计算公式:PRI(new) = PRI(old) + NI

5.2 优先级调整实战

  1. 使用top命令动态调整:

    • 进入top界面,按"r" → 输入进程PID → 输入新的nice值
  2. 使用命令行工具:

    bash 复制代码
    # 启动进程时设置nice值
    nice -n 5 ./test
    # 调整已有进程的nice值
    renice 10 -p 1234
  3. 系统调用接口:

    c 复制代码
    #include <sys/resource.h>
    // 获取优先级
    int getpriority(int which, int who);
    // 设置优先级
    int setpriority(int which, int who, int prio);

5.3 进程调度核心概念

  • 竞争性:进程间竞争CPU资源,优先级决定竞争能力
  • 独立性:多进程运行时独享资源,互不干扰
  • 并行:多个进程在多个CPU上同时运行
  • 并发:多个进程在单个CPU上通过切换交替运行

5.4 Linux 2.6内核O(1)调度算法

核心设计:

  1. 每个CPU对应一个runqueue(运行队列)
  2. 队列分为活动队列(时间片未用完)和过期队列(时间片耗尽)
  3. 采用优先级数组(140个优先级)和位图快速查找最高优先级进程
  4. 调度时间复杂度为O(1),不受进程数量影响

六、环境变量与进程地址空间

6.1 环境变量实战

6.1.1 常见环境变量
  • PATH:命令搜索路径
  • HOME:用户主目录
  • SHELL:当前使用的Shell(默认/bin/bash)
6.1.2 环境变量操作命令
bash 复制代码
# 查看环境变量值
echo $PATH
# 设置环境变量
export MYENV="hello linux"
# 查看所有环境变量
env
# 清除环境变量
unset MYENV
6.1.3 代码中访问环境变量
c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 方法1:通过main函数第三个参数
    // int main(int argc, char *argv[], char *env[])
    
    // 方法2:通过environ全局变量
    extern char **environ;
    for (int i = 0; environ[i]; i++) {
        printf("%s\n", environ[i]);
    }
    
    // 方法3:使用getenv获取指定环境变量
    printf("PATH: %s\n", getenv("PATH"));
    return 0;
}

6.2 虚拟地址空间深度解析

6.2.1 核心认知
  • 程序看到的地址是虚拟地址,并非物理内存地址
  • 虚拟地址通过页表映射到物理地址,由操作系统和MMU(内存管理单元)完成转换
  • 父子进程虚拟地址相同但物理地址不同,实现数据隔离
6.2.2 进程地址空间布局(32位系统)

从高地址到低地址依次为:

  1. 内核空间(1G)
  2. 命令行参数与环境变量
  3. 栈区(向下增长)
  4. 共享区
  5. 堆区(向上增长)
  6. 未初始化数据区(BSS)
  7. 初始化数据区(Data)
  8. 代码区(Text,只读)
6.2.3 虚拟地址空间的优势
  1. 安全性:进程无法直接访问物理内存,避免非法修改
  2. 地址确定性:程序编译后虚拟地址固定,与物理内存布局无关
  3. 效率优化:采用延迟分配机制,仅在实际访问时分配物理内存
相关推荐
ITVV2 小时前
hadoop-3.4.1 单机伪部署
大数据·linux·hadoop
Elias不吃糖2 小时前
epoll 事件全集、每个事件的含义、哪些事件在实际服务器中最常见、哪些会组合出现
linux·c++·event
青柚~3 小时前
【鲲鹏服务器麒麟系统arm架构部署docker】
服务器·arm开发·docker·架构
人工智能训练3 小时前
Ubuntu中如何进入root用户
linux·运维·服务器·人工智能·ubuntu·ai编程·root
tianshiyeben3 小时前
WGCLOUD监控系统使用指南 - 告警消息整理完整版
linux·运维·服务器·系统安全·zabbix
Unlyrical3 小时前
splice, io_uring_prep_splice 调用(无效参数)
linux·服务器·c++·unix
牛奶咖啡133 小时前
银河麒麟高级服务器系统(V11)的安装部署实操保姆级教程
服务器·银河麒麟高级服务器操作系统安装·银河麒麟高级服务器v11配置·设置基础软件仓库时出错·银河麒高级服务器系统的实操教程·生产级部署银河麒麟服务系统教程·linux系统的快速上手教程
喜欢你,还有大家3 小时前
Docker-存储
运维·docker·容器
暂时先用这个名字3 小时前
信创时代下,PHP/MySQL应用的平滑迁移与运维管理升级(AI整理)
运维·mysql·php·信创·国产化·国产·迁移