APUE - 进程环境
进程终止
有 8 种方式使进程终止,其中 5 种为正常终止:
- 从 main 返回。
- 调用 exit。
- 调用 _exit 或 _Exit。
- 最后一个线程从其启动例程返回。
- 最后一个线程调用 pthread_exit。
异常终止有 3 种方式:
- 调用 abort。
- 接到一个信号并终止。
- 最后一个线程对取消请求做出响应。
exit 函数
有三个函数用于正常终止一个程序:_exit 和 _Exit 立即进入内核,exit 则先执行一些清理处理,然后进入内核。
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
由于历史原因,exit 函数总是执行一个标准 I/O 库的清理关闭操作:为所有打开流调用 fclose 函数。
atexit函数
按照 ISO C 的规定,一个进程可以登记多达 32 个函数,这些函数将由 exit 自动调用。我们称这些函数为终止处理程序,并调用 atexit 函数来登记这些函数。
#include <stdlib.h>
int atexit(void (*func)(void) );
exit 调用这些函数的顺序与它们登记时候的顺序相反。同一函数如若登记多次,则也会被调用多次。
根据 ISO C 和 POSIX.1,exit 首先调用各终止处理程序,然后按需多次调用 fclose,关闭所有打开流。POSIX.1 扩展了 ISO C 标准,它指定如若程序调用 exec 函数族中的任一函数,则将清除所有已安装的终止处理程序。
命令行参数
ISO C 和 POSIX.1 都要求 argv[argc] 是一个空指针。这就使我们可以将参数处理循环写为:
for (i = 0; argv[i] != NULL; i++)
环境表
每个程序都会接收到一张环境表。环境表是一个字符指针数组,其中每个指针包含一个以 NULL 结束的 C 字符串的地址。全局变量 environ 则包含了该指针数组的地址:
extern char **environ;
存储器分配
ISO C 说明了三个用于存储空间动态分配的函数。
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
void free(void *ptr);
环境变量
ISO C 定义了一个函数 getenv,可以用来取环境变量值,但是该标准又称环境的内容是由实现定义的。
#include <stdlib.h>
char *getenv(const char *name);
设置环境变量:
#include <stdlib.h>
int putenv(char *str);
int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
setjmp 和 longjmp 函数
在 C 中,goto 语句是不能跨越函数的,而执行这类跳转功能的是函数 setjmp 和 longjmp。
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
getrlimit 和 setrlimit 函数
每个进程都有一组资源限制,其中一些可以用 getrlimit 和 setrlimit 函数查询和更改。
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
struct rlimit {
rlim_t rlim_cur; /* soft limit: current limit */
rlim_t rlim_max; /* hard limit: maxinum value for rlim_cur */
};
在更改资源限制时,须遵循下列三条规则:
- 任何一个进程都可将一个软限制值更改为小于或等于其硬限制值。
- 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低对普通用户而言是不可逆的。
- 只有超级用户进程可以提高硬限制值。