读书笔记——《UNIX环境高级编程》第七章_ 进程环境

第七章 进程环境

各位观众,今天节目的主要内容有:

1、  当执行程序时,其main函数是如何被调用的?

2、  命令行参数是如何传送给执行程序的?

3、  典型的存储器而已是什么样式?

4、  如何分配另外的存储空间?

5、  进程如何使用环境变量?

6、  各种不同进程终止方式

另外,本期特别报导:

         longjmpsetjmp函数以及它们与栈的交互作用;进程的资源限制。

请看详细报导:

1、 main函数

C程序总是从main函数开始执行,当内核执行C程序时,在调用main前先会调用一个特殊的启动例程,启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用 main函数做好安排。

那么一个程序启动了,又是如何终止的呢,请看继续报导:进程终止。

2、 进程终止

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

1.       main返回

2.       调用exit

3.       调用_exit_Exit

4.       最后一个线程从其启动例程返回(第11.5期节目中,将会做详细报导)

5.       最后一个线程调用pthread_exit(第11.5期节目中,将会做详细报导)

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

1.       调用abort(第10.17期节目中,将会做详细报导)

2.       接到一个信号并终止(第10.2期节目中,将会做详细报导)

3.       最后一个线程对取消请求做出响应(第11.512.7期节目中,将会做详细报导)

 

上一节提到到的启动例程会使main返回后立即调用exit函数,如果启动例程以C代码形式表示(事实上启动例程是常常使用汇编语言编写),那么它调用main函数的形式就可能是如下:

exit(main(argc,argv));

下面来看一看exit函数相关资料:

前面已经看到,exit 和他两个兄弟 _exit _Exit三种方式可以正常终止程序,那么这三个兄弟区别在哪里?请看下面:

_exit_Exit立即进入内核,而exit则先执行一些清理处理(包括调用执行各终止处理程序,送亲所以有标准I/O流等),然后进入内核,所以exit要稍微勤快点,干的事稍微多一点。

exit对于标准I/O库的清理关闭操作主要是通过为所有打开流执行fclose函数,回忆5.5期节目中对fclose的介绍,这会造成所有缓冲的输出数据都被冲洗。

这三个兄弟,工作时都会带一个整型参数,这个参数将被用于标明程序的终止状态,也就是说,参数是什么值,那么,程序的终止状态就是什么值,对将对于我们判断一处程序问题出在哪里将非常有用。但是如果进程终止时出现以下三种情况:

1.       调用exit函数时没有带终止态

2.       main执行了一个无返回值的return语句

3.       main没有声明返回类型为整型

程序的终止态就是未定义的

 

另外,若main返回类型是整型,且在执行到最后一条语句时返回隐式返回,那么该进程终止状态将是0main函数中,返回一整型什与该值调用exit是等价的,于是,main函数中:

         exit(0);

等价于

         return(0);

 

2.1 atexit函数

         进程结束前期我们还可以调用一些函数做一些处理,这些函数被称为终止处理程序( exit handler,一个进程最多可以登记32个函数,函数将由exit自动调用,登记是由     atexit完成。定义如下:

         #include <stdlib.h>

         int atexit(void (*func)(void));

需要说明的是,exit调用终止处理程序的顺序与它们登记的时候顺序相反,同一函数若被登记多次,则也会被多次调用。另,exit执行时,首选调用各终止程序,然后再调用fclose,如果程序调用了exec函数族中任一函数,则将清除所有已安装的终止处理程序。

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

 

3、 命令行参数

当一个程序执行时,调用exec的进程可将命令行参数传递给新程序,例子可以参照  main(int argc,char *argv[]),不再过多讨论,另外需要说明一点是argv[argc]是一个空指针

 

4、 C程序存储空间布局

C程序典型存储器安排如下图:

 读书笔记——《UNIX环境高级编程》第七章_ 进程环境_第1张图片


           说明:

正文段:CPU执行的机器指令部份,通常是正文段可以共享的且通常是只读的,以防止程序由于意外而修改其自身指令。

初始化数据段:通常被称为数据段,包含了程序中需明确地赋初值的变量。

非初始化数据段:程序开始前,内核将此段中的数据初始化为0或空指针。如以下声明:long  sum[100];将会被放于非初始化数据段。

堆与栈不再细说。

另外,未初始化数据段内容并不放在磁盘上的程序文件中,需要存放的只有正文段和初始化数据段。

你可能感兴趣的:(编程,unix,汇编,读书,存储,磁盘)