• 进程环境之进程终止


    有8种方式使进程终止(termination),其中5种为正常终止,它们是:

    (1)从main返回。

    (2)调用exit。

    (3)调用_exit或_Exit。

    (4)最后一个线程从其启动例程返回。

    (5)最后一个线程调用pthread_exit。

    异常终止有3种方式,它们是:

    (6)调用abort。

    (7)接到一个信号并终止。

    (8)最后一个线程对取消请求作出响应。

    启动例程是这样编写的,使得从main返回后立即调用exit函数。(关于启动例程:http://learn.akae.cn/media/ch19s02.html)。如果将启动例程以C代码形式表示(实际上该例程常常用汇编语言编写),则它调用main函数的形式可能是:

    exit( main( argc, argv ) );

    1、exit函数

    有三个函数用于正常终止一个程序:_exit和_Exit立即进入内核,exit则先执行一些清理处理(包括调用执行各终止处理程序,关闭所有标准I/O流等),然后进入内核。

    #include <stdlib.h>
    void exit( int status );
    void _Exit( int status );
    #include <unistd.h>
    void _exit( int status );

    exit函数总是执行一个标准I/O库的清理关闭操作:为所有打开流调用fclose函数。这会造成所有缓冲的输出数据都被冲洗(写到文件上)。

    三个exit函数都带一个整型参数,称为终止状态(或退出状态,exit status)。大多数UNIX shell都提供检查进程终止状态的方法。如果(a)若调用这些函数时不带终止状态,或(b)main执行了一个无返回值的return语句,或(c)main没有声明返回类型为整型,则该进程的终止状态是未定义的。但是,若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。

    main函数返回一整型值与用该值调用exit是等价的。于是在main函数中

    exit(0);   等价于    return(0);

    2、atexit函数

    按照ISO C规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。我们称这些函数为终止处理程序(exit handler),调用atexit函数来登记这些函数。

    #include <stdlib.h>
    int atexit( void (*func)(void) );
    返回值:若成功则返回0,若出错则返回非0值

    其中,atexit的参数是一个函数地址,当调用此函数时无需向它传递任何参数,也不期望它返回一个值。exit调用这些函数的顺序与它们登记时候的顺序相反。同一函数若登记多次,则也会被调用多次。

    根据ISO C和POSIX.1,exit首先调用各终止处理程序,然后按需要多次调用fclose,关闭所有打开流。POSIX.1扩展了ISO C标准,它指定如若程序调用exec函数族中的任一函数,则将清除所有已安装的终止处理程序。图7-1显示了一个C程序是如何启动的,以及它可以终止的各种方式。

    09181403-28ffb6e7cceb4e809f1336f6deb4eb31

    从上图我们可以总结出exit和_exit的区别如下图(详情请参考http://www.cnblogs.com/mickole/p/3186606.html):

    注意,内核使程序执行的唯一方法是调用一个exec函数。进程自愿终止的唯一方法是显式或隐式地(通过调用exit)调用_exit或_Exit。进程也可非自愿地由一个信号使其终止。

    程序清单7-2 终止处理程序实例

    [root@localhost apue]# cat prog7-2.c
    #include "apue.h"
    
    static void my_exit1(void);
    static void my_exit2(void);
    
    int
    main(void)
    {
            if(atexit(my_exit2) != 0)
                    err_sys("can't register my_exit2");
    
            if(atexit(my_exit1) != 0)
                    err_sys("can't register my_exit1");
    
            if(atexit(my_exit1) != 0)
                    err_sys("can't register my_exit1");
    
            printf("main is done
    ");
            return(0);
    }
    
    static void
    my_exit1(void)
    {
            printf("first exit handler
    ");
    }
    
    static void
    my_exit2(void)
    {
            printf("second exit handler
    ");
    }

    执行该程序产生:

    [root@localhost apue]# ./prog7-2
    main is done
    first exit handler
    first exit handler
    second exit handler

    终止处理程序每登记一次,就会被调用一次。在程序清单7-2中,第一个终止处理程序被登记两次,所以也会被调用两次。

    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

  • 相关阅读:
    GUI的最终选择Tkinter模块初级篇
    JavaScript的进阶篇
    html标签详解
    docker使用自定义镜像zabbix服务
    Django之url定义和ORM框架的使用
    zabbix实现企业微信监控报警
    centos6 搭建nginx实现负载均衡
    mysql数据库进阶篇
    Linux运维之Ansible自动化运维管理工具
    php菜刀分析学习
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3507921.html
Copyright © 2020-2023  润新知