zoukankan      html  css  js  c++  java
  • 【linux高级程序设计】(第八章)进程管理与程序开发 3

    回收进程用户空间资源

    仅调用退出函数的进程属于一个僵死进程,没有释放进程控制块PCB。

    void exit (int __status):退出进程。会以反序执行on_exit()和atexit()中注册的清理函数,刷新流缓冲区。执行成功没有返回值,参数status用来标识退出状态返回给父进程;否则返回-1。

    void _exit (int __status):不调用任何祖册函数和直接退出进程。此函数调用后不会返回,而是传递SIGCHLD信号给父进程,父进程可以通过wait函数获得子进程结束的状态。该函数不处理标准I/O缓冲区

    int atexit (void (*__func) (void)):告诉进程,在正常退出时执行注册的func函数。注册函数没有参数

    int on_exit (void (*__func) (int __status, void *__arg), void *__arg):告诉进程,在正常退出时执行注册的func函数。注册函数有参数,第一个参数为退出的状态,第二个参数为用户的输入信息。

    exit与return区别:

    (1)return退出当前函数,exit()退出当前进程。在main函数中return(0)和exit(0)完成一样的功能。

    (2)return仅从子函数中返回,并不退出进程。而exit()在子函数中会调用终止处理程序,关闭所有I/O流。

    #include<stdio.h>
    #include<unistd.h>
    #include<string.h>
    int test(void)
    {
        printf("a
    ");
        sleep(1);
        //exit(0);   //循环只执行一次
        return 0;   //死循环
    }
    
    int main(int argc, char * argv[])
    {
        int i = 0;
        i++;
        printf("i=%d
    ",i);
        while(1)
            test();
        return 0;
    }

    exit与_exit使用对比

    #include<stdlib.h>
    int main(int argc, char * argv[])
    {
        printf("output
    ");
        printf("content in buffer");   //注意没有回车,在缓冲区
        _exit(0);
    }

    _exit(0)只显示output

    #include<stdlib.h>
    int main(int argc, char * argv[])
    {
        printf("output
    ");
        printf("content in buffer");   //注意没有回车,在缓冲区
        exit(0);
    }

    exit(0)显示output和content in buffer

    on_exit使用例子:

    #include<stdlib.h>
    void test_exit(int status, void *arg)
    {
        printf("before exit()!
    ");
        printf("exit %d
    ", status);
        printf("arg=%s
    ",(char*)arg);
    }
    int main()
    {
        char *str="test";
        on_exit(test_exit,(void *)str);
        exit(4321);
    }

    回收内核空间资源

    进程PCB的释放,由当前进程的父进程完成的。父进程可以显示的调用wait()waitpid()函数来完成。

    __pid_t wait (__WAIT_STATUS __stat_loc):父进程阻塞式的等待该进程的任意一个子进程结束,回收子进程的内核进程资源。返回当前结束子进程的PID,退出状态存储在stat_loc中。

    #define WIFSIGNALED(status)  __WIFSIGNALED(__WAIT_INT(status)) :宏,用来判断进程是否是因为收到信号后而退出的。如果是宏值为1.

    #define WIFEXITED(status)   __WIFEXITED(__WAIT_INT(status)):宏,用来判断进程是否是正常退出的。如果是,宏值为1.

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<fcntl.h>
    #include<string.h>
    #include<stdlib.h>
    
    extern int errno;
    int main(int argc, char *argv[])
    {
        pid_t pid_one, pid_wait;
        int status;
        if((pid_one = fork()) == -1)
            perror("fork");
        if(pid_one == 0)
        {
            printf("my pid is %d
    ", getpid());
            sleep(20);
            exit(EXIT_SUCCESS);   //正常退出
        }
        else
        {
            pid_wait = wait(&status);   //等待子进程结束
            if(WIFEXITED(status))
                printf("wait on pid: %d, normal exit, return value is:%4x
    ",pid_wait, WEXITSTATUS(status));
            else if(WIFSIGNALED(status))
                printf("wait on pid:%d, recive signal, return value is:%4x
    ", pid_wait, WIFSIGNALED(status));
        }
        return 0;
    }

    __pid_t waitpid (__pid_t __pid, int * __stat_loc, int __options):等待指定子进程结束

      第一个参数为进程PID值。

        PID > 0 :表示等待进程的PID就是PID

        PID == -1 :表示等待任意子进程结束,相当于调用wait函数

        PID == 0 :表示等待与当前进程的进程组PGID一致的进程结束

        PID < -1 :表示等待进程组PGID是此值的绝对值的进程结束

      第二个参数为结束进程的结束状态。

      第三个参数为等待选项,可设置为

        0 :阻塞

        WNOHANG  1 :不阻塞等待          没有子进程退出将返回0, 否则返回子进程的PID。

        WUNTRACED 2 :报告状态信息

    孤儿进程与僵死进程

    孤儿进程:父进程先退出,导致子进程被init进程收养的进程为孤儿进程。即父进程更改为init,init进程负责在孤儿进程退出后回收他的内核空间资源。

    僵死进程:进程已经退出,但是父进程还没有回收其内核空间资源PCB

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    
    int main()
    {
        pid_t pid;
        if((pid = fork()) == -1)
            perror("fork");
        else if(pid == 0)
        {
            printf("child_pid pid = %d
    ", getpid());
        }
        sleep(3);
        system("ps");
        exit(0);
    }

    此时1184为僵死进程。

  • 相关阅读:
    从产品原型到交互设计的过渡——初学者心得
    谈什么是卡片式设计?
    vertical-align:middle的居中细节调整
    line-height:2和line-height:2em的区别,它们是有区别的
    css中!important的用法总结
    使用em为单位制作两列弹性布局
    如何动态修改下拉列表的默认选中项
    【转】深入浅出协议栈
    经典排序js实现
    js 数组的拷贝
  • 原文地址:https://www.cnblogs.com/dplearning/p/4679622.html
Copyright © 2011-2022 走看看