现在的位置: 首页 > 综合 > 正文

第七章 进程环境

2018年04月21日 ⁄ 综合 ⁄ 共 1704字 ⁄ 字号 评论关闭

1.main 函数

  

    C程序总是从main函数开始执行的。main函数的原型是:

     int main(int argc,char *argv[]);

其中,argc是命令行参数的数目,argv是指向参数的各个指针构成的数组。

    当内核执行C程序时(使用一个exec函数),在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址——这是由连接编辑器设置的,而连接编辑器则由C编译器调用。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用main函数做好安排。

2.进程终止

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

    (1)从main返回。

    (2)调用exit。

    (3)调用_exit或_Exit。

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

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

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

    (6)调用abort。

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

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

    当main函数自然返回(主函数结束或使用return返回)时,进程将自动调用exit函数进行扫尾工作。其中有三个函数可以正常终止一个程序:exit,_exit或_Exit。exit先行一些清理处理(包括调用执行各终止处理程序,关闭所有标准I/O流等),然后进入内核;_exit和_Exit则立即进入内核。

    atexit()函数用来注册程序正常终止时要被调用的函数。在一个程序中最多可以用atexit()注册32个处理函数,这些处理函数的调用顺序与其注册的顺序相反,也即最先注册的最后调用,最后注册的最先调用。

 

3.共享库

    共享库使得可执行程序文件中不再需要包含公用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。

 

4.存储器分配

    有三个用于存储空间动态分配的函数:

    (1)malloc。分配指定字节数的存储区。此存储区中的初始值不确定。

    (2)calloc。为指定数量具指定长度的对象分配存储空间。该空间中的每一位都初始化为0。 

    (3)realloc。更改以前分配区的长度。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,以便在尾端提供增加的长度区,而新增区域内的初始值则不确定。

 

    在C中,goto语句是不能跨越函数的,而执行这类跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的。使用时先由setjmp函数指定一个jmp_buf类型缓存,保存寄存器中的数据,当通过longjmp函数返回至setjmp函数调用处时,寄存器中的值被恢复为setjmp函数第一次调用时的值,而存储器中的值保持不变。由于优化编译会对变量存储位置造成影响(存储在存储器中或寄存器中),因此优化编译可能导致setjmp函数通过longjmp返回时寄存器所恢复的值发生变化。记住,setjmp函数调用一次(记录寄存器中的数据)而返回多次(第一次通过setjmp函数返回0,其他时间通过longjmp函数返回,返回值为longjmp函数第二参数);longjmp函数不会返回(返回到了setjmp函数的调用处)。

    当longjmp返回到setjmp函数的调用处,变量值是否能恢复到以前调用setjmp时的值?大多数实现并不回滚这些自动变量和寄存器变量的值,而所有标准则说它们的值是不确定的。如果你有一个自动变量,而又不想使其值回滚,则可定义其为具有volatile属性,声明为全局变量或静态变量在执行longjmp时保持不变。全局、静态和易失变量不受优化的影响,在调用longjmp之后,它们的值是最近所呈现的值。某个系统的setjmp(3)手册页上说明,存放在存储器中的变量将具有longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp时的值。

抱歉!评论已关闭.