Linux 第二十章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

return

exit()

_exit()

进程等待

什么是进程等待

为什么要进行等待

如何进行等待

在子进程运行期间,父进程有没有调用wait?在干嘛呢?

waitpid

验证一下,程序正常终止时,status低16位的高8位是退出码

验证一下,程序正常终止时,status低16位的高8位是退出码

验证一下,程序正常终止时,status低16位的高8位是退出码,低八位是退出信号

父进程如何得知子进程的退出信息呢?wait/waitpid(系统调用)​编辑

进行位运算太麻烦了,使用os自带函数验证status

创建多个子进程,通过waitpid等待子进程并回收资源

我们为什么不用全局变量获取子进程的退出信息?而用系统调用(WEXITSTATUS(status))

waitpid中的options


return

return 是用于从函数中返回值并结束函数的执行,而 exit() 是用于终止整个程序的执行。

在其他函数进行return,表示的是函数调用的结束,main的return表示的是进程的退出

exit() 和 _exit() 都是用于退出程序的函数,但它们有一些不同之处。

exit() 函数是 C 标准库中的函数,而 _exit() 函数是 POSIX 标准中定义的函数。

exit() 函数会执行一系列清理工作,例如关闭文件流、释放内存等,然后调用标准库函数 atexit() 注册的清理函数,最后终止程序。

_exit() 函数会立即终止进程,不会执行任何清理工作,也不会调用 atexit() 注册的函数。

在使用多线程的程序中,exit() 函数会先终止所有线程,然后执行清理工作,而 _exit() 函数则会直接终止进程,不会考虑其他线程。

因此,如果需要执行一些清理工作或者确保所有线程都正常终止,可以使用 exit() 函数;如果需要立即终止程序而不执行任何清理工作,可以使用 _exit() 函数。

exit()

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
        printf("you can sleep me!”);\\没有\n
        sleep(3);
        exit(1);
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
you can sleep me![BCH@hcss-ecs-6176 10_31]$ 

_exit()

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
        printf("you can sleep me!");
        sleep(3);
        _exit(1);
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
[BCH@hcss-ecs-6176 10_31]$ 

进程等待

之前讲过,子进程退出,父进程如果不管不顾,就可能造成僵尸进程的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

什么是进程等待

通过wait/waitpid的方式,让父进程(一般)对子进程进行资源回收的等待过程

为什么要进行等待

1)解决子进程僵尸问题带来的泄漏问题

2)父进程为什么要创建子进程?要让子进程来完成任务。子进程将任务完成的如何,父进程要不要知道呢?——需要通过进程等待的方式,获取子进程退出的信息——那两个数字(信号和退出码)——不是必须的,但是系统需要提供这样的基础功能!

如何进行等待

wait——先验证2个问题,将子进程Z->x(x是瞬时状态)

wait只能够等待任意一个子进程

将子进程和父进程同时跑5秒,5秒后子进程结束,父进程此时sleep5秒,可以观测出此时子进程的状态是Z状态,5秒后通过wait将子进程由Z变为X状态,系统就回收了资源,再过10秒父进程退出

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
        }


}
int main()
{
        pid_t id=fork();
        if(id==0)
        {
        //child
        Worker();
        exit(0);
        }
        else
        {
                sleep(10);
                //father
                pid_t rid=wait(NULL);
                if(rid==id)
                {
                        printf("wait sucess,pid:%d \n",getpid());
                }
                sleep(10);
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; echo "------------------------------------------------------"; done
PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 Z+    1000   0:00 [myprocess] <defunct>
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 Z+    1000   0:00 [myprocess] <defunct>
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 Z+    1000   0:00 [myprocess] <defunct>
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 Z+    1000   0:00 [myprocess] <defunct>
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
 2676  2677  2676 10461 pts/0     2676 Z+    1000   0:00 [myprocess] <defunct>
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
10461  2676  2676 10461 pts/0     2676 S+    1000   0:00 ./myprocess
------------------------------------------------------

在子进程运行期间,父进程有没有调用wait?在干嘛呢?

如果子进程没有退出,父进程必须在wait进行阻塞等待。直到子进程僵尸,wait自动回收,返回

一般而言,谁先运行不知道,但是最后一般都是父进程最后退出!

waitpid

waitpid() 是一个系统调用,用于等待指定进程的状态发生变化并获取相关信息。它的原型是:

#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);

pid 参数指定要等待的进程ID:
如果 pid > 0,则等待指定进程ID等于 pid 的子进程。
如果 pid == -1,则等待任意子进程。
如果 pid == 0,则等待和调用进程属于同一个进程组的任意子进程。
如果 pid < -1,则等待和进程组ID等于 pid 的任意子进程。

status 参数是一个整型指针,用于存储子进程的退出状态信息。

options 参数用于指定等待选项,常见的选项有:
    WNOHANG:如果没有子进程退出或状态发生改变,则立即返回,不阻塞当前进程。
    WUNTRACED:也等待已经停止的子进程状态改变。

waitpid() 函数会阻塞当前进程,直到指定的子进程之一退出或状态发生改变。如果指定了 status 参数,它将会被更新以反映子进程的退出状态信息。如果成功等待到子进程退出,返回值是子进程的进程ID;如果发生错误,返回值是 -1。

事例

BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
        }
}
int main()
{
        pid_t id=fork();

        //子进程
        if(id==0)
        {
        //child
        Worker();
        exit(10);
        }
        else
        {
                //father
                int status=0;//记录
                printf("wait before\n");
                pid_t rid=waitpid(id,&status,0);//传入status的地址
                printf("wait after\n");
                if(rid==id)
                {
                        printf("wait sucess,pid:%d ,status:%d \n",getpid(),status);
                }
                sleep(10);
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
wait before
I am child process,pid: 18911 ,ppid :18910,cnt:4
I am child process,pid: 18911 ,ppid :18910,cnt:3
I am child process,pid: 18911 ,ppid :18910,cnt:2
I am child process,pid: 18911 ,ppid :18910,cnt:1
I am child process,pid: 18911 ,ppid :18910,cnt:0
wait after
wait sucess,pid:18910 ,status:2560//status并不是子进程exit的10

status是一个整数,32bit,低16位

验证一下,程序正常终止时,status低16位的高8位是退出码

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
        }


}


int main()
{
        pid_t id=fork();
        if(id==0)
        {
            //child
            Worker();
            exit(10);//这里10是自己定义的,所以子进程的退出码为10时时正确的
        }
        else
        {
                //father
                int status=0;
                printf("wait before\n");
                pid_t rid=waitpid(id,&status,0);
                printf("wait after\n");
                if(rid==id)
                {
                        printf("wait sucess,pid:%d ,rid:%d,status:%d,exit sign:%d,exit code:%d \n",getpid(),rid,status,status&0x7F,(status>>8)&0xFF);
                }
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
wait before
I am child process,pid: 18357 ,ppid :18356,cnt:4
I am child process,pid: 18357 ,ppid :18356,cnt:3
I am child process,pid: 18357 ,ppid :18356,cnt:2
I am child process,pid: 18357 ,ppid :18356,cnt:1
I am child process,pid: 18357 ,ppid :18356,cnt:0
wait after
wait sucess,pid:18356 ,rid:18357,status:2560,exit sign:0,exit code:10

status&0x7F
0000 1010 0000 0000    :status低16位
0000 0000 0111 1111    :0x7F
0000 0000 0000  000    :status&0x7F

(status>>8)&0xFF
0000 1010 0000 0000    :status低16位
0000 0000 0000 1010    :status>>8
0000 0000 1111 1111    :0xFF
0000 0000 0000 1010    :(status>>8)&0xFF

验证一下,程序正常终止时,status低16位的高8位是退出码

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
        }
}



int main()
{
        pid_t id=fork();
        if(id==0)
        {
            //child
            Worker();
            exit(1);//这里1是自己定义的,所以子进程的退出码为1时错误的
        }
        else
        {
                //father
                int status=0;
                printf("wait before\n");
                pid_t rid=waitpid(id,&status,0);
                printf("wait after\n");
                if(rid==id)
                {
                        printf("wait sucess,pid:%d ,rid:%d,status:%d,exit sign:%d,exit code:%d \n",getpid(),rid,status,status&0x7F,(status>>8)&0xFF);
                }
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
wait before
I am child process,pid: 3504 ,ppid :3503,cnt:4
I am child process,pid: 3504 ,ppid :3503,cnt:3
I am child process,pid: 3504 ,ppid :3503,cnt:2
I am child process,pid: 3504 ,ppid :3503,cnt:1
I am child process,pid: 3504 ,ppid :3503,cnt:0
wait after
wait sucess,pid:3503 ,rid:3504,status:256,exit sign:0,exit code:1

验证一下,程序正常终止时,status低16位的高8位是退出码,低八位是退出信号

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
                
                int a=10;
                a/=0;
        }
}

int main()
{
        pid_t id=fork();
        if(id==0)
        {
            //child
            Worker();
            exit(1);//这里1是自己定义的,所以子进程的退出码为1时错误的
        }
        else
        {
                //father
                int status=0;
                printf("wait before\n");
                pid_t rid=waitpid(id,&status,0);
                printf("wait after\n");
                if(rid==id)
                {
                        printf("wait sucess,pid:%d ,rid:%d,status:%d,exit sign:%d,exit code:%d \n",getpid(),rid,status,status&0x7F,(status>>8)&0xFF);
                }
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
wait before
I am child process,pid: 9439 ,ppid :9438,cnt:4
wait after
wait sucess,pid:9438 ,rid:9439,status:8,exit sign:8,exit code:0//退出信号为8

当一个进程异常了(收到信号),exit code(退出码)还有意义吗?

是没有意义的,所以退出码就不需要关心是多少了

有没有收到信号怎么判定?

只需要判断exit sign是否为0

父进程如何得知子进程的退出信息呢?wait/waitpid(系统调用)

进行位运算太麻烦了,使用os自带函数验证status

WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker()
{
        int cnt=5;
        while(cnt--)
        {
                printf("I am child process,pid: %d ,ppid :%d,cnt:%d\n",getpid(),getppid(),cnt);
                sleep(1);
        }
}
int main()
{
        pid_t id=fork();
        if(id==0)
        {
        //child
        Worker();
        exit(1);
        }
        else
        {
                //father
                int status=0;
                printf("wait before\n");
                //pid_t rid=wait(NULL);
                pid_t rid=waitpid(id,&status,0);
                printf("wait after\n");
                if(rid==id)
                {
                        //printf("wait sucess,pid:%d ,rid:%d,status:%d,exit sign:%d,exit code:%d \n",getpid(),rid,status,status&0x7F,(status>>8)&0xFF);
                        if(WIFEXITED(status))
                        {
                                printf("child process normal quit,exit code:%d\n",WEXITSTATUS(status));
                        }
                        else
                        {
                                printf("child process quit except!\n");
                        }
                }
                sleep(10);
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
wait before
I am child process,pid: 28038 ,ppid :28037,cnt:4
I am child process,pid: 28038 ,ppid :28037,cnt:3
I am child process,pid: 28038 ,ppid :28037,cnt:2
I am child process,pid: 28038 ,ppid :28037,cnt:1
I am child process,pid: 28038 ,ppid :28037,cnt:0
wait after
child process normal quit,exit code:1

创建多个子进程,通过waitpid等待子进程并回收资源

[BCH@hcss-ecs-6176 10_31]$ cat myprocess.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void Worker(int i)
{
        int cnt=10;
        while(cnt--)
        {
                printf("I am child:%d process,pid: %d ,ppid :%d,cnt:%d\n",i,getpid(),getppid(),cnt);
                sleep(1);
        }


}


const int n=10;//创建子进程的个数
int main()
{
        int i=0;
        for(i=0;i<n;i++)
        {
                pid_t id=fork();
                if(id==0)
                {
                        Worker(i);
                        exit(i);//每一个子进程的退出码,设置为创建时的编号
                }
        }
        //如何等待多个进程
        for(i=0;i<n;i++)
        {
                int status=0;
                pid_t rid=waitpid(-1,&status,0);//pid 等于-1时,表示任意一个子进程退出
                if(rid>0)
                {
                        printf("wait child : %d success,exit code:%d\n",rid,WEXITSTATUS(status));//查看每一个子进程的退出码              
                }
        }
        return 0;
}

[BCH@hcss-ecs-6176 10_31]$ ./myprocess
I am child:0 process,pid: 3729 ,ppid :3728,cnt:9//红色表示的是子进程的编号
I am child:2 process,pid: 3731 ,ppid :3728,cnt:9
I am child:4 process,pid: 3733 ,ppid :3728,cnt:9
I am child:5 process,pid: 3734 ,ppid :3728,cnt:9
I am child:1 process,pid: 3730 ,ppid :3728,cnt:9
I am child:3 process,pid: 3732 ,ppid :3728,cnt:9
I am child:7 process,pid: 3736 ,ppid :3728,cnt:9
I am child:6 process,pid: 3735 ,ppid :3728,cnt:9
I am child:8 process,pid: 3737 ,ppid :3728,cnt:9
I am child:9 process,pid: 3738 ,ppid :3728,cnt:9
I am child:0 process,pid: 3729 ,ppid :3728,cnt:8
I am child:2 process,pid: 3731 ,ppid :3728,cnt:8
I am child:4 process,pid: 3733 ,ppid :3728,cnt:8
I am child:5 process,pid: 3734 ,ppid :3728,cnt:8
I am child:1 process,pid: 3730 ,ppid :3728,cnt:8
I am child:3 process,pid: 3732 ,ppid :3728,cnt:8
I am child:7 process,pid: 3736 ,ppid :3728,cnt:8
I am child:6 process,pid: 3735 ,ppid :3728,cnt:8
I am child:8 process,pid: 3737 ,ppid :3728,cnt:8
I am child:9 process,pid: 3738 ,ppid :3728,cnt:8
I am child:0 process,pid: 3729 ,ppid :3728,cnt:7
I am child:2 process,pid: 3731 ,ppid :3728,cnt:7
I am child:4 process,pid: 3733 ,ppid :3728,cnt:7
I am child:5 process,pid: 3734 ,ppid :3728,cnt:7
I am child:1 process,pid: 3730 ,ppid :3728,cnt:7
I am child:3 process,pid: 3732 ,ppid :3728,cnt:7
I am child:7 process,pid: 3736 ,ppid :3728,cnt:7
I am child:8 process,pid: 3737 ,ppid :3728,cnt:7
I am child:6 process,pid: 3735 ,ppid :3728,cnt:7
I am child:9 process,pid: 3738 ,ppid :3728,cnt:7
I am child:0 process,pid: 3729 ,ppid :3728,cnt:6
I am child:2 process,pid: 3731 ,ppid :3728,cnt:6
I am child:4 process,pid: 3733 ,ppid :3728,cnt:6
I am child:5 process,pid: 3734 ,ppid :3728,cnt:6
I am child:1 process,pid: 3730 ,ppid :3728,cnt:6
I am child:3 process,pid: 3732 ,ppid :3728,cnt:6
I am child:7 process,pid: 3736 ,ppid :3728,cnt:6
I am child:8 process,pid: 3737 ,ppid :3728,cnt:6
I am child:6 process,pid: 3735 ,ppid :3728,cnt:6
I am child:9 process,pid: 3738 ,ppid :3728,cnt:6
I am child:0 process,pid: 3729 ,ppid :3728,cnt:5
I am child:2 process,pid: 3731 ,ppid :3728,cnt:5
I am child:4 process,pid: 3733 ,ppid :3728,cnt:5
I am child:5 process,pid: 3734 ,ppid :3728,cnt:5
I am child:1 process,pid: 3730 ,ppid :3728,cnt:5
I am child:7 process,pid: 3736 ,ppid :3728,cnt:5
I am child:3 process,pid: 3732 ,ppid :3728,cnt:5
I am child:8 process,pid: 3737 ,ppid :3728,cnt:5
I am child:6 process,pid: 3735 ,ppid :3728,cnt:5
I am child:9 process,pid: 3738 ,ppid :3728,cnt:5
I am child:0 process,pid: 3729 ,ppid :3728,cnt:4
I am child:2 process,pid: 3731 ,ppid :3728,cnt:4
I am child:4 process,pid: 3733 ,ppid :3728,cnt:4
I am child:5 process,pid: 3734 ,ppid :3728,cnt:4
I am child:1 process,pid: 3730 ,ppid :3728,cnt:4
I am child:7 process,pid: 3736 ,ppid :3728,cnt:4
I am child:3 process,pid: 3732 ,ppid :3728,cnt:4
I am child:6 process,pid: 3735 ,ppid :3728,cnt:4
I am child:8 process,pid: 3737 ,ppid :3728,cnt:4
I am child:9 process,pid: 3738 ,ppid :3728,cnt:4
I am child:0 process,pid: 3729 ,ppid :3728,cnt:3
I am child:2 process,pid: 3731 ,ppid :3728,cnt:3
I am child:4 process,pid: 3733 ,ppid :3728,cnt:3
I am child:5 process,pid: 3734 ,ppid :3728,cnt:3
I am child:1 process,pid: 3730 ,ppid :3728,cnt:3
I am child:7 process,pid: 3736 ,ppid :3728,cnt:3
I am child:6 process,pid: 3735 ,ppid :3728,cnt:3
I am child:3 process,pid: 3732 ,ppid :3728,cnt:3
I am child:8 process,pid: 3737 ,ppid :3728,cnt:3
I am child:9 process,pid: 3738 ,ppid :3728,cnt:3
I am child:0 process,pid: 3729 ,ppid :3728,cnt:2
I am child:2 process,pid: 3731 ,ppid :3728,cnt:2
I am child:4 process,pid: 3733 ,ppid :3728,cnt:2
I am child:5 process,pid: 3734 ,ppid :3728,cnt:2
I am child:1 process,pid: 3730 ,ppid :3728,cnt:2
I am child:7 process,pid: 3736 ,ppid :3728,cnt:2
I am child:6 process,pid: 3735 ,ppid :3728,cnt:2
I am child:3 process,pid: 3732 ,ppid :3728,cnt:2
I am child:8 process,pid: 3737 ,ppid :3728,cnt:2
I am child:9 process,pid: 3738 ,ppid :3728,cnt:2
I am child:0 process,pid: 3729 ,ppid :3728,cnt:1
I am child:2 process,pid: 3731 ,ppid :3728,cnt:1
I am child:4 process,pid: 3733 ,ppid :3728,cnt:1
I am child:5 process,pid: 3734 ,ppid :3728,cnt:1
I am child:7 process,pid: 3736 ,ppid :3728,cnt:1
I am child:1 process,pid: 3730 ,ppid :3728,cnt:1
I am child:3 process,pid: 3732 ,ppid :3728,cnt:1
I am child:6 process,pid: 3735 ,ppid :3728,cnt:1
I am child:8 process,pid: 3737 ,ppid :3728,cnt:1
I am child:9 process,pid: 3738 ,ppid :3728,cnt:1
I am child:0 process,pid: 3729 ,ppid :3728,cnt:0
I am child:2 process,pid: 3731 ,ppid :3728,cnt:0
I am child:4 process,pid: 3733 ,ppid :3728,cnt:0
I am child:5 process,pid: 3734 ,ppid :3728,cnt:0
I am child:3 process,pid: 3732 ,ppid :3728,cnt:0
I am child:7 process,pid: 3736 ,ppid :3728,cnt:0
I am child:8 process,pid: 3737 ,ppid :3728,cnt:0
I am child:1 process,pid: 3730 ,ppid :3728,cnt:0
I am child:6 process,pid: 3735 ,ppid :3728,cnt:0
I am child:9 process,pid: 3738 ,ppid :3728,cnt:0
wait child : 3729 success,exit code:0
wait child : 3730 success,exit code:1
wait child : 3731 success,exit code:2
wait child : 3732 success,exit code:3
wait child : 3733 success,exit code:4
wait child : 3734 success,exit code:5
wait child : 3735 success,exit code:6
wait child : 3736 success,exit code:7
wait child : 3737 success,exit code:8
wait child : 3738 success,exit code:9

可以发现子进程并不是按照创建的顺序被调度的

我们为什么不用全局变量获取子进程的退出信息?而用系统调用(WEXITSTATUS(status))

进程具有独立性,父进程无法直接获得子进程的退出信息

waitpid中的options

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/608175.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

提速25倍!MoonBit 新增后端支持,一周内成为热议焦点

MoonBit 新增 JS 后端支持 近期&#xff0c;MoonBit 迎来了重要更新&#xff1a;新增对 JavaScript 后端的支持&#xff0c;为用户带来了前所未有的性能提升。 MoonBit 诞生于2022年&#xff0c;是专为云计算及边缘计算设计的 AI 云原生编程语言及开发者平台。作为一门诞生于 …

Orange3数据可视化(小提琴图)

小提琴图 小提琴图和箱线图类似&#xff0c;用来显示数据分布和概率密度。结合了箱线图和密度图的特征&#xff0c;用来显示数据的分布形状。 输入 数据: 输入数据集 输出 选中的数据: 从图中选中的实例 数据: 增加了一列&#xff0c;显示数据点是否被选中 …

STM32--4G DTU 及 阿里云

模块概述 ATK-IDM750C/IDM751C 是正点原子(ALIENTEK)团队开发的一款高性能 4G Cat1 DTU 产品&#xff0c; 支持移动 4G、联通 4G 和电信 4G 手机卡。它以高速率、低延迟和无线数传作为核心功能&#xff0c; 可快速解决应用场景下的无线数传方案。 它支持 TCP/UDP/HTTP/MQTT/DN…

酷开科技AI技术支持,酷开系统根据你的喜好量身定制节目

在当今数字化时代&#xff0c;个性化推荐已成为提升消费者体验的关键因素。酷开科技的智慧AI&#xff0c;为消费者提供了精彩的内容推荐服务&#xff0c;更大地丰富了消费者的娱乐生活。 酷开系统中的AI推荐引擎通过学习消费者的观看习惯和偏好&#xff0c;能够快速识别其兴趣…

Python进行excel处理-01

最近干采购&#xff0c;每个月要对供应商的对账单&#xff0c;对对应的采购订单号和物料编号的价格和数量&#xff0c;是不是和物料管控总表里面的价格数量是不是一致&#xff0c;于是写了一个代码。 从总表里面找到&#xff0c;对账单里对应采购订单和物料编码的数据&#xf…

ACPI高级配置和电源接口规范概览

安全之安全(security)博客目录导读 目录 1 Overview 背景 What is ACPI ACPI初始化 2 Introduction 主要目标 Power management 基本原理 ACPI框架 Target Audience 3 术语 通用术语General ACPI Terminology 全局系统状态定义Global System State Definitions 设…

【全开源】JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码

一、特色功能 护理服务功能&#xff1a; 基础护理&#xff1a;提供日常生活中的基础护理服务&#xff0c;如洗漱、穿衣、进食等&#xff0c;用户可以通过小程序预约&#xff0c;由专业的护理人员上门提供服务。康复护理&#xff1a;针对术后康复或慢性病康复的老年人&#xf…

Ansys Mechanical|内嵌nCode疲劳仿真工具

疲劳分析是分析结构受到周期性载荷作用下&#xff0c;结构应力远小于强度极限情况&#xff0c;甚至结构应力比弹性极限还低的情况下就可能发生破坏的情况。Ansys nCode是国际著名的疲劳耐久性仿真分析软件&#xff0c;其多个版本以前已经可以和Ansys Mechanical进行无缝以进行联…

如果你这样使用电路仿真软件,你就无敌了!

在电子设计领域&#xff0c;电路仿真软件如同一把锋利的宝剑&#xff0c;掌握它&#xff0c;你就能在复杂的电子世界中游刃有余。今天&#xff0c;就让我们一起探讨如何高效利用电路仿真软件&#xff0c;让你在电子设计领域所向披靡&#xff01; 一、熟悉软件界面与基础操作 …

Java文件与IO操作

1. 文件与IO操作 1.1 文件 什么是文件: 文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件.excel文件...都是文件。它既可以保存一张图片,也可以保持视频,声音.… 1.1.1 文件流: 1.1.2 常用的文件操作: 创建文件对象相关构造器和方法: 案例&a…

从C向C++16——常见容器2

一.stack容器 1.stack理解 概念&#xff1a; stack是一种先进后出的数据结构&#xff0c;它只有一个出口。 它在C中也叫栈&#xff0c;类似于我们在《数据结构和算法》里面的栈&#xff0c;只不过在C中把其封装成库&#xff0c;我们可以直接使用。 注意&#xff1a;栈中只有…

【因特网中自治系统内部的路由选择,RIP 进程处理 OSPFOSPF(Open Shortest Path First)最短路径优先协议】

文章目录 因特网中自治系统内部的路由选择RIP&#xff08;Routing Information Protocol&#xff09;内部网关协议RIP通告&#xff08;advertisements&#xff09;RIP: 链路失效和恢复RIP 进程处理OSPF(Open Shortest Path First)最短路径优先协议OSPF “高级” 特性(在RIP中的…

C++ 继承篇

面向对象语言的三大特性&#xff1a;封装&#xff0c;继承和多态 根据目前学到的知识&#xff0c;对于封装的理解&#xff0c;大致有两层&#xff1a; 将数据和方法封装&#xff0c;不想让外面看到用private/protected修饰&#xff0c;想让外面看到用public修饰类型的行为不满…

Mybatis 源码分析

《黑马架构师_源码系列-主流框架&中间件》-- MyBatis &#xff08;讲师&#xff1a;子慕&#xff09; * 手写持久层框架-仿写mybatis * Mybatis架构设计&主要组件 * Mybatis如何完成的初始化? * Mybatis如何完成的sql解析及执行? * Mybatis如何设置的参数? * Mybat…

容器集群管理系统Kubernetes(K8S)

目录 一、前言 1.1什么是云原生&#xff1f; 1.2云要素的四要素&#xff1f; 1.2.1微服务 1.2.2容器化 1.2.3DevOps 1.2.4持续交付 1.3云平台有哪些&#xff1f; 1.4SRE 二、Kubernetes 概述 2.1K8S 是什么 2.2K8S作用 2.3K8S版本 2.4为什么要用 K8S 2.5K8S 的特…

【论文阅读】Spectral–Spatial Attention Network for Hyperspectral Image Classification

Spectral–Spatial Attention Network for Hyperspectral Image Classification 论文地址摘要&#xff1a;1. 简介1.1.动机1.2.贡献 2. 相关作品2.1.双向递归网络RNN2.2.CNN2.3. Attention Mechanism 3. 方法3.1 Attention with RNN for Spectral Classification3.2&#xff0e…

【镜像仿真篇】磁盘镜像仿真常见错误

【镜像仿真篇】磁盘镜像仿真常见错误 记系统镜像仿真常见错误集—【蘇小沐】 1、实验环境 2023AFS39.E01&#xff08;Windows11系统镜像&#xff09;Arsenal Image Mounter&#xff0c;[v3.10.262]‍Vmware Workstation 17 Pro&#xff0c;[v17.5.1]Windows 11 专业工作站版…

单片机——直流电机

1 .关于4线直流电机 两根12v供电线&#xff0c;通入12v&#xff0c;风扇以最高转速工作。 一根测速线&#xff0c;电机工作时输出测速信号&#xff0c;提供转速反馈。一根PWM控制信号线&#xff0c;电机工作时控制器输入PWM控制信号&#xff0c;以控制风扇转速(通常为占空比可…

性能测试瓶颈:CPU 问题的深度分析和调优!

性能测试是评估系统、应用程序或服务的性能和稳定性的过程。在进行性能测试时&#xff0c;我们经常会发现一些瓶颈&#xff0c;其中之一就是与CPU相关的问题。CPU是计算机系统中最重要的组件之一&#xff0c;对系统的整体性能起着至关重要的作用。本文将从零开始详细介绍如何分…