进程退出、孤儿进程、僵尸进程

在这里插入图片描述

exit()

/*
//Linux 系统库
#include <unistd.h>
void _exit(int status);
    -参数:
        status:进程退出时的状态信息,父进程挥手子进程的时候可以获取

// 标准C库
#include <stdlib.h>
void _Exit(int status);

*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

    printf("hello \n");
    
    printf("world111"); 

    exit(0);


    printf("world222 \n");

    return 0;
}

/*
carey@ubuntu:~/Linux/lesson12_exit$ ls
_exit.c  exit.c
carey@ubuntu:~/Linux/lesson12_exit$ gcc exit.c -o exit
carey@ubuntu:~/Linux/lesson12_exit$ ./exit 
hello 
world111carey@ubuntu:~/Linux/lesson12_exit$ 

-分析,因为exit是标准C库, 在执行exit的时候会先刷新IO缓冲 关闭文件描述符, 然后再
       调用_exit(), 所以会打印world111

*/

_exit()

/*
//Linux 系统库
#include <unistd.h>
void _exit(int status);
    -参数:
        status:进程退出时的状态信息,父进程挥手子进程的时候可以获取

// 标准C库
#include <stdlib.h>
void _Exit(int status);

*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

    printf("hello \n");
    
    printf("world111 \n"); //(1)
    //printf("world111"); (2)

    //exit(0);
    _exit(0);

    printf("world222 \n");

    return 0;
}

/*
//
(1):
carey@ubuntu:~/Linux/lesson12_exit$ gcc exit.c -o exit
carey@ubuntu:~/Linux/lesson12_exit$ ./exit 
hello 
world111 

-分析:因为printf是标准C库的函数,在IO时有缓冲区,\n之后会刷新缓冲区,所以会打印。

(2):
carey@ubuntu:~/Linux/lesson12_exit$ gcc exit.c -o exit
carey@ubuntu:~/Linux/lesson12_exit$ ./exit 
hello 

-分析:同上,没有\n所以数据没有刷新到系统, 所以没打印。

*/

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(){

    pid_t pid = fork();

    if(pid > 0){
        printf("PARENT : pid = %d, ppid = %d \n", getpid(), getppid());

    }else if(pid == 0){
        sleep(1);
        printf("child : pid = %d, ppid = %d \n", getpid(), getppid());
        

    }

    for(int i=0; i<3; i++){
        printf("i = %d, pid = %d, ppid = %d \n", i, getpid(), getppid());
    }



    return 0;
}
/*
carey@ubuntu:~/Linux/lesson12_exit$ gcc orphan.c -o orphan
carey@ubuntu:~/Linux/lesson12_exit$ 
carey@ubuntu:~/Linux/lesson12_exit$ ./orphan 
child : pid = 3422, ppid = 3421 
PARENT : pid = 3421, ppid = 2141 
i = 0, pid = 3421, ppid = 2141 
i = 1, pid = 3421, ppid = 2141 
i = 2, pid = 3421, ppid = 2141 
carey@ubuntu:~/Linux/lesson12_exit$ i = 0, pid = 3422, ppid = 1 
i = 1, pid = 3422, ppid = 1 
i = 2, pid = 3422, ppid = 1 


*/ 

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(){

    pid_t pid = fork();

    if(pid > 0){
        while(1){
            printf("PARENT : pid = %d, ppid = %d \n", getpid(), getppid());
            sleep(1);
        }
        

    }else if(pid == 0){
        printf("child : pid = %d, ppid = %d \n", getpid(), getppid());
    }

    for(int i=0; i<3; i++){
        printf("i = %d, pid = %d, ppid = %d \n", i, getpid(), getppid());
    }



    return 0;
}

/*
carey@ubuntu:~/Linux/lesson12_exit$ gcc Zomble.c -o zomble
carey@ubuntu:~/Linux/lesson12_exit$ ls
exit  _exit  _exit.c  exit.c  orphan  orphan.c  zomble  Zomble.c
carey@ubuntu:~/Linux/lesson12_exit$ ./zomble 
PARENT : pid = 3472, ppid = 2141 
child : pid = 3473, ppid = 3472 
i = 0, pid = 3473, ppid = 3472 
i = 1, pid = 3473, ppid = 3472 
i = 2, pid = 3473, ppid = 3472 
PARENT : pid = 3472, ppid = 2141 
PARENT : pid = 3472, ppid = 2141 
PARENT : pid = 3472, ppid = 2141 
PARENT : pid = 3472, ppid = 2141 

carey      3472  0.0  0.0   4512   724 pts/1    S+   18:32   0:00 ./zomble
carey      3473  0.0  0.0      0     0 pts/1    Z+   18:32   0:00 [zomble] <defunct>

*/

在这里插入图片描述
在这里插入图片描述

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

pid_t wait(int *wstatus);

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

-功能:
    等待任意一个子进程结束,如果任意一个子进程结束了,次函数会回收子进

-参数: int *wstatus
    进程退出时的状态信息,传入的是一个int类型的地址,传出参数。
    
-返回值:
    -成功:返回被回收的子进程的id
    -失败:-1(所以的子进程都结束,调用函数失败)

调用wait(),函数会被挂起(阻塞),直到他的一个子进程退出或者收到一个不能被忽略的信号时
才被唤醒(继续执行)。
如果没有子进程了,函数立刻返回(-1), 
如果子进程都结束了,函数立刻返回(-1),
并且资源都被回收。
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

#include <unistd.h>


int main(){

    pid_t pid;

    //创建5个子进程
    for(int i=0; i<5; i++){
        pid = fork();

        if(pid == 0){
            break; //子进程不再产生子进程
        }

    }

    if(pid > 0){
        //Parent
        while(1){
            printf("PARENT : pid = %d \n", getpid());

            int st;

            int ret = wait(&st);
            if(ret == -1){
                break;
            }
            if(WIFEXITED(st)){
                //是否正常退出
                printf("退出的状态码:%d \n", WEXITSTATUS(st));
            }
            if(WIFSIGNALED(st)){
                //是否异常终止
                printf("被哪个信号中止:%d \n", WTERMSIG(st));
            }

            printf("ret = %d \n", ret);

            sleep(1);
        }
            

    }else if(pid == 0){
        //child
        while(1){ //不循环为1, 有循环为2
            printf("child : pid = %d \n", getpid());
            sleep(2);

        }
        exit(0);
        
    }


    return 0;
}

# 1 运行结果
carey@ubuntu:~/Linux/lesson13_wait$ gcc wait.c -o wait
carey@ubuntu:~/Linux/lesson13_wait$ ./wait 
child : pid = 4306 
child : pid = 4307 
child : pid = 4309 
child : pid = 4308 
child : pid = 4310 
PARENT : pid = 4305 
退出的状态码:0 
ret = 4306 
PARENT : pid = 4305 
退出的状态码:0 
ret = 4307 
PARENT : pid = 4305 
退出的状态码:0 
ret = 4308 
PARENT : pid = 4305 
退出的状态码:0 
ret = 4309 
PARENT : pid = 4305 
退出的状态码:0 
ret = 4310 
PARENT : pid = 4305 

#2 运行结果
carey@ubuntu:~/Linux/lesson13_wait$ gcc wait.c -o wait
carey@ubuntu:~/Linux/lesson13_wait$ ./wait 
child : pid = 4330 
child : pid = 4329 
child : pid = 4332 
PARENT : pid = 4328 
child : pid = 4333 
child : pid = 4331 
child : pid = 4330
...

# 另开窗口 杀死进程
carey@ubuntu:~/Linux$ kill -9 4329
carey@ubuntu:~/Linux$ kill -9 4330
carey@ubuntu:~/Linux$ kill -9 4331
carey@ubuntu:~/Linux$ kill -9 4332
carey@ubuntu:~/Linux$ kill -9 4333

#结果:
child : pid = 4330 
child : pid = 4333 
被哪个信号中止:9 
ret = 4330 
child : pid = 4331 
child : pid = 4332 
child : pid = 4333 
PARENT : pid = 4328 
child : pid = 4331 
child : pid = 4332 
child : pid = 4333 
被哪个信号中止:9 
ret = 4331 
PARENT : pid = 4328 
child : pid = 4332 
child : pid = 4333 
被哪个信号中止:9 
ret = 4332 
PARENT : pid = 4328 
child : pid = 4333 
被哪个信号中止:9 
ret = 4333 
PARENT : pid = 4328 
/*
#include <sys/types.h>
#include <sys/wait.h>


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

-功能:
    回收指定进程号的子进程,可以设置是否阻塞。


-参数: 
    -pid :
        -pid > 0 : 某个子进程的 pid
        -pid = 0 : 回收当前进程组的所有子进程                           其次
        -pid = -1: 回收所有的子进程,相当于wait()                       最常用
        -pid < -1: 某个进程组的组id的绝对值,回收指定进程组中的子进程
    -int *wstatus
        进程退出时的状态信息,传入的是一个int类型的地址,传出参数。

    
-返回值:
    >0: 返回被回收的子进程的id
    =0: options=WNOHANG, 表示还有子进程活着
    -1: 错误或者没有子进程

调用wait(),函数会被挂起(阻塞),直到他的一个子进程退出或者收到一个不能被忽略的信号时
才被唤醒(继续执行)。
如果没有子进程了,函数立刻返回(-1), 
如果子进程都结束了,函数立刻返回(-1),
并且资源都被回收。
*/

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

#include <unistd.h>


int main(){

    pid_t pid;

    //创建5个子进程
    for(int i=0; i<5; i++){
        pid = fork();

        if(pid == 0){
            break; //子进程不再产生子进程
        }

    }

    if(pid > 0){
        //Parent
        while(1){
            printf("PARENT : pid = %d \n", getpid());

            int st;

            int ret = waitpid(-1, &st, 0);
            if(ret == -1){
                break;
            }
            if(WIFEXITED(st)){
                //是否正常退出
                printf("退出的状态码:%d \n", WEXITSTATUS(st));
            }
            if(WIFSIGNALED(st)){
                //是否异常终止
                printf("被哪个信号中止:%d \n", WTERMSIG(st));
            }

            printf("ret = %d \n", ret);

            sleep(1);
        }
            

    }else if(pid == 0){
        //child
        while(1){
            printf("child : pid = %d \n", getpid());
            sleep(2);

        }
        exit(0);
        
    }


    return 0;
}


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值