进程环境
本节主要介绍Unix的进程环境。
1.命令行参数和环境表
大多数Unix系统支持main
函数带3个参数:
int main(int argc, char *argv[], char *envp[]);
argc
表示命令行参数数目,argv
是指向参数的指针所构成的数组,envp
是环境表地址。
对于命令行参数,可以通过下面的程序进行理解:
#include "apue.h"
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++) /* echo all command-line args */
printf("argv[%d]: %s\n", i, argv[i]);
exit(0);
}
执行该程序可以的到:
环境表也是一个字符指针数组,其中每个指针包含一个以null
结束的C字符串的地址,全局变量environ
包含了该指针数组的地址。其结构可以由下图表示:
通常可以用getenv和putenv来访问特定的环境变量,但是要查看整个环境,则必须使用environ
指针。
2.C程序的存储空间
C程序一直由下列几部分组成:
- 正文段。CPU执行的机器指令部分,通常可以共享
- 初始化数据段。通常称为数据段,包含程序中需明确地赋初值的变量
- 未初始化数据段。通常称为bss段,存放未赋值的变量(通常初始化为0或空指针)
- 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次函数调用时,其返回地址及调用者的环境信息都存放在栈中,然后最近被调用的函数在栈上为其自动和临时变量分配存储空间。
- 堆。通常在堆中进行动态存储分配,通常堆位于未初始化数据段和栈直接。
下图给出了存储空间的典型布局:
3.共享库
共享库使得可执行文件中不再需要包含公用的库函数,而只需在所有进程都可引用的存储区中保存这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。
这样的好处在于减少了每个可执行文件的长度,缺点是增加了运行时间开销,时间开销主要发生在该程序第一次被执行时,或者共享库第一次被调用时。
4.存储空间分配
ISO C说明了3个用于存储空间动态分配的函数:
- malloc,分配指定字节数的存储区。此存储区中的初始值不确定
- calloc,为指定数量指定字长的对象分配存储空间。该空间中的每一位(bit)都设置为0.
- realloc,增加或减少以前分配区的长度。当增加长度时,可能需要将以前分配区的内容移植到另一个足够大的区域,以便在尾部提供增加的存储区,而新增区域初始值则不确定。
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
/* 返回值:成功返回非空指针,失败返回NULL*/
void free(void *ptr);