进程环境

一.程序的启动与终止

1.程序的启动    

      当内核要指向一个C程序时,会先启动一个启动例程,启动例程从内核取得命令行参数和环境变量的值,然后准备调用main函数。启动例程一般为会变语言编写,但若以C代码描述则为以下形势:exit(main(argc,argv));由此亦可看出当程序中main函数中以return num退出,则会回到启动例程,并根据终止码调用exit。

2.进程终止

1)正常终止与异常终止      

       进程终止可以分为正常终止与异常终止,其中正常终止包括5种情况:1)从main返回(return num 或 exit(num));2)调用exit(会先执行清理再返回内核,但是否冲洗还要取决于实现);3)调用_exit或_Exit(立即返回内核,可以直接调用,或由exit间接调用);4)最后一个线程从其启动例程返回。5)最后一个线程调用了pthread_exit。异常终止包括3种情况:1)调用about(产生SIGABOUT信号);2)接到一个信号;3)最后一个线程对取消请求做出响应(参博文《线程》

【注】:不管进程如何终止,最后都会执行内核中的同一代码段。这段代码为相应进程关闭所有打开的描述符,释放它们的存储器。

2)终止码

       我们调用exit时指定的整型参数,以及在main种以return返回的整型,被称为进程的终止状态或终止码。可以通过系统shell检查进程的结束状态。如以一个取得用户口令的程序举例,可以通过echo $?命令获得其进程终止码,如下图所示:

                                             

       由上述可知,进程返回终止码是必要的。以下情况会导致终止状态未定义:1)调用exit等函数时不指定终止状态;2)main函数执行了一个无返回值的return语句;3)main函数没有声明返回类型为整型(谭浩强版C中的毛病)。

3)设置终止处理程序

      我们可以使用函数atexit为进程注册一些终止处理程序,当进程调用exit进行退出时会首先以与注册顺序相反的顺序去调用注册的终止处理程序,某个函数可以被多次注册。APUE中的一张图十分清晰的反应了程序的启动与终止过程:

                       

 

二.C程序的存储空间布局

     C程序的空间布局一直由以下几部分组成,下面以图文的形式进行说明:

               

 

三.环境表和环境变量

       环境变量字符串的形式是name = value,内核并不查看这些字符串,它们的解释完全取决于各个应用程序,即环境变量是给各个应用程序用的。比如:登录时shell设置了HOME、USER等环境变量的值,又如设置了环境变量MAILPATH告诉一些程序去哪里查看邮件。且每个程序都有一张自己的环境变量表,可通过extern char** environ获取。

1.获取环境变量 

     访问环境变量有两种方式:通过environ访问环境变量表和使用函数getenv通关环境变量名获取环境变量值,一般应该使用getenv获取环境变量,而不是访问environ。访问environ的代码如下:

extern char** environ;
int main(int argc, char *argv[])
{
    for(char** p = environ; p != NULL; p++){
         std::cout<<*p<<std::endl;
    }
    return 0;
}

2.设置环境变量

      当我们改变环境变量时,只会影响当前进程及其之后创建或调用产生的任何子进程的环境。这是因为每个进程都有一份自己独立的环境变量表,存储在进程地址空间的顶部(可以参考第二部分的图),而fork出的子进程也会复制这张环境变量表。

     接下来说明一下如何设置环境变量表的,由于存储环境变量的位置位于进程地址空间的最高地址段,因此即不好向上扩展,也不好向下扩展(下面是栈)。当要修改某个环境变量的值的时候比较方便,若新的value长度少于旧的value,则只需将值放置到原先的地址空间。否则开辟一个新的空间用于存放新value,并将环境分配表中针对name的指针指向该空间。当要增加一个新的name-value对时,便会麻烦一些,如果是第一次增加则需要再堆内存中重新分配一张新的指针表,并将其中相应指针指向环境变量所在位置,即进程空间的顶端,接着再为新的name-value分配一个空间,并将新表中相应指针指向该处。若不是第一次增加,则调用realloc进行重新分配即可,再将指向新的name-value的指针放在表尾即可。

 

四.资源限制

     每个进程都有一组资源限制,可以通过getrlimit和setrlimit函数进行获取和设置进程资源。进程资源的限制分为软限制(当前设置的限制值)和硬限制(该资源的最大限制值),通过结构体struct rlimit进行表示。

struct rlimit {
    rlim_t rlim_cur;
    rlim_t rlim_max;
};

   在设置资源限制时需遵循以下原则:1)任一进程都可将软限制更改为小于等于其硬限制的值。2)任一进程都可降低其硬件限制,但必须大于或等于其软限制,但不可提高(降低后亦不可提升)。3)只有超级用户可以提高硬件资源限制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值