第七章 进程环境
7.1 引言
7.2 main函数
1.内核执行C程序的顺序:
A.调用一个特殊的启动例程。
B.可执行程序文件将此启动例程指定为程序的起始地址。
C.启动例程从内核取得命令行参数和环境变量值。
D.从main函数开始执行。
7.3 进程终止
1.进程终止有8种方式,其中:
5种正常方式:A.从main返回
B.调用exit
C.调用_exit或_Exit
D.最后一个线程从其启动例程返回
E.最后一个线程调用pthread_exit
3种异常终止:A.调用abort
B.接到一个信号并终止
C.最后一个线程对取消请求做出响应
2.有三个函数用于正常终止一个程序:_exit和_Exit立即进入内核,exit则先执行一些清理处理。
3.终止状态的两种情况:
一.下面3中情形的终止状态是为定义的:
A.若调用这些退出函数时不带终止状态。
B.main执行了一个无返回值的return语句。
C.main没有声明返回类型为整型。
二.下面的情形的终止状态是0:
若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。
注意:exit(0)等价于return(0)。
4. 终止处理程序:一个进程可以登记多达32个终止处理程序函数,将由exit自动调用。使用atexit函数来登记这些函数。exit调用这些
函数的顺序与它们登记时候的顺序相反,同一函数如果登记多次,则也会调用多次。
5. 图示:一个c程序是如何启动,以及它可以终止的方法:
6. 函数原型:
void exit(int status);
void _Exit(int status);
头文件:stdlib.h
函数功能:正常终止一个程序。
void _exit(int status);
头文件:unistd.h
函数功能:正常终止一个程序。
7. 示例:
******************** 例 7-1 **********************
//终止处理程序的使用。使用到atexit函数
#include <stdio.h>
static void exit1(void)
{
printf("exit1/n");
}
static void exit2(void)
{
printf("exit2/n");
}
int main()
{
atexit(exit1);
atexit(exit2);
atexit(exit2);
printf("main done!/n");
return 0;
}
***********************************************
7.4 命令行参数
7.5 环境表
1. 环境表是一个字符指针数组,全局变量environ则包含了该指针数组的地址:
extern char ** environ;
2. 使用getenv和putenv函数来访问特定的环境变量。
使用environ指针来获得整个环境表。
7.6 C程序的存储空间布局
1. C程序的组成:
A. 正文段。这是由CPU执行的机器指令部分。
B. 初始化数据段。通常将此段称为数据段。它包含了程序中需明确地赋初值的变量。
C. 非初始化数据段。通常将此段称为bss段。在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
D. 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。
E. 堆。通常在堆中进行动态存储分配。
2. 图示,典型的存储器安排:
7.7 共享库
共享库使得可执行文件中不再需要包含公用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。
7.8 存储器分配
1. malloc函数:分配指定字节数的存储区。此存储区中的初始值不确定。
calloc函数:为指定数量和指定长度的对象分配存储空间,该空间每一位都初始化为0.
realloc函数:更改以前分配区的长度(增加或减少),而新增区域内的初始值则不确定。
注:使用sbrk系统调用实现。
2. 函数原型:
void *malloc(size_t size);
void *calloc(size_t nobj,size_t size);
void *realloc(void *ptr,size_t newsize);
void free(void *ptr);
头文件:stdlib.h
返回值:前三个函数,若成功则返回非空指针,若出错则返回NULL。
7.9 环境变量
1. 函数原型
char *getenv(const char * name);
int putenv(char *str);
int setenv(const char * name,const char *value,int rewrite); //rewrite为非0,则改变其值;若为0,其值不变。
int unsetenv(const char *name);
头文件:stdlib.h
函数功能:获取或设置环境变量
返回值:getenv返回指向与name关联的value的指针,若未找到则返回NULL。其余函数若成功则返回0,若出错则返回非0
7.10 setjmp和longjmp函数
1. 函数原型:
int setjmp(jmp_buf,env);
void longjmp(jmp_buf env,int val);
头文件:setjmp.h
返回值:setjmp若直接调用则返回0,若从longjmp调用返回则返回非0(其值是longjmp设置的val的值).
函数功能:执行非局部跳转。
使用方法:希望返回到的位置调用setjmp。需要跳转的地方调用longjmp。
2.示例:
*************** 例 7-2 ****************************
//演示使用setjmp和longjmp实行非局部跳转
//假设“i==2&&wrong2==1 ”和“i==4&&wrong4==1”时是错误,于是发生跳转
#include <stdio.h>
#include <setjmp.h>
jmp_buf jmpbuffer;
int wrong2=1;
int wrong4=1;
void dochar(int i)
{
if(i==2&&wrong2==1)
{
wrong2=0;
longjmp(jmpbuffer,2);
}
if(i==4&&wrong4==1)
{
wrong4=0;
longjmp(jmpbuffer,4);
}
printf("i=%d/n",i);
}
void doline(int i)
{
dochar(i);
}
int main()
{
int setReturn;
int i=0;
if((setReturn=setjmp(jmpbuffer))!=0)
{
printf("error,return=%d/n",setReturn);
}
for(i=0;i<=5;i++)
{
doline(i);
}
return 0;
}
运行结果:
root@BDAMA:~/study# ./161
i=0
i=1
error,return=2
i=0
i=1
i=2
i=3
error,return=4
i=0
i=1
i=2
i=3
i=4
i=5
****************************************************
7.11 getrlimit和setrlimit函数
1. rlimit结构体:
struct rlimit
{
rlim_t rlim_cur; /* The current (soft) limit. */
rlim_t rlim_max; /* The hard limit. */
};
2.更改资源限制时,须遵守的3条规则:
A. 任何一个进程都可将一个软限制值改为小于或等于其硬限制值。
B. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种限制对普通用户是不可逆的。
C. 只有超级用户进程可以提高硬限制值。
3. 函数原型
int getrlimit(int resource,struct rlimit *rlptr);
int setrlimit(int resource,const struct rlimit *rlptr);
头文件:sys/resource.h
返回值:若成功返回0,若出错返回非0值。
函数功能:获取或修改资源的限制值。
4. 资源参数(getrlimit函数和setrlimit函数的resource的值)
RLIMIT_CPU //Per-process CPU limit, in seconds.
RLIMIT_FSIZE //Largest file that can be created, in bytes.
RLIMIT_DATA // Maximum size of data segment, in bytes.
RLIMIT_STACK //Maximum size of stack segment, in bytes.
RLIMIT_CORE //Largest core file that can be created, in bytes.
RLIMIT_RSS //Largest resident set size, in bytes.
RLIMIT_NOFILE //Number of open files.
RLIMIT_AS //Address space limit.
RLIMIT_NPROC //Number of processes.
RLIMIT_MEMLOCK //Locked-in-memory address space.
RLIMIT_LOCKS //Maximum number of file locks.
RLIMIT_SIGPENDING //Maximum number of pending signals.
RLIMIT_MSGQUEUE //Maximum bytes in POSIX message queues.
RLIMIT_NICE //Maximum nice priority allowed to raise to.
RLIMIT_RTPRIO //Maximum realtime priority allowed for non-priviledged processes.
RLIMIT_NLIMITS
5. 示例:
********************** 例 7-3 ***************************
//获取和修改资源限制的值
#include <stdio.h>
#include <sys/resource.h>
int main()
{
struct rlimit prl;
getrlimit(RLIMIT_DATA,&prl);
printf("rlim_cur=%lu,rlim_max=%lu/n",prl.rlim_cur,prl.rlim_max);
prl.rlim_cur=100;
prl.rlim_max=200;
if(setrlimit(RLIMIT_DATA,&prl)!=0)
{
printf("setrlimit wrong!/n");
}
getrlimit(RLIMIT_DATA,&prl);
printf("rlim_cur=%lu,rlim_max=%lu/n",prl.rlim_cur,prl.rlim_max);
return 0;
}
*********************************************************
链接:ttp://blog.csdn.net/wyjlovec/archive/2009/10/06/4635650.aspx
作者:wyjlovec
QQ:294448030