本章节讲诉整个进程生命周期的方方面面,包括main 函数,进程终止方式,命令行参数,内存布局,动态库静态库,环境变量以及资源操作。顺带还解释了longjmp,setjmp函数,以及几种变量类型。
1. main 函数
int main(int argc,char* argv[])
main 函数启动时候,从内核取得命令行参数和环境表项。
2. 进程终止方式
五种终止方式: exit(),_exit(), return ,abort, 还有其他信号比如SIGSTOP等等。
exit()执行些IO的清理动作,而_exit()则直接进入内核。如下代码,则可很清楚的看清楚二者之间的区别。
#include
#include
#include
int main(int argc, char* argv[])
{
printf("Should print if exit() or _exit()\n");
printf("Should print if exit()");
//exit(1);
_exit(1);
}
#include
#include
#include
#include
static void f1(void)
{
printf("In f1 function\n");
}
static void f2(void)
{
printf("In f2 function\n");
}
int main(int argc, char* argv[])
{
if(atexit(f1)!=0 || atexit(f2)!=0 || atexit(f2)!=0)
{
printf("Register atexit error. errno=%d, reason : %s\n", errno, strerror(errno));
return 0;
}
return 1;
}
#include
int main(int argc, char* argv[])
{
int i ;
//for(i=0;i
环境表存储在进程全局变量 environ 中, 是一个字符串数组,最后一个以NULL结束。所以可以采用如下方式遍历:
#include
int main(int argc, char* argv[])
{
extern char** environ;
int i;
for(i=0;environ[i]!=NULL;i++)
printf("%s\n", environ[i]);
}
c程序存储空间包含如下几部分:
从低地址到高地址空间排列分别为: text段,data段,bss段(由exec设为0),堆段和栈段。
6. 共享库。分为动态链接和静态链接
静态链接,可移植性好,但占用空间也大。下面是linux平台下创建使用静态库的demo.
动态库文件staticlib.c,定义了一个全局变量和一个全局函数。
int global =1;
int f(int x)
{
return x*x;
}
编译目标文件并压制动态库,这样便得到了 libstaticlib.a 的静态库文件
gcc -c staticlib.c
ar -crv libstaticlib.a staticlib.o
编写main 函数文件,testdota.c ,并链接静态库。
int f(int);
extern int global;
int main(int argc, char* argv[])
{
printf("result is %d\n, global =%d\n",f(10), global);
}
gcc testdota.c -L ./ -lstaticlib
下面来看下动态库,动态库省空间,运行时候才调用。但移植性不如静态库好。
编写动态库程序dynamic.c
int global =1;
int f(int x)
{
return x*x*x;
}
testdyn.c
#include
int f(int);
extern int global;
int main(int argc, char* argv[])
{
printf("result is %d\n, global =%d\n",f(10), global);
}
gcc -fPIC -c dynamic.c
gcc -shared -o libdynlib.so dynamic.o
gcc testdyn.c -L ./ -ldynlib
malloc, realloc,calloc, free 以及不用操心释放的calloca
8. 环境变量
char* getenv(const char* name);
int putenv(const char* str);
int setenv(const char* name, const char* value, int rewrite);
void unsetenv(const char* name);
操纵环境变量的例子
#include
#include
int main(int argc, char* argv[])
{
extern char** environ;
int i,res;
printf("****************Before process enviroment****************\n");
for(i=0;environ[i]!=NULL;i++)
printf("%s\n", environ[i]);
char* homep;
homep = getenv("HOME");
printf("home is %s\n", homep);
res = putenv("TESTENV=a test");
res = setenv("TESTENV2","a test of env2", 1);
printf("****************After process enviroment****************\n");
for(i=0;environ[i]!=NULL;i++)
printf("%s\n", environ[i]);
unsetenv("TESTENV");
printf("****************After unset enviroment****************\n");
for(i=0;environ[i]!=NULL;i++)
printf("%s\n", environ[i]);
}
setjmp 和longjmp提供跨函数跳转的功能。longjmp跳转后,程序将丢弃原来的调用栈二直接到设置jmp_buf 的位置。
jmp会造成非volatile 变量值的失真。 此段代码能正确显示的是因为定义的变量为全局变量。
#include
#include
#include
jmp_buf buf;
int count =97;
int val = 98;
volatile int sum = 99;
void f();
int main()
{
printf("count=%d,val =%d, sum=%d\n", count, val,sum);
if(setjmp(buf)!=0)
printf("jmp from other place\n");
else
f();
printf("count=%d,val =%d, sum=%d\n", count, val,sum);
}
void f()
{
printf("in function f\n");
count++;
val++;
sum++;
longjmp(buf,1);
}
来看下面这段代码, 变量失真了。
#include
#include
#include
jmp_buf buf;
void f();
void g();
int main()
{
int count =97;
register int val = 98;
volatile int sum = 99;
printf("count=%d,val =%d, sum=%d\n", count, val,sum);
if(setjmp(buf)!=0)
printf("count=%d,val =%d, sum=%d\n", count, val,sum);
else
{
count++;
val++;
sum++;
f();
}
}
void f()
{
g();
}
void g()
{
longjmp(buf,1);
}
10. getrlimit和setrlimit
设置和获得资源的最大值,比如core数量,进程打开文件的句柄数目等等。只有root用户才可以改变硬限制值。
int getrlimit(int source,struct rlimit* ptr)
int setrlimit(int source, const struct rlimit* ptr)
struct rlimit
{
rlim_t rlim_cur;
rlim_t rlim_max;
}
书上的打印各个资源限制的代码:
#include
#include
#include
#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);
exit(0);
}
static void pr_limits(char* name, int resource)
{
struct rlimit limit;
if(getrlimit(resource,&limit)<0)
{
printf("get resource %s error",name );
return;
}
printf("%-14s ",name);
if(limit.rlim_cur ==RLIM_INFINITY)
printf("(infinite) ");
else
printf("%10ld ", limit.rlim_cur);
if(limit.rlim_max ==RLIM_INFINITY)
printf("(infinite) \n");
else
printf("%10ld \n", limit.rlim_max);
}