UNIX进程的环境(二)

2016-02-02  本文已影响53人  千里山南

2016-02-02

命令行参数

当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序。
其中argv[0]是 程序名称

环境表

每个程序都接收一张环境表,与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null借宿的字符转的地址。全局变量environ则包含了该指针数组的地址。
extern char **environ
按照惯例环境由name=value这样的字符串组成。大多数预定义名全由大写字母组成。通常用getenv和putenv函数来存取特定的环境变量,而不是用environ变量,如果要查看整个环境则必须使用environ指针。

c程序的存储空间布局

由于历史原因,c程序一直由下列几部分组成

命令行参数和环境变量-->栈-->堆-->非初始化数据-->初始化数据-->正文
size命令报告正文段、数据段、bss段的长度

共享库

现在很多unix系统支持共享库,共享库是的可执行程序文件中不再需要包含常用的库函数,而只需在所有进程都可存取的存储区中保存这一种库例程的一个副本。程序第一次执行或则第一次调用某个库函数时,用动态链接方法将程序与共享库函数相连接。这就减少了每个可执行文件的长度,但增加了一些运行时的开销。共享库的另一个优点是可以用库函数的新版本代替老版本而无需对使用该库的程序从新连接编辑。
不同的系统使用不同的方法使说明程序是否要使用共享库。比较典型的有cc和ls命令可选

存储器分配

ANSI C说明了三个用于存储空间动态分配的函数

void *malloc(size_t size);
void *calloc(sieze_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
void free(void *ptr);

这单个分配函数所犯规的指针一定是适当对其的,使其可用于任何数据对象。例如,在一个特定的系统上,如果最苛刻的对其要求是double,则对其必须在8的倍数的地址单元处,那么这三个函数返回的指针都应这样对齐。
realloc在改变存储区大小的时候有可能会移动存储区的位置,因此不应当使用任何指针指向此存储区
realloc中若ptr为null则与malloc的功能相同。
这些分配例程通常调用sbrk系统调用实现。虽然sbrk可以扩从或者缩小一个进程的存储空间,但大多数malloc和free实现都不减小进程的存储空间,释放的空间可以供以后再分配,但他们被保存在malloc池而不返回给内核。
应当注意的是大多数实现所分配的存储空间比所要求的要稍微大一些,额外的空间用来记录管理信息分配块的长度,指向下一个分配快的指针等。这就意味着如果写过一个已分配区的尾端,则会改写后一块的管理信息。这种类型的错误是灾难性的。
其他的可能产生的致命性的错误是:释放了一个已经释放的块,调用free时所用的指针不是三个alloc函数返回值。
因为存储器分配出错很难跟踪,所以某些系统提供了这些函数的另外一种实现方法,每次调用者单个分配函数中的任意一个或者free时都进行附加的出错检查。

alloca函数

其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。其优点是:当函数返回时,自动释放它所使用的栈帧,多以不必再为释放空间而费心。其缺点是:某些系统在函数一杯调用后不能增加栈帧的长度,于是也就不能支持alloca函数。

环境变量

如同前面所述,环境字符串的形式是:name=value
unix内核并不关心这种字符串的意义,他的解释完全取决于各个应用程序。
char *getenv(const char *name)
除了取环境变量,有时也需要设置环境变量,或者改变现有的变量的值,或者是增加新变量的(我们能影响的是当前进程及其后生成的子进程的环境,但不能影响父进程的环境)
int putenv(const char *str)
int setenv(const char *name, const char *value, int rewrite)
void unsetenv(const char *name)

setjmp和longjmp

在C中不允许使用跳跃函数goto 而执行这种跳转功能的是函数setjmp和longjmp这两个函数对于处理发生在很深的嵌套函数调用中出错情况非常有用。
int setjmp(jmp_buf env)
void longjmp(jmp_buf env, int val)
在希望返回到达的位置调用setjmp。setjmp的参数env是一个特殊类型jmp_buf这一数据类型是某种形式的数组,其中UC南方在调用longjmp时能用来恢复栈状态的所有信息。一般,env变量是个全局变量,因为需要从另一个函数中引用它。
当检查到一个错误时,则以两个参数滴啊用longjmp第一个就是在调用setjmp时所用的env第二个val是个非0值,它成为setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。

自动、寄存器和易失变量

当longjmp返回时,大多数实现并不回滚自动变量和寄存器变量。如果你有一个自动变量而又不想使其值回滚,则可以定义其为具有volatile属性。说明为全局和静态变量的值在执行longjmp时保持不变。因此如果要编写一个使用非局部跳转的可移植程序,则必须使用volatile属性。

自动变量的潜在问题

基本规则是说明自动变量的函数已经返回后,就不能再引用这些自动变量。

getrlinit和setrlimit函数

每个进程都有一组资源限制,其中某一些可以用getrlimit和setrlimit函数查询和更改
int getrlimit(int resource, struct rlinit *rlptr)
int setrlinit(int resource, const struct rlimit *rlptr)
对这两个函数的每一次调用都制定一个资源以及一个指向下列结构的指针

struct rlimit {
    rlimi_t rlim_cur;
    rlimi_t rlim_max;
}

进程的资源限制通常是在系统初始化时由0进程建立的,然后由后续进程继承。
更改资源限制时,需准守下列三条原则:

资源限制影响到调用进程并由其子进程继承。

上一篇 下一篇

猜你喜欢

热点阅读