今天一天就结了一章,确实挺快的,不过第六章的内容现在还用不太到,但第七章的内容我认为就比较关键了,主要是有关于进程环境的内容
7.2 main函数
这一小节介绍了简单介绍了有关于main函数的内容,我认为讲的很简单,所以给大家分享一点我之前的学习体会:http://blog.csdn.net/u012927281/article/details/51356228
7.3 进程终止
有8种方式使进程终止,其中5种为正常终止,它们是:
异常终止有3种方式,它们是:
以下三个函数用于正常终止一个程序:_exit或_Exit立即进入内核,exit则先执行一些清理处理,然后返回内核。
函数原型如下:
#include
extern void exit (int __status) __THROW __attribute__ ((__noreturn__));
extern void _Exit (int __status) __THROW __attribute__ ((__noreturn__));
#include
extern void _exit (int __status) __attribute__ ((__noreturn__));
以下内容直接引用自APUE:
“由于历史原因,exit函数总是执行一个标准I/O库的清理关闭工作:对于所有打开流调用fclose函数,这就造成输出缓冲中的所有数据都被冲洗(写入文件或输出)。”
若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。其他情况下,进程的终止状态是未定义的。这一点可以通过stddef.h中相关的定义验证。
#define EXIT_FAILURE 1 /* Failing exit status. */
#define EXIT_SUCCESS 0 /* Successful exit status. */
终止处理程序注册函数:
#include
extern int atexit (void (*__func) (void)) __THROW __nonnull ((1));
根据ISO C的规定,一个进程可以登记多至32个函数,这些函数由exit自动调用,通过atexit函数来注册这些函数。exit调用这些函数的顺序与他们登记时候的顺序相反。
根据ISO C和POSIX.1,exit首先调用各终止处理程序,然后关闭(通过fclose)所有打开流。POSIX.1扩展了ISO C标准,如若程序调用exec函数族中的任一函数,则将清除所有已安装的终止处理程序。
这里还要注意的一点是内核使程序执行的唯一方法是调用一个exec函数。进程自愿终止的唯一方法是显示或隐式地(通过调用exit)调用_exit或_Exit。进程也可非自愿地由一个信号使其终止。
一个C程序是如何启动和终止的见下图。
7.4 命令行参数的有关内容就不给大家详细分享了。
7.5 环境表
每个程序都接收到一张环境表。使用全局变量environ对这一环境表进行引用,environ为环境指针,指针数组为环境表,其中各指针指向的字符串为环境字符串。
7.6 C程序的存储空间布局
这一章也不详细分析了,有关于这部分的内容请见我有关于《程序员的自我修养》的读书笔记。
7.7 共享库
这一章也不详细分析了,这部分内容还是请见我有关于《程序员的自我修养》的读书笔记。
7.8 存储空间分配
这一部分也先不说了,不过有机会的话要把malloc的源码简单分析一下。
7.9 环境变量
ISO C定义了一系列函数用于查询、修改环境变量,首先来看查询环境变量的函数。
#include
extern char *getenv (const char *__name) __THROW __nonnull ((1)) __wur;
再来看看更改环境变量的函数:
#include
extern int putenv (char *__string) __THROW __nonnull ((1));
extern int setenv (const char *__name, const char *__value, int __replace)
__THROW __nonnull ((2));
extern int unsetenv (const char *__name) __THROW __nonnull ((1));
setenv将name设置为value。如果在环境中name已经存在,那么(a)若rewrite非0,则首先删除其现有的定义;(b)若rewrite为0,则不删除其现有定义(name不设置为新的value,而且也不出错)。
unsetenv删除name的定义,即使不存在这种定义也不算出错。
putenv与setenv的区别在于setenv必须分配存储空间,以便依据其参数创建name=value字符串。但putenv存在一定的隐患,若将存放在栈中的字符串作为参数传递给putenv函数,但从当前函数返回时,其栈帧占用的存储区可能将被重用。
关于7.10节与7.11节的内容也不给大家分享了。