Unix环境高级编程 读书笔记 第七章 进程环境

main函数

在C语言中,main函数的原型为:

int main(int argc, char *argv[]);

argc是命令行参数的数目,argv是指向命令行参数的各个指针所组成的数组。

当内核在执行C程序时,在调用main函数之前会调用一个特殊的启动例程,可执行程序文件将此启动例程指定为程序的起始地址。
启动例程从内核取得命令行参数和环境变量值,为调用main函数作好准备。

进程终止

进程终止具有5种正常终止方式:

  1. 从main返回;
  2. 调用exit;
  3. 调用_exit或者_Exit;
  4. 最后一个线程从其启动例程返回;
  5. 最后一个线程调用pthread_exit。

进程终止具有3种异常终止方式:

  1. 调用abort;
  2. 接到一个信号;
  3. 最后一个线程对取消请求做出响应。

具有3个函数用于正常终止一个程序:

#include <stdlib.h>
void exit(int status);
void _Exit(int status);

#include <unistd.h>
void _exit(int status);

其中exit函数总是执行一个标准IO库的清理关闭操作:对所有打开流调用fclose函数,造成输出缓冲中所有的数据都被冲洗到文件上。

以上的3个函数都带一个整型的参数,为终止状态或者退出状态。对于以下情况,进程的终止状态是未定义的:

  1. 调用exit系列函数时不带终止状态;
  2. main函数执行了一个无返回值的return语句;
  3. main函数没有声明返回类型为整型。

函数atexit提供了注册终止处理程序的功能,这些被注册登记的终止处理程序将由exit函数自动调用。

#include <stdlib.h>
int atexit(void (*func)(void));
/*若成功,返回0,若出错,返回非0*/

exit调用这些函数的顺序与其登记时候的顺序相反。
在这里插入图片描述

环境表

每个程序都对应一张环境表,环境表是一个字符指针数组,其中每个指针包含一个以null结尾的C字符串地址。
全局变量environ包含该指针数组的地址,称environ为环境指针。指针数组为环境表,各个指针指向的字符串为环境字符串。
在这里插入图片描述

C程序的存储空间布局

典型的存储空间布局安排为:

  1. 正文段,即text段,是CPU执行的机器指令部分,可共享;
  2. 初始化数据段,即data段;
  3. 未初始化数据段,即bss段,名称起源于早期汇编中的block started by symbol,在程序执行之前,由内核将此段中的数据初始化为0或者空指针;
  4. 栈,自动变量和每次函数调用所需保存的信息都存放在此段中;
  5. 堆,在堆中进行动态存储分配。
    在这里插入图片描述

存储空间分配

系统提供了3个用于存储空间动态分配的函数,以及1个用于空间内存释放的函数:

#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);

malloc函数分配指定字节数的存储区,分配的存储区的初始值不确定。
calloc函数为指定数量指定长度的对象分配存储空间,存储空间数据会被初始化为0。
realloc函数增加或者减少之前分配的存储空间大小。新增的存储空间数据初始值不确定。
free函数释放ptr指向的存储空间。

大多数的实现所分配的存储空间比所要求的要稍微大一些,额外的空间用来记录管理信息,包括分配块的长度,指向下一个分配块的指针等信息。
如果超过一个分配块的尾端或者在已分配块起始位置之前进行写操作,则可能会改写另一块分配块的管理信息数据,或者其他动态分配的对象数据,这样的错误是灾难性的,且不易排查。

环境变量

系统定义了1个函数getenv,可以用其取环境变量的值:

#include <stdlib.h>
char *getenv(const char *name);
/*返回指向与name相关的value的指针,若未找到,返回NULL*/

应当使用函数getenv从环境中取一个指定的环境变量的值,而不是直接访问全局变量environ。
在这里插入图片描述

有时候不仅需要获取环境变量的值,也需要设置环境变量的值,可能是希望改变某个现有环境变量的值,或者是新增环境变量。系统提供了调用函数来实现:

#include <stdlib.h>
int putenv(char *str);
/*若成功,返回0,若出错,返回非0*/

int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
/*若成功,返回0,若出错,返回-1*/

函数putenv取形式为name=value的字符串,将其放入环境表中。若name已经定义,则删除原先的定义。

函数setenv将环境变量name设置为value,若name已经定义,则由参数rewrite来绝对是否删除原先的定义,若rewrite为0,则不删除原先定义,若rewrite非0,则删除原先的定义。

函数unsetenv删除环境变量name,即使原先不存在环境变量name,也不出错。

猜你喜欢

转载自blog.csdn.net/jiangzhangha/article/details/85773046