1、main函数
main 函数 C/C++ 程序的入口函数, 但并不是进程真正开始执行的地方。main函数的原型:int main(int argc, char *[]argv)。其中,argc是命令行参数的数目,argv是指向参数的各个指针所构成的数组。
当内核执行C程序时(使用一个exec函数),在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址,这是由连接编辑器设置的,而连接编辑器则由C编译器调用。启动例程从内核取得命令行参数和环境变量,然后为调用main函数做好安排。
2、进程终止
有8种终止方式,正常终止(5种):
(1)从main返回。
(2)调用exit。
(3)调用_exit或_Exit。
(4)最后一个线程从其启动例程返回。
(5)最后一个线程调用pthread_exit。
异常终止(3种):
(1)调用abort。
(2)接到一个信号并终止。
(3)最后一个线程对取消请求做出响应。
在上面的正常终止中有exit和_exit,区别在于:_exit调用后立即进入内核;而exit则会先执行一些清除工作(包括调用执行各种终止处理程序,关闭所有标准I/O流等),然后在进入内核。
3、环境表
在Unix操作系统中,每一个进程都包含一个环境列表(environment list),环境列表以数组的方式存储,数组地址存储在全局变量environ中,使用时需在文件中包含:
extern char** environ;
环境列表中的数据以"name=value"的方式存储。
4、C程序的存储空间布局
C程序由以下几部分组成:
正文段:也叫代码段,是CPU执行的机器指令。正文段一般可以共享的,且是只读的。
初始化数据段:也叫做数据段,包含程序中已经初始化的全局变量和静态变量。
非初始化数据段:也叫做bss段,包含未初始化的全局变量和静态变量,在程序执行之前有内核初始化为0。不在代码中存储器初始值,可以减小代码的大小。(在可执行文件中不占位置,程序运行前才开辟并清0)
栈:自动存储变量以及每次函数调用时所需保存的信息都放在此段中。每次函数调用时,其返回地址、以及寄存器中的变量都放在栈中。新被调的函数在栈上为其自动和临时变量分配存储空间。
堆:进行动态分配的变量。需要手动释放。堆位于未初始化数据段的顶和栈底之间。
5、共享库
共享库使得可执行文件中不再需要包含公用的库函数,而只需在所有进程都可引用的存储区中保存这种库的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。
6、存储空间分配
malloc。分配指定字节数的存储区。此存储区中的初始值不确定。
calloc。为指定数量具指定长度的对象分配存储空间。该空间中的每一位(bit)都初始化为0。
realloc。更改以前分配区的长度。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,以便在尾段提供增加的存储区,新增区域内的初始值不确定。
这3个分配函数所返回的指针是适当对齐的。
7、环境变量
8、函数setjmp和longjmp
在C中,goto语句是不能跨越函数的。而执行这种跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在很深的嵌套函数调用中的出错情况非常有用。
int setjmp(jmp_buf env) ;
返回:若直接调用则为0,若从longjmp返回则为非0
void longjmp(jmp_buf env , int val) ;
应用:(1)允许从一个深层嵌套的函数调用中立即返回,而不是费力地解开调用栈;(2)使一个信号处理程序分支到一个特殊的代码位置,而不是返回到被信号到达中断了的指令的位置。