Linux进程

15 阅读4分钟

进程ID

  • 进程==程序的运行实例
    • 程序+程序加载器(内核)⇒进程
  • 每个进程都有进程ID(PID)
    • pid_t:唯一标识进程的正整数
    • getpid()返回调用者的PID
    • 内核使用“电梯”算法分配PID
      • 当电梯到达范围上限时,它循环使用
      • PID从范围低端重新开始
    • Linux系统最大PID为32767
      • 若所有PID槽位已用⇒fork()调用失败并返回EAGAIN
      • 上限可通过/proc/sys/kernel/pid_max调整(上限为
      • 内核PID_MAX_LIMIT常量,通常为4×1024×1024)

父进程

#include <unistd.h>
pid_t getppid(void);
  • 每个进程都有父进程
    • 通常,使用fork()创建该进程的进程即为父进程
    • 子进程终止时会通知父进程
  • 系统中所有进程由此形成树状结构
    • 根节点为init进程(PID=1),乃所有进程的始祖
    • “孤儿”进程将被init进程“收养”
  • getppid()返回调用者父进程的PID(PPID)

进程内存布局

readelf - 查看ELF文件的内存布局
进程的虚拟内存划分为段:

  • 文本段:机器语言指令(可执行代码)
    • 标记为只读以防止自我修改
    • 多个进程可在内存中共享相同代码
    • 在ELF文件中对应.text
  • 初始化数据:显式初始化的全局变量和静态变量
    • 进程创建时从程序文件读取值
  • 未初始化数据:未显式初始化的全局及静态变量
    • 进程创建时初始化为零
  • 栈:用于存储函数局部变量及调用链路信息(保存的栈指针SP和程序计数器PC寄存器)
    • 默认大小:通常8MB(可通过ulimit -s调整)
  • 堆:可动态分配与释放内存的区域
    • malloc()与free()函数
高地址 0xFFFFFFFF
+----------------------+
|     内核空间         | 1GB (用户进程不可直接访问)
|   (Kernel Space)     |
+----------------------+ 0xC0000000
|                      |
|       栈              | (向下增长)
|      (Stack)         |
|                      |
+----------------------+
|          ↓           |
|                      |
|          ↑           |
+----------------------+
|       内存映射区      | (共享库、文件映射等)
|   (Memory Mapping)   |
+----------------------+
|                      |
|        堆            | (向上增长)
|       (Heap)         |
|                      |
+----------------------+
|     BSS 段           | (未初始化静态/全局变量)
|    (.bss)            |
+----------------------+
|     数据段           | (已初始化静态/全局变量)
|    (.data)           |
+----------------------+
|     代码段           | (程序指令,只读)
|    (.text)           |
+----------------------+ 0x08048000 (32位典型起始)
低地址 0x00000000

环境变量列表

# 查看当前shell的环境变量
cat /proc/PID/environ | tr '\0' '\n'

/proc文件系统

/proc 是 Linux 系统中的一个 虚拟文件系统,它不占用实际的磁盘空间,而是由内核在内存中动态生成,提供了访问内核内部数据结构和进程信息的接口。 进程

进程信息:

/proc/1234/
├── cmdline           # 启动进程的完整命令行(以\0分隔)
├── comm              # 进程的命令名(可修改,不超过16字符)
├── cwd -> /path      # 符号链接到进程当前工作目录
├── environ           # 进程的环境变量(\0分隔)
├── exe -> /bin/bash  # 符号链接到可执行文件
├── fd/               # 打开的文件描述符
│   ├── 0 -> /dev/pts/1   # stdin
│   ├── 1 -> /dev/pts/1   # stdout
│   └── 2 -> /dev/pts/1   # stderr
├── fdinfo/           # 文件描述符详细信息
├── maps              # 进程内存映射(地址空间布局)
├── mem               # 进程内存(需通过工具访问)
├── mountinfo         # 进程相关的挂载信息
├── mounts            # 进程挂载的文件系统
├── net/              # 进程的网络信息
├── ns/               # 进程的命名空间
├── pagemap           # 页表映射信息
├── root -> /         # 符号链接到进程根目录
├── smaps             # 详细的内存映射统计
├── stat              # 进程状态信息(单行,空格分隔)
├── statm             # 内存状态(单行,页为单位)
├── status            # 进程状态(可读格式)
└── task/             # 线程信息(每个线程一个子目录)
    └── [TID]/        # 线程ID目录,结构与进程类似

系统信息:

/proc/
├── cpuinfo           # CPU详细信息(型号、核心、频率)
├── meminfo           # 内存使用统计(物理内存、交换空间)
├── loadavg           # 系统负载(1、5、15分钟平均负载)
├── uptime            # 系统运行时间(秒)
├── version           # 内核版本和编译信息
├── filesystems       # 支持的文件系统列表
├── interrupts        # 中断统计
├── iomem             # 物理内存映射
├── ioports           # I/O端口范围
├── mounts            # 已挂载的文件系统
├── net/              # 网络协议统计和配置
│   ├── tcp           # TCP套接字状态
│   ├── udp           # UDP套接字状态
│   ├── arp           # ARP表
│   └── route         # 路由表
├── scsi/             # SCSI设备信息
├── sys/              # 可调整的内核参数(见下文)
├── tty/              # 终端信息
└── ...               # 其他很多文件