一,进程号获取函数

1.getpid函数

所需头文件

#include <sys/types.h>

#include <unistd.h>

原型 pid_t getpid(void)
功能 获取当前进程自身的进程号
参数
返回值 返回当前进程自身的进程号

代码示例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,const char *argv[])
{
    pid_t pid = fork();
if(pid == -1)
{
    perror("创建子进程失败\n");
    return -1;
}
else if(pid == 0)
{
    printf("子进程的pid:%d\n",getpid());
}else if(pid > 0)
{
    printf("父进程的pid:%d\n",getpid());
}
while(1);
    return 0;
}

2.getppid函数

所需头文件

#include <sys/types.h>

#include <unistd.h>

原型 pid_t getppid(void)
功能 获取当前进程的父进程的进程号
参数
返回值 返回当前进程的父进程的进程号

代码示例:

// 获取父进程号
// 函数:getppid()
// 参数:无
// 返回值:父进程的pid
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,const char *argv[])
{
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("创建子进程失败\n");
        return -1;
    }
    else if(pid == 0)
    {
        printf("我是子进程的,我的父进程号为:%d\n",getppid());
    }else if(pid > 0)
    {
        printf("我是父进程的,我的父进程号为:%d\n",getppid());
    }
    return 0;
}

二,进程退出函数

1.exit函数(是一个库函数,不是一个系统调用)

所需头文件 #include <stdlib.h>
原型 void exit(int status)
功能

正常终止进程,且status & 0377 (按位与运算后的值)会被返回给父进程

C标准规定了两个常量 EXIT_SUCCESS和EXIT_FAILURE,它们可被传递给exit()函数

参数 status 退出状态值
返回值

代码示例:

include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
#if 0
    printf("hello");
    //exit是一个库函数.不是一个系统调用
    //所以在查看该函数的时候,是man 3 exit
    //exit(0);  //exit在正常退出之前.会做一系列的清理工作
    exit(EXIT_SUCCESS);  //exit(0)等价于exit(EXIT_SUCCESS)
    while(1){}
#else
    // 创建子进程
    pid_t pid = fork();
    if (pid == -1)
    {
        perror("创建子进程失败");
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        while (1)
        {
            printf("hello\n");
            sleep(1);
            exit(EXIT_SUCCESS);  //exit(0):正常退出
        }
    }
    else if (pid > 0)
    {
        // 父进程
        while (1)
        {
            printf("world\n");
            sleep(1);
        }
    }
#endif
    return 0;
}

2._exit函数(它是一个系统调用,不是库函数)

所需头文件 #include <unistd.h>
原型 void_exit(int status);
功能

立即终止进程,且status & 0377(按位与运算后的值)会被返回给父进程

C标准库为exit函数规定了EXIT_SUCCESS和EXIT_FAILURE常量,由于其值通常为0和1;

也可传递给_exit兼容使用,但_exit本身是系统调用,不依赖这些宏;

参数 status 退出状态值
返回值

代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
#if 0
    printf("hello");
    //_exit不是一个库函数.是一个系统调用
    //所以在查看该函数的时候,是man 2 _exit
    //_exit(0);  //_exit在正常退出之前.不会做一系列的清理工作
    _exit(EXIT_SUCCESS);  //_exit(0)等价于_exit(EXIT_SUCCESS)
    while(1){}
#else
    // 创建子进程
    pid_t pid = fork();
    if (pid == -1)
    {
        perror("创建子进程失败");
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        while (1)
        {
            printf("hello\n");
            sleep(1);
            _exit(EXIT_SUCCESS);  //_ exit(0):正常退出
        }
    }
    else if (pid > 0)
    {
        // 父进程
        while (1)
        {
            printf("world\n");
            sleep(1);
        }
    }
#endif
    return 0;
}

三,资源回收函数

1.wait函数

所需头文件

#include <sys/types.h>

#include <sys/wait.h>

原型 pid_t wait(int *wstatus);
功能

父进程阻塞,等待任意一个子进程结束;若没有子进程结束,wait会一直等待;

当有子进程终止时,它会回收该子进程的资源,并通过wstatus获取子进程的退出状态值

参数 wstatus

用于存储子进程的退出状态值的内存空间首地址

wstatus若为空(NULL),表示忽略子进程退出时的状态

wstatus若不为空,表示将子进程退出状态写入该指针指向的内存,供父进程后序用宏解析

返回值

成功返回终止子进程的PID

如果调用进程没有子进程或者是调用出错,返回-1,同时会设置errno来指示错误原因

代码示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,const char *argv[])
{
    //fork 函数,创建子进程
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("创建子进程失败\n");
        return -1;
    }
    else if(pid == 0)
    {
        printf("我是子进程,我的进程id是%d\n",getpid());
        exit(EXIT_SUCCESS); //子进程正常退出
        //exit(1000); //子进程非正常退出,退出状态是一个非0值
    }

    else if(pid > 0)
    {
        int status = 0; //保存子进程的状态值
        //pid_t wait_ret =wait(NULL);//等待子进程的结束,不关注子进程的状态
        pid_t wait_ret = wait(&status);//等待子进程的结束,关注子进程的状态
        printf("我是父进程,我的进程id是%d\n",getpid());
        if(wait_ret == -1)
        {
            perror("没有子进程或者是调用失败");
            return -1;
        }
        printf("终止的子进程的pid是%d\n",wait_ret);
        //针对于status这个子进程的退出状态码
        //是需要进行宏解析的,这样的话才可以得到正确的退出状态码
        //printf("子进程的退出状态值是:%d\n",status);
        //进行宏解析
        if(WIFEXITED(status))
        {
            printf("子进程正常退出,退出状态是:%d\n",WEXITSTATUS(status));
        }
        else if(WIFSIGNALED(status))
        {
            printf("子进程非正常退出(子进程被信号终止),信号是:%d\n",WTERMSIG(status));
        }
    }
    return 0;
}

2.wait函数状态解析宏

子进程正常退出:

     WIFEXITED(wstatus):若子进程是正常终止(调用exit()/_exit()或从 main()返回),则返回true;

      WEXITSTATUS(wstatus):仅当WIFEXITED为true时使用,返回子进程的退出状态码(即exit(n)中的n,取低8位);

子进程被信号终止:

       WIFSIGNALED(wstatus):若子进程是被信号终止(如SIGKILL等),则返回true;
       
WTERMSIG(wstatus):仅当WIFSIGNALED为true时使用,返回导致子进程终止的信号编号(如9对应SIGKILL);
       
WCOREDUMP(wstatus):仅当WIFSIGNALED为true时使用,若子进程终止时产生了核心转储文件,则返回true;

子进程被信号暂停:

       WIFSTOPPED(wstatus):若子进程是被信号暂停(仅在使用WUNTRACED标志或子进程被跟踪时有效),则返回true;
       
WSTOPSIG(wstatus):仅当WIFSTOPPED为true时使用,返回导致子进程暂停的信号编号(如19对应SIGSTOP);

子进程被恢复运行:
         
 WIFCONTINUED(wstatus):若子进程是通过SIGCONT信号恢复运行,则返回true;

3.waitpid函数

所需头文件

#include <sys/types.h>

#include <sys/wait.h>

原型 pid_twaitpid(pid_t pid,int *wstatus,int options);
功能

父进程等待子进程状态变化并获取其状态信息

允许父进程精准控制子进程的范围,可通过options调整等待行为(如阻塞 / 非阻塞)

参数 PID

指定要等待的子进程

<-1:等待任何进程组id于进程pid相等的绝对值的子进程

-1:等待任何子进程资源

0:等待任何进程组id与调用进程相同的进程

>0: 等待指定pid的子进程

wstatus

用于存储子进程的退出状态值的内存空间首地址

wstatus若为空(NULL),表示忽略子进程退出时的状态

wstatus若不为空,表示将子进程退出状态写入该指针指向的内存,供父进程后续用宏解析

options 标志位(默认模式是阻塞等待模式 options = 0)
返回值

成功返回终止子进程的PID

如果设置非阻塞且没有子进程退出,会返回0

如果调用进程没有子进程或者是调用出错,返回-1.同时会会设置reeno来指示错误原因

代码示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc ,const char*argv[])
{
    //创建函数
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("创建子进程失败\n");
        return -1;
    }
    else if(pid == 0)
    {
        //子进程
        while(1)
        {   
            printf("我是子进程\n");
            sleep(1);
            exit(EXIT_SUCCESS);// //子进程正常退出
        }
       
    }
    else if(pid > 0)
    {
        //父进程
        while(1)
        {
            printf("我是父进程\n");
            sleep(1);
            //等待子进程退出
            //第一个参数用于指定要等待的子进程,-1表示等待任意子进程退出
            //第二个参数用于指定字子进程的退出状态值的存放空间
            //NULL代表不关注子进程的退出状态值
            //第三个参数用于指定等待的方式,0:表示是阻塞等待方式
            //pid_t waitpid_ret = waitpid(-1,NULL,0);
            //关注子进程的退出状态值
            int st = 0;//保存子进程的退出状态值
            pid_t waitpid_ret = waitpid(-1,&st,0);
            if(waitpid_ret == -1)
            {
                perror("调用进程中没有子进程或者是调用出错\n");
                return -1;
            }
            else if(waitpid_ret == pid)
            {
                printf("父进程成功等待到了子进程的退出\n");
                //获取子进程的退出状态值
                if(WIFEXITED(st))//正常退出
                {
                    printf("子进程的退出状态值为%d\n",WEXITSTATUS(st));
                }
                else if(WIFSIGNALED(st))
                {
                    printf("子进程非正常退出(子进程被信号终止),信号是:%d\n",WTERMSIG(st));
                }
                
            }
            
        }
    }
    return 0;
}

4.options参数

选项常量 作用 具体行为 典型应用场景
0 实现阻塞等待 父进程暂停直到子进程状态变化

常规子进程同步等待(如批处理

WNOHANG 实现非阻塞等待

调用waitpid时,若指定子进程未退出,

函数立即返回0,父进程无需阻塞等待

父进程需轮询监控子进程状态

(入后台任务管理)

WUNTRACED 捕获子进程暂停状态

当子进程因信号(如SIGSTOP)停止运行时

waitpid返回该子进程PID

调试场景

需处理子进程暂停逻辑的程序

WCONTINUED 捕获子进程恢复运行状态

已停止的子进程通过SIGCONT信号恢复运行时

waitpid返回该子进程

需跟踪子进程完整声明周期

(暂停 - 恢复)场景

5.waitpid函数状态解析宏

子进程正常退出:

      WIFEXITED(wstatus): 若子进程是正常终止(调用exit()/_exit()或从main()返回),则返回true;
      WEXITSTATUS(wstatus): 仅当WIFEXITED为true时使用,返回子进程的退出状态码(即exit(n)中的n, 取低8位);

子进程被信号终止:

       WIFSIGNALED(wstatus): 若子进程是被信号终止(如SIGKILL等), 则返回true;
       WTERMSIG(wstatus): 仅当WIFSIGNALED为true时使用,返回导致子进程终止的信号编号(如9对应SIGKILL);
       WCOREDUMP(wstatus): 仅当WIFSIGNALED为true时使用,若子进程终止时产生了核心转储文件,则返回true;

子进程被信号暂停:

       WIFSTOPPED(wstatus): 若子进程是被信号暂停(仅在使用WUNTRACED标志或子进程被跟踪时有效),则返回true;
       WSTOPSIG(wstatus): 仅当WIFSTOPPED为true时使用,返回导致子进程暂停的信号编号(如19对应SIGSTOP);

子进程被恢复运行:

        WIFCONTINUED(wstatus): 若子进程是通过SIGCONT信号恢复运行,则返回true;

非阻塞模式:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc ,const char*argv[])
{
    //创建子进程  --完成:让父进程以非阻塞的方式等待子进程退出
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("创建子进程失败\n");
        return -1;
    }
    else if(pid == 0)
    {
        //子进程
        printf("我是子进程,我开始执行...\n");
        sleep(6);//延时6秒
        printf("我是子进程,我执行完毕...\n");
        exit(EXIT_SUCCESS);//子进程正常退出
       
    }
    else if(pid > 0)
    {
        
        //父进程
        printf("我是父进程,我开始执行...\n");
        while(1)
        {
        //父进程等待子进程的退出
        //父进程在非阻塞下等待子进程的退出
        //非阻塞模式本质上就是在循环轮询子进程的状态
        pid_t ret = waitpid(-1,NULL,WNOHANG);
        if(ret == -1)
        {
            perror("父进程等待子进程失败\n");
            return -1;
        }
        else if(ret == 0)//只有在非阻塞模式下才判断返回值为0的情况
        {
            printf("父进程非阻塞等待子进程,子进程没有退出\n");
            sleep(1);//休眠1秒再次进行检查
        }
        else if(ret > 0)
        {
            printf("父进程非阻塞等待子进程,子进程退出了\n");
            break;
        }
            
        }

    }
    return 0;

}

阻塞模式:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc ,const char*argv[])
{
    //创建函数
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("创建子进程失败\n");
        return -1;
    }
    else if(pid == 0)
    {
        //子进程
        while(1)
        {   
            printf("我是子进程\n");
            sleep(1);
            exit(EXIT_SUCCESS);// //子进程正常退出
        }
       
    }
    else if(pid > 0)
    {
        //父进程
        while(1)
        {
            printf("我是父进程\n");
            sleep(1);
            //等待子进程退出
            //第一个参数用于指定要等待的子进程,-1表示等待任意子进程退出
            //第二个参数用于指定字子进程的退出状态值的存放空间
            //NULL代表不关注子进程的退出状态值
            //第三个参数用于指定等待的方式,0:表示是阻塞等待方式
            //pid_t waitpid_ret = waitpid(-1,NULL,0);
            //关注子进程的退出状态值
            int st = 0;//保存子进程的退出状态值
            pid_t waitpid_ret = waitpid(-1,&st,0);
            if(waitpid_ret == -1)
            {
                perror("调用进程中没有子进程或者是调用出错\n");
                return -1;
            }
            else if(waitpid_ret == pid)
            {
                printf("父进程成功等待到了子进程的退出\n");
                //获取子进程的退出状态值
                if(WIFEXITED(st))//正常退出
                {
                    printf("子进程的退出状态值为%d\n",WEXITSTATUS(st));
                }
                else if(WIFSIGNALED(st))
                {
                    printf("子进程非正常退出(子进程被信号终止),信号是:%d\n",WTERMSIG(st));
                }
                
            }
            
        }
    }
    return 0;
}

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐