Process Environment
1 Process Termination
进程的终止有些下面的方法:
1. 从main函数return
2. 调用exit:exit属于ISO C标准中定义的函数,会执行清理工作。包括关闭IO库中所有打开的文件流(这会导致所有的文件buffer都被flush),还会调用阿texit所注册的退出函数。Exit还会。等价于return (0)
3. 调用_exit或者_Exit:这两个函数都不会执行清理工作,直接退出进程。_exit是POSIX.1标准定义的函数,而_Exit则是ISO C标准定义的函数。
4. 最后一个线程从其线程函数return
5. 最后一个线程调用pthread_exit
非正常中止包括:
1. Abort
2. 接收一个signal
3. 最后一个线程收到了Cancel请求
Atexit可以用来注册多达32个退出函数:
#include <stdlib.h> int atexit(void (*func)(void)); 成功返回0,错误返回非0 |
这些函数以注册的逆序被调用。同一个函数可以被注册多次,并被调用多次。
2 Environment List
每个程序都被传入一个环境列表,定义如下:
extern char **environ; |
其实就是一个字符串数组,每个元素都是一个字符串,表示一个环境变量,如HOME=/home/sar,以0结尾。而整个字符串数组也以NULL结尾。
3 Memory Layout
1. Text Segment
2. Initialized Data segment(Data Segment),一般简称为data。用来专门存放已经初始化的数据,如int maxcount = 99
3. Uninitialized data segment,一般简称为bss,根据一个很古老的汇编语句BSS(代表Block Started by Symbol)命名。存放未初始化的数据,如long sum[1000]; 由内核自动初始化为0。
4. Stack,一般来说向低地址增长
5. Heap,一般来说向高低址增长,和Stack共用一块空间
4 Memory Allocation
1. 一般内存分配使用malloc / calloc / realloc,大家应该都很熟悉了,calloc和malloc的区别是前者会初始化内存为0,而后者不会。这些函数一般用sbrk系统调用实现。
2. 除了一般的malloc/free等内存分配函数之外,部分系统还提供了一些替代函数。值得一提的是alloca函数,这个函数从Stack上分配内存空间,优点是速度快而且不用释放,但是不是所有系统都支持,并且使用的场合有限。
5 Environment Variables
下列函数可以用来访问环境变量:
#include <stdlib.h> char *getenv(const char *name); int putenv(char *str); int setenv(const char *name, const char *value, int rewrite); int unsetenv(const char *name); 成功返回0,错误返回非0 |
1. getenv获得环境变量的内容,如果没有此变量则返回NULL
2. putenv接受用name=value形式定义的参数,设置环境变量的值
3. setenv设置name的值为value。如果rewrite=0并且name已经有值的话,不会设置name的值。
4. unsetenv删除name的值
6 setjmp & longjmp
goto可以跳转到程序的另外的一个地方,但是有在同一个函数的限制。而setjmp和longjmp提供了绕过此限制的跳转功能:
#include <setjmp.h> char *setjmp(jmp_buf env); 直接调用者返回0,从longjmp返回则返回非0 void longjmp(jmp_buf env, int val); |
1. 在longjmp应该返回的位置调用setjmp可以记住当前的函数的栈的相关信息,并保存到env之中。如果返回0,则是正常流程。如果返回非0,说明刚从longjmp返回
2. Longjmp调到之前setjmp所记住的位置
需要注意的是,setjmp主要纪录栈的相关信息以保证程序流程可以跳转到setjmp的位置并继续执行,因此只能保证栈指针的正确位置,不会导致栈被破坏,但是栈上的变量则无法保证会被恢复,这个和具体实现相关。如果你想保证某个自动变量(栈上的变量)不被恢复的话,可以定义其为volatile。
7 getrlimit and setrlimit
getrlimit和setrlimit可以定义进程相关的资源限制:
#include <sys/resource.h> int getrlimit(int resource, struct rlimit *rlptr); int setrlimit(int resource, const struct rlimit *rlptr); 成功返回0,错误返回非0 |
rlimit结构定义如下:
struct rlimit { rlim_t rlim_cur; /* 当前limit,称为soft limit */ rlim_t rlim_max; /* 最大limit,称为hard limit */ } |
1. 进程可以修改soft limit为比hard limit小或者相等的任意值
2. 进程可以降低hard limit的值,但必须比soft limit大或者相等。注意normal user作这个操作是不可逆的
3. 只有super user才可以增加hard limit的值
4. 无限可以用常数RLIM_INFINITY
5. 注意soft limit是实际起作用的limit,而hard limit是一个限制值
Limit | Description |
RLIMIT_AS | 进程最大可用内存,对sbrk系统调用有影响 |
RLIMIT_CORE | Core(内存转储,用于事后调试)文件的最大Size |
RLIMIT_CPU | 进程占用CPU的最大时间,超过此限制的时候则发送SIGXCPU signal |
RLIMIT_DATA | 数据的最大Size,包括初始化数据,非初始化数据和Heap |
RLIMIT_FSIZE | 创建文件的最大Size,如果超过则发送SIGXFSZ signal |
RLIMIT_LOCKS | 最大文件锁的数量 |
RLIMIT_MEMLOCK | 最大用mlock锁定内存的Size |
RLIMIT_NOFILE | 打开文件的最大数量 |
RLIMIT_NPROC | 每个user id的最大子进程数 |
RLIMIT_RSS | 最大常驻内存Size。当内存不足时,内核会尝试从内存使用量超过RSS的进程拿走一部分内存 |
RLIMIT_SBSIZE | 一个用户所能使用的Socket缓冲区的最大Size |
RLIMIT_STACK | Stack的最大Size |
RLIMIT_VMEM | 等价于RLIMIT_AS |
Links
进程编程1 – UNIX高级环境编程7章读书笔记
UNIX信号(signal)编程 - UNIX高级环境编程第10章读书笔记
使用pthread库进行多线程编程1 - UNIX环境高级编程第11章读书笔记
使用pthread库进行多线程编程2 - UNIX高级环境编程第12章读书笔记
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1539367