进程环境
7.3 进程终止 非常非常重要!!!!!!!!!
7.6章节
pthread_exit(posix(标准) thread)
abort():给本进程自己发送自杀信号
一、进程终止
1.1 钩子函数
1.1.1 atexit()
描述:当程序正常终止时,调用指定的函数 func。您可以在任何地方注册你的终止函数,但它会在程序终止的时候被调用。
手册:
man 3 atexit
头文件:
函数原型:
- function – 在程序终止时被调用的函数。
返回值:
成功:0
失败:!0
1.2 exit()
exit带回的可能性(-128~127)
描述:(库函数)使进程正常终止,在程序正常终止之前,它会先执行一些清除操作以逆序的顺序调用声明的钩子函数(如调用执行各终止处理函数、关闭所有标准IO等)。
手册:
man 3 exit
头文件:
函数原型:
返回值:空
代码演示:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
void f1()
{
puts("f1() is working.");
}
void f2()
{
puts("f2() is working.");
}
void f3()
{
puts("f3() is working.");
}
int main()
{
puts("Begin!");
atexit(f1);
atexit(f2);
atexit(f3);
puts("End!");
exit(0);
}
1.3 _exit() & _Exit()
描述:(系统调用)直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构。
手册:
man 2 _exit
头文件:
#include <unistd.h>
#include <stdlib.h>
函数原型:
void _exit(int status);
void _Exit(int status);
使用条件:当不确定缓存区内有什么的时候调用
if(1)
else if(2)
else //我确定只有前面几种可能,最后出现的可能我也不知道会发生什么
_exit() //或调用abort()
1.4 拓展
exit()函数与_exit()函数区别:
exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的"清理I/O缓冲"一项。
二、命令行参数
2.1 getopt()
描述:命令行参数分析(只能分析短格式)
手册:
man 3 getopt
头文件:
函数原型:
extern char *optarg;//只有在碰到有arg修饰的opt时候生效,指向opt后边的串
extern int optind, opterr, optopt;
int getopt(int argc, char * const argv[],const char *optstring);
- optarg – 只有在碰到有arg修饰的opt时候生效,指向opt后边的串
- optind – 计数器,记录数组下标
- argc – 记录命令行参数个数
- argv[] – 存放命令行的参数
- optstring – 可选项字符串(所有的命令行参数可选项都放在此字符串内)
用法:opt(选项),arg(参数)
识别opt的
//命令行传参:./a.out -m -dM -S
int ch;
ch = getopt(argc,argv,"ymdHMS")
注意:
某个选项带arg修饰时(opt-arg) 串选项后要加 :(识别修饰opt的arg)
在选项串前加 -,分析命令行,如果不是选项时返回1(识别非opt的arg)//命令行传参:./a.out -y 4 int ch; ch = getopt(argc,argv,"y:mdH:MS");
//命令行传参:./a.out -y 4 /tmp/out int ch; ch = getopt(argc,argv,"-y:mdH:MS");//非选项传参
代码演示:
功能:通过命令行传参,控制显示
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#define TIMESTRSIZE 128
int main(int argc,char *argv[])
{
time_t stamp;
struct tm *tm;
char fmtstr[TIMESTRSIZE] = {'\0'};
char timestr[TIMESTRSIZE];
int ch;
FILE *fp = stdout;
stamp = time(NULL);
tm = localtime(&stamp);
while(1)
{
ch = getopt(argc,argv,"-y:mdH:MS");
if(ch < 0)
break;
switch(ch)
{
case 1:
if(fp == stdout)
{
fp = fopen(argv[optind-1],"w");
if(fp == NULL)
{
perror("fopen()");
fp = stdout;
}
}
break;
case 'y':
if(strcmp(optarg,"2") == 0)
strncat(fmtstr,"%y ",TIMESTRSIZE);
else if(strcmp(optarg,"4") == 0)
strncat(fmtstr,"%Y ",TIMESTRSIZE);
else
fprintf(stderr,"Invalid argument of -y\n");
break;
case 'm':
strncat(fmtstr,"%m ",TIMESTRSIZE);
break;
case 'd':
strncat(fmtstr,"%d ",TIMESTRSIZE);
break;
case 'H':
if(strcmp(optarg,"12") == 0)
strncat(fmtstr,"%I(%P) ",TIMESTRSIZE);
else if(strcmp(optarg,"24") == 0)
strncat(fmtstr,"%H ",TIMESTRSIZE);
else
fprintf(stderr,"Invalid argument of -H\n");
break;
case 'M':
strncat(fmtstr,"%M ",TIMESTRSIZE);
break;
case 'S':
strncat(fmtstr,"%S ",TIMESTRSIZE);
break;
default:
break;
}
}
strncat(fmtstr,"\n",TIMESTRSIZE);
strftime(timestr,TIMESTRSIZE,fmtstr,tm);
fputs(timestr,fp);
if(fp != stdout)
fclose(fp);
exit(0);
}
返回值:
成功:返回选项字符
失败:-1
2.2 getopt_long()
描述:命令行参数分析(长短格式都可以)
手册:
man 3 getopt
头文件:
函数原型:
2.3 getopt_long_only()
描述:命令行参数分析(只能长格式)
手册:
man 3 getopt
头文件:
函数原型:
三、环境表
全局变量environ包含了该指针数组的地址
和argv[],glob中 gl_pathv[] 的结构类似
shell命令:export
功能:打印目前进程环境变量(把当前shell(终端,获取输入反馈输出)当程序来跑的话,相当于大程序的全局变量,用户和目前管理员沟通的途径)
字符串形式:name = value
伪码演示:
功能:类似export命令
int i;
for(i = 0 ; environ[i] != NULL; i++)
puts(environ[i]);
四、环境变量
字符串形式:name = value
4.1 getenv()
描述:从环境中取字符串,获取环境变量的值
手册:
man getenv
头文件:
函数原型:
- name – 环境变量名
返回值:
成功:返回与name关联的value指针
失败:NULL
代码演示:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
extern char **environ;
int main()
{
int i;
for(i = 0 ; environ[i] != NULL; i++)
puts(environ[i]);
printf("-----------------\n");
puts(getenv("PWD"));
exit(0);
}
4.2 setenv()
描述:改变或增加环境变量
手册:
man setenv
头文件:
函数原型:
int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);
- name – 环境变量名称字符串
- value – 为变量内容
- overwrite – 用来决定是否要改变已存在的环境变量
若环境变量不存在
如果没有此环境变量则无论overwrite为何值均添加此环境变量。
若环境变量存在:
当overwrite不为0时,原内容会被改为参数value所指的变量内容。
当overwrite为0时,则参数value会被忽略。
返回值:
成功:0
失败:-1
4.3 putenv()
描述:改变或增加环境变量
(推荐setenv())
五、setjmp() & longjmp()
用来实现函数之间的跳转
5.1 setjmp()
描述:设置跳转点
手册:
man setjmp
头文件:
函数原型:
- env – 设置的跳转标志
返回值:
如果是设置跳转点:返回0。
如果是由longjmp()跳转过来的,返回longjmp函数中设置的val值(!0)
5.2 longjmp()
描述:跳转到env所标志的地方
手册:
man longjmp
头文件:
函数原型:
回调值:
如果val填的是0,默认回调1到setjmp中
代码演示:
功能:嵌套调用到d()后直接跳转到a()
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static jmp_buf FLAG;
void d()
{
printf("%d:[%s]Begin.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]Jump now!~~~\n",__LINE__, __FUNCTION__);
longjmp(FLAG,666);
printf("%d:[%s]End.\n",__LINE__, __FUNCTION__);
}
void c()
{
printf("%d:[%s]Begin.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]Call d().\n",__LINE__, __FUNCTION__);
d();
printf("%d:[%s]d() returned.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]End.\n",__LINE__, __FUNCTION__);
}
void b()
{
printf("%d:[%s]Begin.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]Call c().\n",__LINE__, __FUNCTION__);
c();
printf("%d:[%s]c() returned.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]End.\n",__LINE__, __FUNCTION__);
}
void a()
{
int ret;
printf("%d:[%s]Begin.\n",__LINE__, __FUNCTION__);
ret = setjmp(FLAG);
if(ret == 0)
{
printf("%d:[%s]Call b().\n",__LINE__, __FUNCTION__);
b();
printf("%d:[%s]b() returned.\n",__LINE__, __FUNCTION__);
}
else
printf("%d:[%s]Jumped back here with code %d\n",__LINE__, __FUNCTION__,ret);
printf("%d:[%s]End.\n",__LINE__, __FUNCTION__);
}
int main()
{
printf("%d:[%s]Begin.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]Call a().\n",__LINE__, __FUNCTION__);
a();
printf("%d:[%s]a() returned.\n",__LINE__, __FUNCTION__);
printf("%d:[%s]End.\n",__LINE__, __FUNCTION__);
exit(0);
}