进程环境

进程环境

一个exe的生命周期

mark

启动

内核使用exec启动C函数的app,execmain之前会调用另一个函数_start,负责从内核那里接收命令行参数和环境变量,设置好这些之后再调用main函数。

退出

进程正常终止:

  • 1.从main函数返回,即retrun 0;
  • 2.调用exit,即在main函数内或者其他会被main调用的函数体内调用exit();
  • 3.调用_exit_Exit,即在main函数内或者其他会被main调用的函数体内调用_exit或_Exit;,
  • 4.最后一个线程从其所在进程返回;
  • 5.最后一个线程在其所在进程调用pthread_exit

进程异常终止:

  • 6.调用abort
  • 7.进程接收到信号;
  • 8.进程中最后一个线程最取消做出响应。

可以使用exit、_exit_Exit函数来正常终止程序,第一个函数和后面两个函数区别是,exit会进行一些资源清理工作,然后返回内核,而_exit和_Exit则不清理立即返回内核_exit和Exit等价

注意除非通过return语句来返回,或者通过exit( )来退出才会调用清理函数,_exit和_Exit函数是不会调用清理函数的

注册自己的清理函数

int atexit(void (*function)(void));

这个函数在exitmain的return才会调用,最多可以注册32个,重复注册的函数会重复调用,先注册的最后执行,类似于栈

void exit1()
{
    printf("exit 1\n");
}
void exit2()
{
    printf("exit 2\n");
}
void exit3()
{
    static int a=0;
    printf("exit 3,static num=%d\n",a++);
}

int main(int argc, char const *argv[])
{
    atexit(exit1);
    atexit(exit2);
    atexit(exit3);
    atexit(exit3);
    printf("main in\n");
    return 0;
}

//main in
//exit 3,static num=0
//exit 3,static num=1
//exit 2
//exit 1

环境变量

char *getenv (const char *name);
int putenv (char *string);
int setenv (const char *name, const char *value, int replace);
int unsetenv (const char *name);

跨函数跳转

// 联合使用的
int setjmp (jmp_buf env);
void longjmp (struct jmp_buf_tag env[1], int val);

第一次调用setjmp函数时,其返回值为0,后续调用返回值由传入longjmp的val值决定

  1. 在想要跳转的地方设置int setjmp (jmp_buf env),变量存放了当前的栈信息,一般是全局变量
  2. 在需要跳出也就是goto的地方放置longjmp (struct jmp_buf_tag env[1], int val),第一个参数就是1中的栈信息,第二个参数是1中的返回值,其实也就是可能在多处设置了setjmp ,可以选择跳到哪里去
  3. 这里的跳转还是有点麻烦的,全局变量和静态变量不受影响因为不在栈中,其他的情况有点不太好确认的,与编译器优化也有关系
  4. 没必要研究这个了, https://blog.csdn.net/qq_34793133/article/details/80475323, c++可以使用异常

资源限制

int getrlimit (rlimit_resource_t resource, struct rlimit *rlimits);
int setrlimit (rlimit_resource_t resource, const struct rlimit *rlimits);
posted @ 2019-11-30 15:14  zongzi10010  阅读(186)  评论(0编辑  收藏  举报