进程状态

进程命令:

ps aux

top

kill

进程号和相关函数

pid_t

父子进程共享

共享原则: 修改前保持只读共享,修改后各自维护独立数据副本

  • 初始状态: fork后父子进程共享同一地址空间,内核不立即复制整个地址空间。
  • 内存映射: 通过内存映射机制,父子进程的虚拟地址指向相同的物理内存区域。
  • 示例说明: 如变量

    num=10num=10num=10

    ,初始时父子进程通过相同虚拟地址访问同一物理内存。
  • 触发条件: 当任一进程执行写操作时(如修改

    num=10num=10num=10

    num=11num=11num=11

    ),内核才进行实际拷贝。
  • 拷贝过程:
    • 父进程修改时:复制新内存区域存放

      num=11num=11num=11

      ,子进程仍指向原

      num=10num=10num=10

    • 子进程修改时:同理复制新区域存放修改值(如

      num=12num=12num=12

知识点

核心内容

考试重点/易混淆点

fork函数返回值

父进程返回子进程PID(>0),子进程返回0

区分父子进程的唯一依据是fork返回值

PCB内核区差异

父子进程的PID、PPID、信号集不同

内核区数据独立,用户区数据初始共享

写时拷贝机制

读时共享数据,写时独立拷贝

修改变量后父子进程互不影响,不能用于进程间通信

代码段执行逻辑

子进程从fork处开始执行,不重复执行上方代码

父子进程代码段相同,通过返回值判断执行分支

GDB多进程调试

默认跟踪父进程,子进程自动运行

通过set follow-fork-mode设置跟踪父/子进程

detach-on-fork参数

on:其他进程脱离GDB控制;off:其他进程挂起在fork处

off模式下可通过inferior命令切换调试进程

inferior命令

查看所有进程列表,切换调试目标进程

使用inferior 编号切换,detach inferior 编号分离进程

对比项

父进程

子进程

fork返回值

子进程PID(>0)

0

GDB默认跟踪

是(parent模式)

否(需设置child模式)

数据独立性

写时拷贝后独立

写时拷贝后独立

调试切换方式

inferior 1

inferior 2

脱离GDB控制

detach inferior 1

detach inferior 2

命令

功能

使用场景

set follow-fork-mode parent/child

设置GDB跟踪父/子进程

调试前配置

set detach-on-fork on/off

设置其他进程是否脱离GDB

多进程调试控制

info inferiors

查看所有进程列表

查看当前调试进程

inferior 编号

切换到指定进程

切换调试目标

detach inferior 编号

使指定进程脱离GDB

释放进程控制

show follow-fork-mode

查看当前跟踪模式

确认当前配置

exec函数

  • 替换机制: 将当前进程的用户区数据(代码段、数据段、堆栈等)完全替换为新程序的内容,仅保留进程ID等内核区信息。
  • 形象比喻: 类似"金蝉脱壳",保持原进程外壳(进程ID等),但注入新程序"灵魂"(代码和数据)。
  • 执行起点: 新程序从main函数开始执行,完全替代原程序的执行流程。

将当前进程的用户区替换成要执行的文件的用户段,并存替换的main开始执行(内核保留)

exit

exit比_exit多了两个步骤。

带来效果:exit输出world _exit不输出

原因:对于这个代码

第二个printf因为没有加\n所以会加载到缓冲区,exit会刷新缓冲区,能输出出来

带有 \n)或程序正常 return 0 退出,都会触发刷盘,把缓冲区里的 hi 打印到屏幕上。

孤儿进程

产生条件:父进程先于子进程终止

  • 变化现象:
    • 父进程终止后子进程ppid变为1
    • 初始时子进程ppid为父进程pid
    • 原因说明:
      • 父进程终止后内核将孤儿进程分配给init进程(pid=1)
      • init进程成为新的父进程负责资源回收
    • 回收机制:
      • 避免僵尸进程产生
      • 由init进程(pid=1)负责回收孤儿进程资源
      • 无害性:
        • 不会造成资源泄漏
        • 系统自动处理无需人工干预

      僵尸进程

        • 产生原因:
          • 进程终止时会释放用户区数据(栈、堆等),但内核区的PCB(进程控制块)需要父进程调用wait()或waitpid()来释放
          • 当父进程未及时回收子进程资源时,子进程的PCB残留内核中形成僵尸进程
        • 特性:
          • 无法被kill -9命令终止
          • 进程状态显示为Z(Zombie)和<defunct>标记
        • 危害:
          • 占用系统进程号资源(PID有限)
          • 大量僵尸进程会导致系统无法创建新进程
        • 解决方法:
          • 父进程必须调用wait()或waitpid()回收子进程资源
          • 杀死父进程(临时方案),此时僵尸进程会被init进程(PID=1)接管并回收

      wait函数

        • 僵尸进程现象:
          • 子进程结束后父进程未调用wait回收,子进程会变成僵尸进程(状态为Z+)
          • 使用ps aux命令可以查看僵尸进程
        • wait函数调用:
          • 父进程中调用wait(NULL)会阻塞等待子进程结束
          • 当有子进程结束时(可用kill -9),wait会返回该子进程的pid
          • 当所有子进程都已结束时,wait会返回-1
        • 循环回收:
          • 通常将wait放在循环中,以便回收所有子进程
          • 当wait返回-1时可以通过break退出循环
      • 注意事项
        • 一次回收一个:wait函数一次只能回收一个子进程
        • 阻塞特性:默认是阻塞的,会暂停父进程执行直到有子进程结束
        • 资源回收:成功调用wait后会回收子进程资源,避免僵尸进程
        • 状态获取:可以通过wstatus参数获取子进程退出状态(演示中使用NULL表示不关心退出状态)

      waitpid

      • 功能相似性:两者都用于回收子进程资源
      • 主要区别:
        • wait只能回收任意子进程,waitpid可指定特定子进程
        • waitpid提供更多控制选项(如WNOHANG非阻塞模式)
        • waitpid可以回收指定进程组的子进程
      Logo

      有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

      更多推荐