进程环境

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



}

你可能感兴趣的:(进程)