进程终止的方式:
1,正常终止:
从main返回;
调用exit;
调用_exit;
2,异常终止:
调用abort;
由一个信号终止。
exit和_exit的差异:
#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);
其中,exit会先执行一些清理工作,而_exit则直接进入内核。
终止处理函数:exit handler
ANSI C规定,一个进程可以登记多至32个函数。
登记方法:
#include <stdlib.h>
int atexit(void (*func)(void));
exit会以登记顺序相反的顺序调用这些函数。
环境表
extern char** environ;
存取方法:
#include <stdlib.h>
char* getenv(const char* name);
int putenv(char* string);
int setenv(const char* name, const char* value, int overwrite);
int unsetenv(const char* name);
int clearenv(void);
设置环境变量的难点在于环境变量处于内存的顶端,需要增加空间的时候处理逻辑比较重要。如果需要内存的话就会把环境表移到堆中去。
c程序的存储空间布局:
可以用size命令查看text,data,bss
共享库:
减少了每个可执行文件的长度,但增加了一些运行时间开销。
存储器分配:
#include <stdlib.h>
void* malloc(size_t size);
void* calloc(size_t nobj, size_t size);
void* realloc(void* ptr, size_t size);
void* free(void* ptr);
大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息----分配块的长度,指向下一个分配块的指针等等。如果写过一个已分配区的文段,则会改写后一块的管理信息,这种错误是灾难性的。
另一个致命错误是释放一个已经释放的块。
alloca函数在栈上分配空间,并自动释放:
#include <alloca.h>
void* alloca(size_t size);
非局部跳转----setjmp和longjmp函数。
非局部跳转表示在栈上跳过若干调用帧。
#include <setjmp.h>
int setjmp(jmp_buf env);
int longjmp(jmp_buf env, int val);
存放在存储器中的变量将具有longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp时的值。
ex:
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
static void f1(int,int,int);
static void f2(void);
static jmp_buf jmpbuffer;
int main(void){
int count;
register int val;
volatile int sum;
count=2;
val=3;
sum=4;
if(setjmp(jmpbuffer)!=0){
printf("after longjmp:count=%d, val=%d, sum=%d\n",count,val,sum);
exit(0);
}
count=97;
val=98;
sum=99;
f1(count,val,sum);
}
static void f1(int i, int j, int k){
printf("in f1():count=%d, val=%d, sum=%d\n",i,j,k);
f2();
}
static void f2(void){
longjmp(jmpbuffer,1);
}
结果:
hoperun@rh-ub063:/local/unix_environment$ gcc -O testjmp.c -o testjmp
hoperun@rh-ub063:/local/unix_environment$ testjmp
in f1():count=97, val=98, sum=99
after longjmp:count=2, val=3, sum=99
hoperun@rh-ub063:/local/unix_environment$ gcc testjmp.c -o testjmp
hoperun@rh-ub063:/local/unix_environment$ testjmp
in f1():count=97, val=98, sum=99
after longjmp:count=97, val=98, sum=99
资源限制:
规则:
1.任何一个进程都可将一个软限制更改为小于或等于其硬限制。
2.任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。不可逆。
3.只有超级用户可以提高硬限制。
资源限制影响到调用进程并由其子进程继承。
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit* rlim);
int setrlimit(int resource, const struct rlimit* rlim);
struct rlimit
{
/* The current (soft) limit. */
rlim_t rlim_cur;
/* The hard limit. */
rlim_t rlim_max;
};
例子:
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#define doit(name) pr_limits(#name,name);
static void pr_limits(char*, int);
int main(void){
doit(RLIMIT_CORE);
doit(RLIMIT_CPU);
doit(RLIMIT_DATA);
doit(RLIMIT_FSIZE);
doit(RLIMIT_STACK);
#ifdef RLIMIT_MEMLOCK
doit(RLIMIT_MEMLOCK);
#endif
#ifdef RLIMIT_NOFILE
doit(RLIMIT_NOFILE);
#endif
#ifdef RLIMIT_OFILE
doit(RLIMIT_OFILE);
#endif
#ifdef RLIMIT_NPROC
doit(RLIMIT_NPROC);
#endif
#ifdef RLIMIT_RSS
doit(RLIMIT_RSS);
#endif
#ifdef RLIMIT_VMEM
doit(RLIMIT_VMEM);
#endif
exit(0);
}
static void pr_limits(char* name, int resource){
struct rlimit limit;
if(getrlimit(resource, &limit)<0){
printf("getrlimit error for %s", name);
}
printf("%-14s ",name);
if(limit.rlim_cur == RLIM_INFINITY){
printf("(infinity) ");
}else{
printf("%10ld ", limit.rlim_cur);
}
if(limit.rlim_max == RLIM_INFINITY){
printf("(infinity)\n");
}else{
printf("%10ld\n", limit.rlim_max);
}
}
unbuntu下执行结果:
hoperun@rh-ub063:/local/unix_environment$ gcc rlimittest.c -o rlimittest
hoperun@rh-ub063:/local/unix_environment$ rlimittest
RLIMIT_CORE 0 (infinity)
RLIMIT_CPU (infinity) (infinity)
RLIMIT_DATA (infinity) (infinity)
RLIMIT_FSIZE (infinity) (infinity)
RLIMIT_STACK 8388608 (infinity)
RLIMIT_MEMLOCK 65536 65536
RLIMIT_NOFILE 1024 1024
RLIMIT_OFILE 1024 1024
RLIMIT_NPROC (infinity) (infinity)
RLIMIT_RSS (infinity) (infinity)
hoperun@rh-ub063:/local/unix_environment$