UNIX/Linux-进程环境(实例入门篇)

UNIX进程环境

当内核执行C程序时,在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址(由链接器设置的),启动例程从内核取得命令行参数和环境变量值,为调用main函数做好安排。

启动例程的逻辑就是:使得从main返回后立即调用exit函数。即:exit(main(argc, argv)) ;

(启动例程的作用就是把命令行参数传给main,在main结束时做一些清理工作)

 

1exit函数

有三个函数用于正常终止一个程序:

#include <stdlib.h>

void  exit(int status) ;

void  _Exit(int status) ;

#include <unistd.h>

void  _exit(int status) ;


_exit_Exit立即进入内核,exit则先执行一些清理处理(调用执行各终止处理程序,关闭所有标准I/O流等),然后进入内核。

exit函数总是执行一个标准I/O库的清理关闭操作:为所有打开流调用fclose函数,这会造成所有缓冲的输出数据都被冲洗。

main函数的return 0;等效于 exit(0) ;

 

2atexit函数

我们可以用atexit函数来登记终止处理函数,这些函数将由exit自动调用。

exit调用这些函数的顺序与它们登记时候的顺序相反。同一函数如若登记多次,则也会被调用多次。

#include <stdlib.h>

int  atexit(void (*func)(void)) ;

例如:

#include <stdio.h>
#include <error.h>
#include <stdlib.h> //包含atexit

static void My_exit1(void) ;
static void My_exit2(void) ;

int 
main(int argc, char** argv)
{
    //注册退出处理函数
    if (atexit(My_exit2) != 0)
    {
        perror("can't register My_exit2!\n") ;
    }
    if (atexit(My_exit1) != 0)
    {
        perror("can't register My_exit1!\n") ;
    }
    if (atexit(My_exit1) != 0)
    {
        perror("can't register My_exit1!\n") ;
    }

    printf("main is done!\n") ;
    exit(0) ;
}


static void
My_exit1(void)
{
    printf("first exit handler\n") ;
}

static void
My_exit2(void)
{
    printf("second exit handler\n") ;
}

环境表

每个程序都会接收到一张环境表。与参数表一样,环境表也是一个字符指针数组。其内容如:”HOME=/home/sar\0” “PATH=:/bin:usr/bin\0” “USER=sar\0” “LOGNAME=sar\0”

环境表(字符串的指针数组)和环境字符串通常存放在进程存储空间的顶部(栈之上)

全局变量environ则包含了该指针数组的地址:extern char** environ ;我们可使用此指针查看整个环境。

//用系统定义的全局变量environ指针,打印出进程的整个环境表。
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
 
int 
main(void)
{
    char** ptr ;
    extern char** environ ;

    for (ptr = environ; *ptr != 0; ptr++)
    {
        printf("%s\n", *ptr) ;
    }

    exit(0) ;
}

 

ISO C定义了一个函数getenv,可以用其取特定环境变量的值。

#include <stdlib.h>

char* getenv(const char* name) ;

此函数返回一个指针,它指向name=value字符串中的value

改变环境变量的值:

int  setenv(const char* name,  const char* value,  int rewrite) ;

name环境变量设置为value。如果在环境中name已经存在,那么若rewrite0,则先删除现有的定义;若rewrite0,则不删除其现有定义。

int  unsetenv(const char* name) ;

删除name的定义。

 

注意:我们能影响的只是当前进程及调用的任何子进程的环境,但不能影响父进程的全局变量。(环境变量就像进程的全局变量一样,子进程会得到它的一份副本。)

 

资源限制

每个进程都有一组资源限制,其中一些可以用getrlimitsetrlimit函数查询和更改

进程的资源限制通常是在系统初始化时由进程0建立的,然后每个后续进程继承。

#include <sys/resource.h>

int  getrlimit(int resource, struct rlimit * rlptr) ;

int  setrlimit(int resource, const struct rlimit * rlptr) ;

详细使用,略。

 

C程序的存储空间布局


a.out中还有若干其他类型的段,例如:包含符号表的段、包含调试信息的段以及包含动态共享库连接表的段等。这些部分并不装载到进程执行的程序映像中。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值