进程环境

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");

}
原文地址:https://www.cnblogs.com/xiaofeifei/p/4082487.html