APUE - 进程环境

进程终止

有 8 种方式使进程终止,其中 5 种为正常终止:

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

异常终止有 3 种方式:

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

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 */
};

在更改资源限制时,须遵循下列三条规则:

  1. 任何一个进程都可将一个软限制值更改为小于或等于其硬限制值。
  2. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低对普通用户而言是不可逆的。
  3. 只有超级用户进程可以提高硬限制值。