• 进程环境


    main函数

    内核在通过exec执行main函数之前还会这行启动程序,启动程序地址通常由编译器和链接器在可执行程序中指定。启动程序从内核传递命令行参数以及环境变量传递给main函数以及做一些启动main函数的准备。

    进程终止

    正常终止:

    从main函数返回

    调用exit,_exit,_Exit

    进程中最后一个线程返回

    进程中最后一个线程执行pthread_exit

    异常终止:

    信号终止

    最后一个线程对pthread_cancle作出响应

    调用abort

    退出函数

    _exit(),_Exit()立即退出返回到内核,exit()执行一些清理动作然后返回内核。ISO允许进程注册清理函数,在进程退出的时候以相反的顺序执行这些清理函数,注册多少次执行多少次。

    #include <stdlib.h>
    void exit(int status);
    void _Exit(int status);
    #include <unistd.h>
    void _exit(int status);
    
    int atexit(void (*func)(void));
    //Returns: 0 if OK, nonzero on error

    ISO C规范规定exit函数先执行清理函数然后调用fclose关闭所有标准流。Posix规定如果执行任何exec函数,那么注册的清理函数都会被清除。

    环境变量列表

    每个程序除了被传递命令行参数外还传递环境变量列表,列表元素是个以\0结尾的字符串,字符串格式如:Key=Value,列表地址是个全局变量:

    extern char **environ;

    C程序内存布局

    C程序一般由文本段,初始化数据段,未初始化数据段,堆,栈,命令行参数和环境变量组成。文本段是机器执行的指令,一般是只读的且共享的,初始化数据指初始化的变量等,未初始化数据在程序执行前由内核初始化为0 或空指针。典型的内存布局如下:

    典型内存空间布局

    size命令可以打印程序文件代码段,初始化数据段,为初始化数据段大小。

    内存分配

    #include <stdlib.h>
    void *malloc(size_t size);
    void *calloc(size_t nobj, size_t size);
    void *realloc(void *ptr, size_t newsize);
    //All three return: non-null pointer if OK, NULL on error
    void free(void *ptr);

    malloc分配指定大小的内存,内存初始值是不能确定

    calloc分配nobj个size大小的内存,如果是一般变量内存初始化为0,指针不一定初始化为NULL

    realloc增加或减少之前分配的内存,如果增加内存,那么会将以前的内容移动到新的地方,新增加的部分初始值是不确定的。如果ptr为空同malloc.

    环境变量

    获取指定的环境变量值:

    #include <stdlib.h>
    char *getenv(const char *name);
    //Returns: pointer to value associated with name, NULL if not found

    设置环境变量:

    #include <stdlib.h>
    int putenv(char *str);//str is like name=value,if name already exist ,remove it first
    //Returns: 0 if OK, nonzero on error
    int setenv(const char *name, const char *value, int rewrite);//nozero  rewite, 0 not
    int unsetenv(const char *name);//remove the name=value do not care weather name exist
    //Both return: 0 if OK, −1 on error

    局部跳转(超级goto)

    #include <setjmp.h>
    int setjmp(jmp_buf env);
    //Returns: 0 if called directly, nonzero if returning from a call to longjmp
    void longjmp(jmp_buf env, int val);

    在希望跳转到的地方调用setjmp,直接调用将返回0,jum_buf类型是一种特殊数组,包含了能够恢复调用longjump时的栈状态所有信息。在我们希望跳转的时候传递两个参数给longjmp一个是前面的env后面一个是非0值,这个值将作为setjmp的返回值。

    在longjmp返回到setjmp所在函数后,setjmp所在函数中栈变量和寄存器变量值是不确定的。如果想使用栈变量又不想回滚它的值将他定义为volatile.申明为全局变量或者静态变量的值在执行longjmp时不变。

    #include <stdio.h>
    #include <stdlib.h>
    #include <setjmp.h>
    
    static void f1(int ,int,int,int);
    static void f2();
    static jmp_buf jmpbuffer;
    static int globval;
    
    int main(int argc,char* argv[])
    {
        int autoval;
        register int regival;
        volatile int volaval;
        static int staval;
    
        globval =1;autoval=2;regival=3;volaval=4;staval=5;
    
        if(setjmp(jmpbuffer)!= 0)
        {
            printf("after longjmp:\n");
            printf("globval = %d,autoval=%d,regival=%d,volaval=%d,staval=%d\n",\
                    globval,autoval,regival,volaval,staval);
            exit(0);
        }
    
        globval = 95;autoval=96;regival=97;volaval=98;staval=99;
    
        f1(autoval,regival,volaval,staval);
    
        exit(0);
    }
    
    static void f1(int i,int j,int k,int l)
    {
        printf("int f1:\n");
        printf("globval=%d,autoval=%d,regival=%d,volaval=%d,staval=%d\n",globval,i,j,k,l);
    
        f2();
    }
    
    static void f2()
    {
        longjmp(jmpbuffer,1);
    }

    执行结果:

    hero@powerPC:~$ gcc -o test test.c
    hero@powerPC:~$ ./test
    int f1:
    globval=95,autoval=96,regival=97,volaval=98,staval=99
    after longjmp:
    globval = 95,autoval=96,regival=3,volaval=98,staval=99
    hero@powerPC:~$ gcc -O2 -o test test.c
    hero@powerPC:~$ ./test
    int f1:
    globval=95,autoval=96,regival=97,volaval=98,staval=99
    after longjmp:
    globval = 95,autoval=2,regival=3,volaval=98,staval=99

    优化执行代码和不优化执行代码,结果不一样。全局变量,静态变量,寄存器变量不受优化影响。

    资源限制

    每个进程都有一组资源限制,其总一些可以通过gerrlimit和setrlimit来查询和更改。

    #include <sys/resource.h>
    int getrlimit(int resource, struct rlimit *rlptr);
    int setrlimit(int resource, const struct rlimit *rlptr);
    //Both return: 0 if OK, −1 on error

    rlimit结构如下:

    struct rlimit {
                   rlim_t rlim_cur;  /* Soft limit */
                   rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
               };

    在更改资源限制时必须遵循下面规则:

    任何一个进程可以将一个软限制指改为小于等于其硬限制值

    任何一个进程都可降低硬限制值,但是必须大于等于软限制值。这中更改对普通用户是不可逆的

    超级用户可以提高硬限制值

    #include <stdio.h>
    #include <sys/resource.h>
    
    #define FMT "%10lld "
    
    #define doit(name) pr_limits(#name,name)
    
    static void pr_limits(char*,int);
    
    int main(int argc,char* argv[])
    {
        doit(RLIMIT_AS);
        doit(RLIMIT_CORE);
        doit(RLIMIT_CPU);
        doit(RLIMIT_DATA);
        doit(RLIMIT_FSIZE);
        doit(RLIMIT_NOFILE);
        doit(RLIMIT_RSS);
    
    
    }
    
    static void pr_limits(char* name,int resource)
    {
        struct rlimit limit;
    
        if(getrlimit(resource,&limit) < 0)
        {
            printf("get resource limit faild\n");
            return ;
        }
    
        printf("%-14s  ",name);
    
        if(limit.rlim_cur == RLIM_INFINITY )
        {
            printf("infility\n");
        }else
        {
            printf(FMT,(long long)limit.rlim_cur);
        }
        if(limit.rlim_max == RLIM_INFINITY )
        {
            printf("infility\n");
        }else
        {
            printf(FMT,(long long)limit.rlim_max);
        }
    
        printf("\n");
    
    }
  • 相关阅读:
    poj1573
    poj2632
    poj2993 poj2996
    poj3295 构造法
    poj2965枚举
    poj1753 枚举
    poj942Paths on a Grid
    poj1019
    poj1321棋盘问题
    博客园访问量有些小,我就没有必要在复制一份了,博客园就这样吧,继续CSDN了。
  • 原文地址:https://www.cnblogs.com/xiaofeifei/p/4082487.html
Copyright © 2020-2023  润新知