本章主要介绍了unix进程环境,包含main函数是如何被调用的,命令行参数如何传递,存储方式布局,分配存储空间,环境变量,进程终止方法,全局跳转longjmp和setjmp函数及进程的资源限制。
main函数的原型为int main(int argc,char *argv[]);其中argc是命令行参数的数目,argv是指向参数的各个指针构成的数组。当内核执行c程序时,使用一个exec函数,在调用main函数前线调用一个特殊的启动例程,从内核获取命令行参数和环境变量。
进程终止分为正常终止和异常终止。正常终止包括:(1)从main返回,(2)调用exit();(3)调用_exit或者_exit();(4)最后启动一个线程从其启动例程返回;(5)最后一个线程调用pthread_exit。异常终止包括:(1)调用abort();(2)接收到一个信号并终止;(3)最后一个线程对取消请求做出响应。
1、exit函数系列:_exit和_exit函数立即进入内核,而exit函数则执行清理处理(如关闭标准i/o流,执行各终止处理程序)。在main函数执行return (0)与exit(0)是等价的。
#include <unistd.h>
void _exit(int status);
#include <stdlib.h>
void exit(int status);
2、atexit函数,用来登记终止处理程序,一个进程可以登记多达32个函数,这些函数将有exit自动调用,调用顺序与登记顺序相反,同一个函数可以登记多次,则也会被调用多次。函数原型如下:
int atexit(void (*function)(void)); //成功返回0,否则返回非0值
一个c程序启动和终止的过程如下图所示:

内核使程序执行的唯一方法是调用一个exec函数,终止的唯一方法是显式或者隐式地通过exit函数调用_exit()或_exit(),也可以非自愿的由一个信号使其终止。
写个程序进程练习,程序如下:
程序执行结果如下:
命令行参数,当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序,进程间通信数据传输进程用到。写个程序输出其命令行参数,程序如下:
测试结果如下:
c程序的存储空间布局:
存储器分配函数:
void *malloc(size_t size);
void *calloc(size_t nmemb,size_t size);
void *realloc(void *ptr, size_t size); //更改以前分配区的长度
void free(void *ptr);
写个程序练习函数的使用:
环境变量:形式为name=value,环境变量可以在用进程进程间通信,exec函数可以通过环境变量进程传参数,例如在cgi程序中用到http协议get和post方法对应的环境变量。环境变量可用于所有的子进程,这包括编辑器、脚本和应用。环境变量操作函数如下:
char *getenv(const char *name); //指向与name关联的value的指针
int putenv(char *string); //取形式为name=value的字符串,将其放到环境表中
int setenv(const char *name, const char *value, int overwrite); //将name设置为value
int unsetenv(const char *name); //删除name的定义
int clearenv(void); //删除环境表中所有项
写个程序进行环境变量的读取设置及删除。程序如下:
程序执行结果如下:
全局跳转函数setjmp和longjmp:解决跨越函数跳跃,处理发生在深层次嵌套函数调用中出错情况非常有用。全局或者静态变量的值在执行longjmp是保持不变。函数原型如下:
int clearenv(void);
#include <setjmp.h>
int setjmp(jmp_buf env); //返回值为0为直接调用,从longjmp调用返回非0值
int sigsetjmp(sigjmp_buf env, int savesigs);
一般用法是:设置一个全局的jmp_buf变量,在主进程中调用setjmp()设置跳转变量,如果后面的函数出现错误,调用longjmp设置一个值,说明函数调用出错。写个程序来表达用法,程序如下:
进程资源限制函数:getrlimit和setrlimit,资源结果和函数原型如下:
struct rlimit {
rlim_t rlim_cur; /* soft limit */
rlim_t rlim_max; /* hard limit (ceiling for rlim_cur) */
};
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
关于进程资源限制目前还不知道有何用,以后再来补充。