Linux 第二十章

news2024/9/22 15:35:39

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

❤️‍🔥专栏系列:线性代数,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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Transformer详解:从放弃到入门(一)

Transformer由论文《Attention is All You Need》提出&#xff0c;是一种用于自然语言处理&#xff08;NLP&#xff09;和其他序列到序列&#xff08;sequence-to-sequence&#xff09;任务的深度学习模型架构&#xff0c;在自然语言处理领域获得了巨大的成功&#xff0c;在这个…

自动化运维工具---Ansible

一 Puppet Puppet是历史悠久的运维工具之一。它是一种基础架构即代码(laC)工具&#xff0c;使用户可以定义其基础 架构所需的状态&#xff0c;并使系统自动化以实现相同状态。 Puppet可监视用户的所有系统&#xff0c;并防止任何偏离已定义状态的情况。从简单的工作流程自动…

数据仓库基础理论(学习笔记)

数据仓库基础理论 1.数据仓库概念 2.数据仓库为何而来 3.数据仓库主要特征 4.OLTP、OLAP系统 5.数据仓库与数据库的区别 6.数据仓库与数据集市的区别 7.数据仓库分层架构 7.1为什么要分层&#xff1f; 8.ETL、ELT

NFS共享存储服务配置实践

一、NFS 1.NFS定义 NFS&#xff08;Network File System&#xff09;网络文件服务&#xff1a;基于TCP/IP传输的网络文件系统协议&#xff0c;NFS服务的实现依赖于RPC&#xff08;Remote Process Call&#xff09;远端过程调用&#xff1a;通过使用NFS协议&#xff0c;客户机…

ICode国际青少年编程竞赛- Python-1级训练场-变量入门

ICode国际青少年编程竞赛- Python-1级训练场-变量入门 1、 a 4 Dev.turnRight() Dev.step(a)2、 a 4 Spaceship.step(a) Dev.step(a)3、 a 4 Dev.step(a) Dev.turnLeft() Dev.step(a)4、 a 5 Dev.step(a) Spaceship.step(a) Dev.step(a)5、 a 3 Dev.step(a) Dev.tur…

C语言写的LLM训练

特斯拉前 AI 总监、OpenAI 创始团队成员 Andrej Karpathy 用 C 代码完成了 GPT-2 大模型训练过程&#xff1a;karpathy/llm.c: LLM training in simple, raw C/CUDA (github.com) 下载源码 git clone --recursive https://github.com/karpathy/llm.c.git下载模型 从HF-Mirro…

Burp和Proxifier抓包微信小程序

1、Burp设置代理 2、浏览器下载证书 3、安装证书 4、Proxifier设置代理 5、Proxifier设置Proxification Rule 6、Burp查看抓包数据 打开一个小程序&#xff0c;可以看到WeChatAppEx的流量先经过Proxifier&#xff0c;再经过127.0.0.1:8080到Burp

基于现有语言大模型,定制“人人AI气象”公众号天气助手

最近&#xff0c;月之暗面的Kimi大模型非常受欢迎&#xff0c;尝试用了moonshot(128K)基座模型&#xff0c;通过调用各种公开渠道的API&#xff0c;简易实现了一个天气助手&#xff0c;可以回答天气相关的基础概念、原理、应用等方面的问题&#xff0c;同时也可调用多个插件获取…

音频可视化:原生音频API为前端带来的全新可能!

音频API是一组提供给网页开发者的接口&#xff0c;允许他们直接在浏览器中处理音频内容。这些API使得在不依赖任何外部插件的情况下操作和控制音频成为可能。 Web Audio API 可以进行音频的播放、处理、合成以及分析等操作。借助于这些工具&#xff0c;开发者可以实现自定义的音…

MoonBit 开源之夏重磅来袭!12000元奖金等你来拿!

宣讲视频 MoonBit 开源之夏宣讲视频 关于我们 开源之夏 「开源之夏 (OSPP)」是中科院软件所「开源软件供应链点亮计划」指导下的系列暑期活动&#xff0c;旨在鼓励在校学生积极参与开源软件的开发维护&#xff0c;培养和发掘更多优秀的开发者&#xff0c;促进优秀开源软件社区…

JavaScript中Math函数与舍入

立方根 console.log(Math.sqrt(25)); //数学方式25平方根 console.log(25 ** (1 / 2)); //25的0.5次方 console.log(8 ** (1 / 3)); //8的1/3次方计算最大最小值 console.log(Math.max(1, 5, 88, 22, 132)); //返回最大值 console.log(Math.max(1, 5, 88, 22, 132)); //…

【C语言】高质量选择题

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目八&#xff1a; 题目九&#xff1a; 题目十&#xff1a; 题目十一&#xff1a; 题目十二&#xff1a; 题目十…

快捷回复软件让你告别回复慢

可能自己是个客服的原因&#xff0c;一连几天大数据给我推了一个叫“客服宝聊天助手”的软件。用了几天真心觉得好用&#xff0c;能解决我回客户很慢的困扰。如果大家对快捷回复软件感兴趣&#xff0c;可以接着了解哦&#xff01; 一、减少复制粘贴 传统的客服工作中&#xff…

75.网络游戏逆向分析与漏洞攻防-角色与怪物信息的更新-伪造服务端更新属性消息欺骗客户端

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

【查找算法】之二分查找

一、算法介绍 二分查找&#xff0c;也称为折半查找&#xff0c;是一种在有序数组中查找特定元素的高效算法。对于包含 n 个元素的有序数组&#xff0c;二分查找的步骤如下&#xff1a; 确定搜索范围&#xff1a;首先&#xff0c;将要查找的元素与数组中间的元素进行比较。如果…

基于 Linux 自建怀旧游戏之 - 80 款 H5 精品小游戏合集

1&#xff09;简介 最近又找到了一款宝藏游戏资源分享给大家&#xff0c;包含 80 款 H5 精品小游戏&#xff0c;都是非常有趣味耐玩的游戏&#xff0c;比如 植物大战僵尸、捕鱼达人、贪吃蛇、俄罗斯方块、斗地主、坦克大战、双人五子棋、中国象棋 等等超级好玩的 H5 小游戏&…

Chrome浏览器命令行妙用:使你的网上冲浪更加无障碍

引言 在当今数字化时代&#xff0c;网络浏览器已成为我们日常生活中不可或缺的工具之一。对于许多人来说&#xff0c;Google Chrome浏览器是首选&#xff0c;不仅因为它的普及度&#xff0c;更因为它提供的丰富功能和高度的可定制性。在Chrome的众多特性中&#xff0c;命令行功…

景源畅信数字:抖音怎么挂橱窗商品?

抖音作为一款短视频分享平台&#xff0c;近年来逐渐融入了电商功能&#xff0c;其中“橱窗”就是商家或个人展示和销售商品的一个重要工具。如何在抖音上挂橱窗商品&#xff0c;成为了众多商家关注的焦点。 一、确保账号资质&#xff1a;在抖音上挂橱窗商品前&#xff0c;需要确…

iOS ------ JSONModel源码

一&#xff0c;JSONModel的基本使用 1&#xff0c;基本使用方法 - (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err; - (instancetype)initWithData:(NSData *)data error:(NSError **)error; - (instancetype)initWithString:(NSString *)str…

yolov5-pytorch-Ultralytics训练+预测+报错处理记录

一、前言 玩一段时间大模型&#xff0c;也该回归一下图像识别。本项目用于记录使用基于Ultralytics的yolov5进行目标检测测试。为什么用Ultralytics呢&#xff1f;答案有3 1、其良好的生态&#xff0c;方便我们部署到其它语言和设备上。因此本次测试结论&#xff1a;大坑没有&…