全部博文(842)
分类: LINUX
2012-03-04 17:38:18
进程环境
1.1 main函数
1.内核执行C程序的顺序:
A.调用一个特殊的启动例程。
B.可执行程序文件将此启动例程指定为程序的起始地址。
C.启动例程从内核取得命令行参数和环境变量值。
D.从main函数开始执行。
main函数原型:
int main(int argc, char *argv[])
1.2 进程终止
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. 终止处理程序:
头文件:
int atexit(void (*func)(void));
返回值:成功返回1,否则返回非零值
一个进程可以登记多达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-2 **********************
//终止处理程序的使用。使用到atexit函数
#include "apue.h"
static void my_exit1(void);
static void my_exit2(void);
int
main(void)
{
if(atexit(my_exit2) != 0)
printf("can not register my_exit2\n");
if(atexit(my_exit1) != 0)
printf("can not register my_exit1\n");
if(atexit(my_exit1) != 0)
printf("can not register my_exit1\n");
printf("main is done \n");
return 0;
}
static void my_exit1(void)
{
printf("first exit handler\n");
}
static void my_exit2(void)
{
printf("second exit handler\n");
}
结果:
main is done
first exit handler
first exit handler
second exit handler
注意:exit调用这些函数的顺序与它们登记时候的顺序相反,同一函数如果登记多次,则也会调用多次。而且主函数是先结束的,当然其实主函数还是应该是在清理函数后结束的,我这么觉得的。
***********************************************
1.3 命令行参数
例程2:
#include "apue.h"
int
main(int argc, char *argv[])
{
int i;
char **ptr;
extern char **environ;
for(i = 0;i < argc; i++ )
printf("argv[%d] : %s \n", i, argv[i]);
for(ptr = environ; *ptr != 0; ptr++)
printf("%s\n", *ptr);
return 0;
}
运行结果:
argv[0] : ./7-3
argv[1] : gong
argv[2] : fun1
argv[3] : fun2
SSH_AGENT_PID=2523
HOSTNAME=localhost.localdomain
TERM=xterm
SHELL=/bin/bash
HISTSIZE=50
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=20972290
USER=root
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
SSH_AUTH_SOCK=/tmp/ssh-XXmoci9Y/agent.2509
SESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/2509
USERNAME=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
INPUTRC=/etc/inputrc
PWD=/root/unixfile
XMODIFIERS=@im=Chinput
LANG=zh_CN.GB2312
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SHLVL=3
HOME=/root
LANGUAGE=zh_CN.GB18030:zh_CN.GB2312:zh_CN
GNOME_DESKTOP_SESSION_ID=Default
BASH_ENV=/root/.bashrc
LOGNAME=root
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0.0
G_BROKEN_FILENAMES=1
COLORTERM=gnome-terminal
XAUTHORITY=/root/.Xauthority
OLDPWD=/root/unixfile/db
_=./7-3
注意命令行参数的使用。
1.4 环境表
1. 环境表是一个字符指针数组,全局变量environ则包含了该指针数组的地址:
extern char ** environ;
2. 使用getenv和putenv函数来访问特定的环境变量。
使用environ指针来获得整个环境表。
1.5 C程序的存储空间布局
1. C程序的组成:
A. 正文段。这是由CPU执行的机器指令部分。
B. 初始化数据段。通常将此段称为数据段。它包含了程序中需明确地赋初值的变量。
C. 非初始化数据段。通常将此段称为bss段。在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
D. 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。
E. 堆。通常在堆中进行动态存储分配。
2. 图示,典型的存储器安排:
1.6 共享库
共享库使得可执行文件中不再需要包含公用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。
1.7 存储器分配
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。
1.8 环境变量
1. 函数原型
char *getenv(const char * name);
返回值:指向关联name的value值的指针,若没有找到返回NULL
int putenv(char *str);
返回值:成功返回0,否则返回非0值
int setenv(const char * name,const char *value,int rewrite); //rewrite为非0,则改变其值;若为0,其值不变。
返回值:成功返回0,否则返回非0值
int unsetenv(const char *name);
返回值:成功返回0,否则返回非0值
头文件:stdlib.h
函数功能:获取或设置环境变量
返回值:getenv返回指向与name关联的value的指针,若未找到则返回NULL。其余函数若成功则返回0,若出错则返回非0
1.9 setjmp和longjmp函数
1. 函数原型:
int setjmp(jmp_buf,env);
void longjmp(jmp_buf env,int val);
头文件:
返回值:setjmp若直接调用则返回0,若从longjmp调用返回则返回非0(其值是longjmp设置的val的值).
函数功能:执行非局部跳转。
使用方法:希望返回到的位置调用setjmp。需要跳转的地方调用longjmp。
2.示例:
*************** 例 7-2 ****************************
//演示使用setjmp和longjmp实行非局部跳转
//假设“i==2&&wrong2==1 ”和“i==4&&wrong4==1”时是错误,于是发生跳转
#include
#include
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
****************************************************
1.10 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);
头文件:
返回值:若成功返回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
#include
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;
}
*********************************************************