一、main函数
C程序总是从main
函数开始执行。但是,对内核而言,会先调用一个特殊的启动例程。
启动例程从内核取得命令行参数和环境变量值,为调用main函数做好安排。
二、命令行参数
当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序。命令行参数会缓存于main
函数的argv
参数中。
例如,执行以下命令:
./a.out a b c
那么,argv[0]
值为./a.out
,argv[1]
值为a
,以此类推。
三、环境表
每个C程序都接收到一张环境表,它是一个字符指针数组,全局变量environ
包含了该指针数组的地址:extern char **environ;
环境表中的每个字符串都是name=value
的格式,直接使用environ
存取可能不太方便,所以一般使用以下函数存取:
char *getenv(const char *name);
返回name指定的环境变量的值。
int putenv(char *string);
把string指定的字符串添加到环境表中。
四、函数setjmp和longjmp
在C程序中,goto
语句是不能跨越函数的,而要实现跨越函数的跳转,可以使用setjmp
和longjmp
函数,它们的原型如下:
int setjmp(jmp_buf env);
在函数调用处设定跳转点,把当前状态信息保存到 jmp_buf 结构中。
void longjmp(jmp_buf env, int val);
跳转到jmp_buf保存的位置继续执行,并把val作为该处的setjmp返回值。
五、进程终止
1.退出函数
void exit(int status);
void _Exit(int status);
void _exit(int status);
status用于指定程序的退出状态。
exit
函数先执行一些清理处理,然后返回内核。_exit
和_Exit
会立即进入内核。exit
和_Exit
位于<stdlib.h>
,_exit
位于<unistd.h>
2.终止方式
进程终止的方式有8种。其中,5种为正常终止,它们是:
- 从
main
函数返回。 - 调用
exit
。 - 调用
_exit
或_Exit
。 - 最后一个线程从其启动例程返回。
- 从最后一个线程调用
pthread_exit
。
异常终止的方式有3种,它们是:
- 调用
abort
。 - 接到一个信号。
- 最后一个线程对取消请求做出响应。
3.钩子函数
int atexit(void (*func)(void);
把参数指定的函数登记为终止处理程序。
- 终止处理程序没有参数和返回值。
- 程序终止时,按登记顺序的倒序执行终止处理程序。
六、C程序的存储空间布局
C程序在内存中的存储空间布局分为六个部分,其中,堆和栈在程序执行前才会被分配:
- 正文段:CPU执行的机器指令,它是只读、可共享的。
- 初始化数据段:包含程序中需明确赋初始值的变量。
- 未初始化数据段:bss段,在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
- 栈:自动变量以及每次函数调用时所需保存的信息都存放在此段中。
- 堆:用于动态存储分配的内存。
- 命令行参数区:用户指定的命令行参数。
- 环境表:系统环境变量组成的列表。