• Linux--进程--进程-父进程退出


    1.进程退出函数

    进程退出分为正常退出&异常退出

    正常退出:

            1、main函数调用return

            2、进程调用exit(),标准c库

            3、进程调用_exit()或者_Exit(),属于系统调用

            补充

            1、进程最后一个线程返回

            2、最后一个线程调用pthread_exit

    异常退出:

            1、调用abort,等于放弃当前进程

            2、当进程收到某些信号时,如ctrl+c

            3、最后一个线程对取消(cancellatio)请求做出响应
    exit函数:

    1. #include
    2. void exit(int status);
    3. void _Exit(int status);
    4. #include
    5. void _exit(int status);

    代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. int main()
    6. {
    7. pid_t pid;
    8. int cnt=0;
    9. pid=vfork();
    10. if(pid>0){
    11. while(1){
    12. printf("cnt=%d\n",cnt);
    13. printf("this is father print%d\n",getpid());
    14. sleep(1);
    15. }
    16. }
    17. if(pid==0){
    18. while(1){
    19. printf("this is child print,pid=%d\n",getpid());
    20. sleep(1);
    21. cnt++;
    22. if(cnt==3){
    23. //break;
    24. //exit(0);
    25. //_exit(0);
    26. _Exit(0);
    27. }
    28. }
    29. }
    30. return 0;
    31. }

    进程退出调用(exit\_exit\_Exit)函数,尽量调用exit函数,调用后会对子进程调用的数据进行一下冲刷处理再退出,_exit\_Exit是直接退出。

    结果:

    2.父子进程退出

    僵尸进程:子进程退出状态不被收集,变成僵尸进程(僵死进程)Z+状态

    孤儿进程:父进程退出,子进程还在运行;此时父进程会被init进程吸收,其pid=1;Linux系统作用

    调用wait()阻塞函数:

    1. #include
    2. #include
    3. pid_t wait(int *status);

    作用:等待子进程完成或者退出,之后通常运行父进程

     进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

    参数:

    参数status(注意此为指针)用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像这样:pid = wait(NULL);
    返回值:

    如果成功,wait会返回被收集的子进程的进程ID;
    如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
    多数使用wait函数
     

    2.waitpid函数:  wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞。

    1. #include
    2. #include
    3. pid_t waitpid(pid_t pid, int *status, int options)

    参数

    status:与wait的一样用法。


    pid:从参数的名字pid和类型pid_t中就可以看出,这里需要的是一个进程ID。但当pid取不同的值时,在这里有不同的意义。

    对于waitpid函数中pid参数作用解释如下:

            pid=-1        等待任一子进程,&wait等效

            pid>0        等待其进程ID与pid相等的子进程

            pid==0        等待其组ID等于调用进程组ID的任一子进程

            pid<-1        等待其组ID等于pid绝对值的任一子进程
     


    options:提供了一些额外的选项来控制waitpid,目前在Linux中只支持:WNOHANG和WUNTRACED两个选项,这是两个常数,可以用"|"运算符把它们连接起来使用;比如ret=waitpid(-1,NULL,WNOHANG | WUNTRACED); 如果我们不想使用它们,也可以把options设为0,如ret=waitpid(-1,NULL,0); 如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。而WUNTRACED参数,由于涉及到一些跟踪调试方面的知识,加之极少用到,可以自行查阅相关材料。

    返回值:waitpid的返回值比wait稍微复杂一些,一共有三种情况:
    ① 当正常返回的时候,waitpid返回收集到的子进程的进程ID;
    ② 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;  一般options写WNOHANG    
    ③ 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD;

    waitpid提供了wait函数不能实现的3个功能:

    ① waitpid等待特定的子进程, 而wait则返回任一终止状态的子进程;
    ② waitpid提供了一个wait的非阻塞版本;
    ③ waitpid支持作业控制。用于检查 wait() 和 waitpid() 两个函数返回终止状态的宏: 这两个函数返回的子进程状态都保存在status指针中,用以下3个宏可以检查该状态:
    WIFEXITED(status): 若为正常终止, 则为真。此时可执行 WEXITSTATUS(status): 取子进程传送给exit或_exit参数的低8位.
    WIFSIGNALED(status): 若为异常终止, 则为真。此时可执行 WTERMSIG(status): 取使子进程终止的信号编号.
    WIFSTOPPED(status): 若为当前暂停子进程, 则为真。此时可执行 WSTOPSIG(status): 取使子进程暂停的信号编号


    代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. int main()
    6. {
    7. pid_t pid;
    8. int cnt=0;
    9. int status=10;
    10. pid=fork();
    11. if(pid>0){
    12. // wait(&status);
    13. waitpid(pid,&status,WNOHANG);
    14. printf("child quit,child status=%d\n",WEXITSTATUS(status));
    15. while(1){
    16. printf("cnt=%d\n",cnt);
    17. printf("this is father print%d\n",getpid());
    18. sleep(1);
    19. }
    20. }
    21. if(pid==0){
    22. while(1){
    23. printf("this is child print,pid=%d\n",getpid());
    24. sleep(1);
    25. cnt++;
    26. if(cnt==3){
    27. //break;
    28. //exit(0);
    29. //_exit(0);
    30. exit(3);
    31. }
    32. }
    33. }
    34. return 0;
    35. }

    运行:

    子进程、父进程同时运行3次,子进程退出,父进程运行;非阻塞下,子进程变成僵尸进程

  • 相关阅读:
    B+树索引(11)之索引挑选(上)
    【树莓派开发日记1】1.3k预算的树莓派+显示屏+键鼠的选型与拆箱物理安装
    细说从0开始挖掘cms-
    Jsoup | Document | HTML解析器
    Bootstrap中固定某一个元素不随滚动条滚动
    【OpenCV】使用OpenCV调用手机摄像头
    【React Router v6】路由组件传参params/search/state(router v6)
    C++-CMake指令:include指令【.cmake文件/MACRO宏/function函数】
    Ubuntu(20.04 LTS)更换镜像源
    三次握手四次挥手
  • 原文地址:https://blog.csdn.net/Herry_z/article/details/132767053