0

0

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

爱谁谁

爱谁谁

发布时间:2025-07-23 08:52:37

|

465人浏览过

|

来源于php中文网

原创

一. 进程创建

fork函数用于创建新进程,生成的进程称为子进程,而调用fork的进程称为父进程。

fork函数的声明位于头文件 中。

在创建子进程时,系统会为子进程分配新的内存块和内核数据结构,并将父进程的部分数据结构内容复制到子进程中。子进程随后被添加到系统的进程列表中。fork函数执行后,调度器开始调度新创建的进程。

关于fork函数的返回值:

  • 子进程接收到返回值0。
  • 父进程接收到子进程的进程ID(PID)。
  • 如果创建失败,fork函数返回-1。

子进程和父进程共享fork函数之后的代码。

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

实例演示:

int main() {
    printf("before: pid: %d\n", getpid());
    pid_t id = fork();
    printf("after:\n");
    if (id == 0) {
        // 子进程
        printf("我是子进程  pid: %d  ppid: %d\n", getpid(), getppid());
    } else if (id > 0) {
        // 父进程
        printf("我是父进程  pid: %d  ppid: %d\n", getpid(), getppid());
    } else {
        printf("出错\n");
    }
    return 0;
}

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换


二. 进程终止

进程终止的情况有三种:

  1. 代码运行完毕,结果正确。
  2. 代码运行完毕,结果不正确。
  3. 代码异常终止:本质上是接收到相应的信号。

常用的进程退出方法包括:

  • return
  • exit
  • _exit

父进程会关心子进程的运行情况。子进程在退出时会变成僵尸进程,需要父进程回收。

父进程期望获得子进程退出的信息,包括:

  • 子进程是否异常退出。
  • 如果异常,可以通过错误码查看错误信息。
  • 通过退出码了解进程的退出情况。

可以使用以下命令查看最后一次进程退出的退出码:

echo $?

我们可以打印每个错误码对应的错误信息:

int main() {
    for (int i = 0; i < 10; i++) {
        printf("错误码 %d 对应的错误信息是:%s\n", i, strerror(i));
    }
    return 0;
}

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

错误码为0时,表示代码正常执行完毕,因此主函数中的return通常是return 0。我们也可以设计一套自定义的错误码体系。

exit_exit都可以退出进程,但exit在退出前会执行额外的工作:

  • 执行通过atexiton_exit定义的清理函数。
  • 关闭所有打开的流,并将所有缓存数据写入。
  • 调用_exit

_exit是直接退出进程,不处理缓冲区。因此,通常推荐使用exit函数来退出进程。

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

三. 进程等待

进程等待是通过系统调用waitwaitpid来检测和回收子进程的状态。

为什么需要进程等待?

  • 子进程在退出时会变成僵尸进程,无法被杀死,需要通过进程等待来回收,解决内存泄漏问题。
  • 通过进程等待,父进程可以获得子进程的退出情况,了解子进程任务的完成情况。

父进程通过调用waitwaitpid来回收僵尸进程。

wait函数:

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

wait函数的头文件是

Teleporthq
Teleporthq

一体化AI网站生成器,能够快速设计和部署静态网站

下载

返回值:

  • 成功返回被等待进程的PID。
  • 失败返回-1。

参数:

  • 输出型参数,用于获取子进程的退出状态。如果不关心,可以设置为NULL。

wait等待任意一个子进程。

实例:

#include 
#include 

void Run() {
    int cnt = 5;
    while (cnt) {
        printf("我是一个子进程 pid: %d  ppid: %d\n", getpid(), getppid());
        cnt--;
        sleep(1);
    }
}

int main() {
    pid_t id = fork();
    if (id == 0) {
        // 子进程
        Run();
        exit(0);
    } else if (id > 0) {
        // 父进程
        int cnt = 10;
        while (cnt) {
            printf("我是一个父进程 pid: %d  ppid: %d\n", getpid(), getppid());
            cnt--;
            sleep(1);
        }
        pid_t ret = wait(NULL);
    } else {
        printf("出错\n");
    }
    return 0;
}

可以使用以下指令查看运行时进程的变化:

while :; do ps ajx | head -1 && ps ajx | grep testwait | grep -v grep; sleep 1; echo "------------------------"; done

waitpid函数:

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

waitpid函数有三个参数:

  • pidpid = -1等待任何一个子进程,与wait等效;pid > 0等待其进程ID与pid相等的子进程。
  • statusWIFEXITED(status)若为正常终止子进程返回的状态,则为真;WEXITSTATUS(status)WIFEXITED非零,提取子进程退出码。
  • optionsWNOHANGpid指定的子进程没有结束,则waitpid()函数返回0,不予以等待;若正常结束,则返回该子进程的ID。

status是一个输出型参数,类型为int,有32个比特位,可以视为位图。低7位表示终止信号,第8位表示core dump标志,第9位到第15位表示退出状态。

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

获取终止信号:status & 0x7f

获取退出码:(status >> 8) & 0xff

为什么要传一个输出型参数?因为进程之间具有独立性,不能使用全局变量代替。

等待的原理:

子进程在退出时,会将退出码和终止信号写入PCB的exit_codeexit_signal变量中。等待进程时,从子进程的PCB中读取这两个变量的值,并写入到输出型变量status中,这样父进程就可以知道子进程的退出信息。

实例:

int main() {
    pid_t id = fork();
    if (id == 0) {
        // 子进程
        int cnt = 5;
        while (cnt) {
            printf("我是一个子进程  pid: %d  ppid: %d\n", getpid(), getppid());
            cnt--;
            sleep(1);
        }
    } else if (id > 0) {
        // 父进程
        int status = 0;
        while (1) {  // 轮询
            pid_t ret = waitpid(-1, &status, WNOHANG);  // 非阻塞
            if (ret > 0) {
                printf("子进程退出,等待成功\n");
                break;
            } else if (ret == 0) {
                printf("你先等等,子进程还没有退出....\n");
                sleep(1);
            } else {
                printf("等待失败\n");
                break;
            }
        }
        return 0;
    }
}

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

四. 进程替换

在理解进程替换之前,我们先看看如何使用进程替换。操作系统提供了以下进程替换函数:

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

这些函数如果调用成功,则加载新的程序从启动代码开始执行,不再返回。如果调用失败,则返回-1。因此,exec函数只有失败的返回值,没有成功的返回值。

参数的含义:

  • l(list):表示参数采用列表形式。
  • v(vector):参数用数组形式。
  • p(path):有p自动搜索环境变量PATH
  • e(env):表示自己维护环境变量。

【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

232

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

437

2024.03.01

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

540

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 8.7万人学习

Node.js 教程
Node.js 教程

共57课时 | 9万人学习

CSS3 教程
CSS3 教程

共18课时 | 4.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号