Linux编程之进程的环境

进程是非常重要的概念,学习进程自我感觉最好的学习方式是从进程的结构上去理解进程,先从浅再入深,循环渐进,下面就总结一下最近对进程的环境的学习总结吧。

(一)程序的存储空间布局

每一个程序都包括以下部分:
1. 正文段 :CPU执行的机器指令部分,通常是可以共享的,并且是只读的以防止程序意外修改。
2. 已初始化数据段: 包含明确赋初值的变量。
3. 未初始化数据段: 又称为BBS段,函数外为初始化的变量。
4. 栈: 保存自动变量以及每次函数调用时所需保存的信息。
5. 堆:常用与动态份分配存储空间。
6. 命令行参数与环境变量:一些程序需要的环境变量。
其存储空间安排如图所示:

(二)进程的关闭
正常终止: 
(1)从main函数返回。     
(2)调用exit()函数,退出时执行清理工作。  
(3)调用_exit()函数或者_Exit()函数,直接进入内(即直接退出)。     
(4)最后一个线程从其启动例程返回。    
(5)从最后一个线程调用pthread_exit()函数。   
异常终止:
(1)调用abort()函数。   
(2)接受到一个信号。  
(3)最后一个线程最取消请求做出响应。   

注意: return退出与exit退出是不一样的,return是退出该函数,而exit是退出该进程,但是当在mian函数时我自己感觉他们是相同的
例如:

#include <stdio.h>
#include <stdlib.h>

void fun1()
{
    printf("jingtiki\n");
    return ;
}
void fun2()
{
    printf("jjjjjjjj\n");
    exit(0);
}
int main()
{
    fun2();//直接退出main
    fun1();//只是退出fun1函数,main继续运行
    printf("hhhhhh\n");
    return 0;
}

另外: atexit()函数 即退出时先执行处理函数

   #include <stdlib.h>
   int atexit(void (*function)(void));

例如:

#include <stdio.h>
#include <stdlib.h>
void fun1()
{
    printf("fun1\n");
}
void fun2()
{
    printf("fun2\n");
}   
int main()
{
    if( atexit(fun1) != 0 )
    {
        perror("atexit err\n");
        exit(EXIT_FAILURE);
    }
    if( atexit(fun2) != 0 )
    {
        perror("atexit err\n");
        exit(EXIT_FAILURE);
    }

    if( atexit(fun2) != 0 )
    {
        perror("atexit err\n");
        exit(EXIT_FAILURE);
    }
    return 0;
}
(三)环境变量
(1)环境表

每此运行程序都会有一张环境表,与参数表一样,环境表也是一个字符串指针数组,其中每个指针包含以NULL结束的c字符串的地址,全局变量environ则包含了指针数组的地址。图示如下:

(2)获得环境变量
 #include <stdlib.h>
 char *getenv(const char *name);

例如:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    const char *path = "PATH";
    char * p = getenv("PATH");
    if( p == NULL )
    {
        perror("get environment err\n");
        exit(EXIT_FAILURE);
    }

    printf("PATH: %s",p);

    return 0;
}
(3)设置环境变量
   #include <stdlib.h>
   int putenv(char *string); 

   #include <stdlib.h>
   int setenv(const char *name, const char *value, int overwrite);
   int unsetenv(const char *name);
  • 如果putenv要设置的环境变量已经存在,则使用现定义。
  • 如果setenv要设置的环境变量name已经存在,那么若rewrite非0,则删除现有的定义,那么若rewrite为0,则不删除现有的定义。
  • unsetenv删除name的定义。
    注意设置的环境变量只对该程序有效。
(四)setjmp函数与longjmp函数
   #include <setjmp.h>
   int setjmp(jmp_buf env);
   int sigsetjmp(sigjmp_buf env, int savesigs);
(1)作用: 检测深层函数的错误信息
(2)实现步骤:
  • 首先调用setjmp函数获得此时进程的栈状态,有两个返回值,第一次是直接调用所以返回0。
  • 在深层函数中调用longjmp函数,如果该函数中出现错误,将会返回主函数,此时造成setjmp重新返回,返回值为val。

例如:

#include <stdio.h>
#include <setjmp.h>
#define MAXLINE 512
jmp_buf jmp_buffer;

void fun2(char buff[])
{
    int i = 1;

    if( 1 == i )
    {
        printf("fun2 , longjmp()\n");
        longjmp(jmp_buffer,2);
    }
}
void fun1(char buff[])
{
    printf("fun1 , buff: %s\n",buff);   
    fun2(buff);
}
int main()
{
    char buff[MAXLINE];
    int flag,val;
    if( (val = setjmp(jmp_buffer)) != 0 )
    {
        printf("err\n");
    }
    printf("setjmp:%d\n",val);
    while( fgets(buff,MAXLINE,stdin) != NULL )
    {
        fun1(buff);
    }   
    return 0;
}

注意: 错误返回后的变量值有的是返回原先的状态,有得是内存函数的改变后的值,只是根据变量属性不同会有所改变。如果不想要返回到main函数时数值回滚,则可以将其定义为volatile属性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值