●进程终止的方式

1、正常终止

1)从main函数返回;

2)调用exit函数;

3)调用_exit或_Exit;

4)最后一个线程从启动例程返回;

5)最后一个线程调用pthread_exit;

2、异常终止

●main函数

        我们通常认为C语言的起始函数是main函数,实质上一个程序的启动函数并不一定是main函数,这个可以采用链接器来设置,但是gcc中默认main就是C语言的入口函数,在main函数启动之前,内核会调用一个特殊的启动例程,这个启动例程从内核中取得命令行参数值和环境变量值,为调用main函数做好准备,因此对应程序而言main函数并不是起始,但是对应C 语言而言,main函数就是入口地址,其他的链接器帮助我们完成,实际上mian函数的执行是使用了exec函数,这是一个函数族,这也是内核执行一个程序的唯一方法,这在进程控制部分将进行分析。   

       简单说就算是,当内核使用一个exec函数执行C程序时,在调用main函数之前先调用一个特殊的启动例程,可执行程序将此例程指定为程序的起始地址。启动例程从内核获取命令行参数和环境变量,然后为调用main函数做好准备。

● exit、_exit和_Exit函数

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

        #include <unisth.h>

先做一些清理工作(调用执行各终止处理程序,按需对所有打开的流调用fclose(),关闭所有标准I/O流,这样会造成所有缓冲的输出数据都被冲洗即写入文本中),再进入内核。三个函数所带的整型参数(status)称为终止状态或退出状态。

        如果满足以下几点,则进程的终止状态是未定义的。

        1)调用这些函数不带参数

●对比exit和return、about、_exit进行进程的终止

    1、exit与return         exit:一个函数,有参数。exit执行完后把控制权交给系统         return:函数执行完后的返回。return执行完后把控制权交给调用函数     2、exit与about         exit:正常终止进程         about:异常终止进程     3、exit与_exit都是用来终止进程的。当程序执行到exit或者_exit时,系统无条件的停止剩下的所有操作,清楚包括PCB在内的各种数据结构,并终止本进程的运行。exit中的参数exit_code为0代表进程正常终止,若为其他值表示程序执行过程中有错误发生。

                exit()函数的头文件——->stdlib.h                _exit()函数的头文件——>unistd.h

        2)执行后的动作不同                  a、 _exit()在执行后立即返回给内核,而exit()要先执行一些清除工作,然后把控制权交给内核。

       但不会刷新流                                                                    (stdin,stdout,stderr等)

exit()函数是在_exit()函数之上的一个封装,它会调用_exit()函数,并在调用之前刷新流。   

                 

centos停止npm服务__exit

●atexit函数

         1、 atexit函数功能:注册终止函数,即在main执行结束后调用的函数。

         2、 其中,atexit的参数是一个函数地址,当调用此函数时无须传递任何参数,该函数也不能返回值,atexit函数称为终止处理程序注册程序,注册完成以后,当函数终止是exit()函数会主动的调用前面注册的各个函数,但是exit函数调用这些函数的顺序与这些函数登记的顺序相反,我认为这实质上是参数压栈造成的,参数由于压栈顺序而先入后出(即和函数调用的栈帧过程相似)。

        3、一个进程可以注册若干个函数,这些函数由exit自动调用,这些函数被称为终止处理函数,atexit函数可以注册这些函数。

        4、如果一个函数被多次登记,那么该函数也将多次的执行。

            我们知道exit是在main函数调用结束以后调用,因此这些函数的执行肯定在main函数之后。

写一个程序,在Linux环境下验证一下atexit函数调用注册函数的顺序

      

centos停止npm服务__exit_02

如果main函数中输出部分不加\n,则main函数要输出的内容会先放到标准输出缓冲区中,当main中调用exit函数的时候,会做一些自身清理工作,同时刷新标准输出缓冲区中的内容

●环境表

●C程序的空间布局

●存储器分配

       #incldue<stdlib.h>

       1、malloc函数分配指定字节数的存储区,该存储区中的初始值不确定;、

以上函数的大多数实现所分配的存储空间都比所要求的大一些,额外的空间用来存储管理信息。如果在一个超过已分配区的尾端进行写操作,就会重写下一个分配区的管理记录;同样,在一个已分配区的起始位置之前写入,会重写本分配区的管理记录。这种错误是灾难性的,但因为不会很快暴露出来,所以很难发现。