《Unix环境高级编程》总结(五)

进程环境 (第七章)

1、进程终止方式

正常终止:
- main函数返回
- exit()
- _exit() 或 _Exit()
- 最后一个线程返回
- 最后一个线程调用pthread_exit()

异常终止:
- abort()
- 接到一个信号
- 最后一个线程对取消请求做出响应

相关函数如下:

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

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

其中exit() (或调用return)会调用终止处理函数后再调用_exit()/_Exit(),终止处理函数常用于处理终止前的一些数据,如关闭打开的I/O等。status为终止状态,同main()函数返回值。如main()声明的返回类型不为int;或者调用的上述exit不带终止状态;或者main()执行未返回值的return,则终止状态未定义。如main声明为返回int,且main()执行到最后一条语句后隐藏返回,则终止状态为0。

添加终止处理函数方法如下:

#include <stdlib.h>
int atexit(void (*func)(void));
                                    成功返回0,失败非0

atexit()注册函数的顺序与调用顺序相反,同个函数被注册多次将被调用多次。其中支持的函数个数,各系统不一,至少为32个。

2、C程序的存储空间

C程序的存储空间如下:
image

需要存放在磁盘文件中的只有正文段和初始化的数据。
- 正文段:常为可共享的只读空间;
- 初始化数据段:即数据段,存放初始化的数据,如初始化的全局变量;
- 非初始化数据段:即bss段,执行执行前会被自动初始化为0或NULL,如非初始化的全局变量;
- 栈:存放自动变量及每次函数调用时的信息,如函数调用时的返回地址、环境信息等(会自动释放);
- 堆:进行动态存储分配(要手动释放)。

查看各段的大小,如下:

3、存储空间分配

空间分配函数有3个,如下:

#include <stdlib.h>
void *malloc(size_t size);
                            分配空间未初始化
void *calloc(size_t nobj, size_t size);
                            分配空间初始化为0(分配size个单元,每个单元的大小为nobj)
void *realloc(void *ptr, size_t newsize); 
                            增减分配区的长度(内容未初始化,其中newsize为新的总的长度,若ptr为NULL,则同malloc

注:实现分配的长度会大小请求的长度(其中包括一些管理信息),所以在分配空间的前后写,会修改另一个数据单元的管理记录信息。对于空间的另一种常见错误是
重复释放一个块或者调用free()释放非上述3个函数分配的空间。
另有一个函数 alloca() ,其用法同malloc(),但其在栈上分配空间(不用手动释放,缺点是有的系统在函数被调用后,栈的空间不能增加了,便不支持该函数了)

4、环境变量

环境变量相关函数如下:

#include <stdlib.h>
char *getenv(const char *name);
    返回NULL或name对应的value
int putenv(char *str);
    成功返回0,失败非0
    其中str形式为:"name=value",若name存在则先删除。
int setenv(const char *name,const char *value,int rewrite);
    成功返回0,失败-1
    若name存在,且rewrite非0,则先删除(修改),若rewrite为0,则不修改(但不出错)
int unsetenv(const char *name);
    成功返回0,失败-1
    删除指定name,若不存在也不算出错

其中系统中定义的name如下:

putenv和setenv的区别:setenv()中会重新分配空间来存放”name=value”;而putenv不会,所以putenv的参数不能在栈中,否则会出错。
环境表(name=value的指针数组)和环境字符串存放在进程空间的顶部(栈之上),所以该空间不能再增加。

5、实现跨函数的跳跃:setjmp()和longjmp()

相关函数定义如下:

#include <setjmp.h>
int setjmp(jmp_buf env);
    直接调用返回0,从longjmp返回则为非0
    指定要跳转到的点
void longjmp(jmp_buf env,int val);
    跳转到指定的点

注:jmp_buf用来存放恢复栈的所有信息,通常为全局变量,两个函数应为同一个jmp_buf。val为setjmp的返回值(一个setjmp可能对应多个longjmp,所以用
val区分是从哪里返回的)
在跳转时,全局、静态变量的值不变,对于自动变量要想其不变,可指定 volatile 属性。如 volatile int x;

6、查询/更改进程的资源限制

进程的资源限制通常在系统初始化时由0进程建立,相关函数如下:

#include <sys/resource.h>
int getrlimit(int resource,struct rlimit *rlptr);
    成功返回0,出错返回非0
int setrlimit(int resource,const struct rlimit *rlptr);
    成功返回0,出错返回非0

struct rlimit{
    rlim_t rlim_cur;
    rlim_t rlim_max;
}

更改进程的资源限制时规则:
- 任一进程都可将其软限制值改为小于等于其硬限制值
- 任一进程都可降低其硬限制值,但必须大于等于其软限制值,同时对于普通用户该操作不可逆
- 只有root可提高硬限制值

其中,RLIM_INFINITY 指定一个无限量的限制,resource 的取值如下:



注:资源限制影响到调用进程并由子进程继承。shell就是这个原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值