进程的退出方式,环境表的操作,在内存中布局和非局部跳转

进程ID:
每个linux进程都一定有一个唯一的数字标识符,称为进程ID(总是一个非负整数)

进程终止:
正常终止:
1.从Main返回(return)
2.调用exit (标准库)
3.调用_exit或_Exit (内核提供)
4.最后一个线程从启动例程返回
5.最后一个线程调用pthread_exit
异常终止:
调用abort(信号相关)
接收到一个信号并终止(信号相关)
最后一个线程对取消请求做相应
exit与_exit() 区别 是否刷新缓存区
flush I/O
atexit 函数

exit:先刷新缓存区,然后结束进程 ,在结束之前调用信号注册函数atexit
_exit:不刷新缓存区 直接从进程退出,由内核直接结束进程 没经过atexit

exit.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>int main(int argc,char *argv[]){if(argc<3){        fprintf(stderr, "usage:%s file return|exit|_exit\n", argv[0]);        exit(1);    }    FILE *fp=fopen(argv[1],"w"); //双 引号char *str = "hellophp";    fprintf(fp, "%s",str );if(!strcmp(argv[2],"return")){return 0;    }else if(!strcmp(argv[2],"exit")){        exit(0);    }else if(!strcmp(argv[2],"_exit")){        _exit(0);    }else{        printf("process error\n");    }return 0;}

运行结果

[root@centos1 exit]# ./a.out exit.txt exit[root@centos1 exit]# ./a.out _exit.txt _exit[root@centos1 exit]# ./a.out return.txt return[root@centos1 exit]# more *.txt::::::::::::::_exit.txt::::::::::::::::::::::::::::exit.txt::::::::::::::hellophp::::::::::::::return.txt::::::::::::::hellophp

进程的环境表

获取当前进程的环境表
1.通过别的地方定义的 引入过来
 extern char **environ
2.通过main的第三个参数

进程中环境表操作
#include <stdio.h>
char *getenv(const char *name)
返回:指向与name关联的value指针,若未找到则返回NULL

#include <std;ib.h>
int putenv(char *str);
int setenv(const char *name,const char *value,int rewrite); //1非0表示覆盖
int unsetenv(const char *name);
返回:成功返回0,出错返回非0

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>extern char **environ;void showenv(char **env){int i=0;char *str;while ((str =env[i]) != NULL){        printf("%s\n",str );        i++;    }}int main(int argc,char *argv[],char *envp[]){    printf("envrison=%p,envp=%p\n",environ,envp );//2个变量地址值一样的//showenv(environ);//printf("-------\n");//showenv(envp);printf("----------------------------\n");char *oldpath=getenv("PATH");char *addpath=":/tmp/hkui";int newlen=strlen(oldpath)+1+strlen(addpath)+1;    printf("newlen=%d\n",newlen );char newpath[newlen];    strcpy(newpath,oldpath);    strcat(newpath,addpath);    printf("oldpath:%s\n",oldpath);    setenv("PATH",newpath,1);    printf("newpath:%s\n",getenv("PATH"));    putenv("NAME=HKUI2018");    printf("NAME:%s\n",getenv("NAME"));    return 0;}

 进程在内存中布局

正文段(代码段)
初始化数据段(全局数据,静态变量)
非初始化数据(全局数据,静态变量)
堆(手动分配的内存空间 malloc)
栈(一端封闭,一端开口)
main参数

进程在栈区实现非局部跳转
头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回

setjump,longjump
#include <setjmp.h>
int setjmp(jmp_buf env)
返回:直接调用返回0,若从longjmp调用返回,则返回非0值(longjmp第二个参数 val)

void longjmp(jmp_buf env,int val)

setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用。
如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0
setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中
longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。
当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行
包含setjmp()宏调用的函数一定不能已经终止。
所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的

非局部跳转应注意的问题
自动,寄存器和易失变量
寄存器中的变量再非局部跳转时可恢复原始值
自动变量的潜在问题

#include <stdio.h>#include <stdlib.h>#include <setjmp.h>jmp_buf jmp;int g_v=1;void fun(){    printf("jmp=%d\n",jmp );    longjmp(jmp,1);    printf("jmp=%d\n",jmp );}int main(void){static int s_v=1;    auto int a_v=1;    register r_v=1;volatile v_v=1;int *h_v=(int*)malloc(sizeof(int));*h_v=1;    printf("1:g_v=%d,s_v=%d,a_v=%d,r_v=%d,v_v=%d,h_v=%d\n",g_v,s_v,a_v,r_v,v_v,*h_v );    printf("setjmp(jmp)=%d\n",setjmp(jmp));if(setjmp(jmp) == 1){        printf("2:g_v=%d,s_v=%d,a_v=%d,r_v=%d,v_v=%d,h_v=%d\n",g_v,s_v,a_v,r_v,v_v,*h_v );        exit(1);    }    g_v=2;    s_v=2;    a_v=2;    r_v=2;    v_v=2;*h_v=2;    printf("3:g_v=%d,s_v=%d,a_v=%d,r_v=%d,v_v=%d,h_v=%d\n",g_v,s_v,a_v,r_v,v_v,*h_v );    fun();return 0;}

[root@centos1 process]# ./a.out
1:g_v=1,s_v=1,a_v=1,r_v=1,v_v=1,h_v=1
setjmp(jmp)=0
3:g_v=2,s_v=2,a_v=2,r_v=2,v_v=2,h_v=2
jmp=6294496
2:g_v=2,s_v=2,a_v=1,r_v=1,v_v=2,h_v=2

©著作权归作者所有:来自51CTO博客作者hkui2010的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. dns查询1:DomainNameResolve.java
  2. strcmp的返回值 字符串比较
  3. 函数的递归
  4. 微服务时代组件化和服务化的抉择
  5. 「知识点」JavaScript 中11个有趣的事实
  6. try catch fianlly执行顺序
  7. 函数的嵌套调用和链式访问
  8. 函数的形参和实参
  9. Go语言RPC学习记录

随机推荐

  1. 哪些年遇到过的Andriod问题(5)This text
  2. Android:在Eclipse下开发android应用产生
  3. android中国风笔记源码,金鱼游动动画源码
  4. (转帖)Android系列之浅谈Android 3D旋转
  5. android 图片的 放大 缩小 移动
  6. 使用Vitamio打造自己的Android万能播放器
  7. android Handler 机制研究学习笔记
  8. Android原生(Native)C开发之二 framebuff
  9. android BaseAdapter优化
  10. Android中图片占用内存的计算