天天看点

嵌入式软件开发 day17(进程环境)进程环境

进程环境

7.3 进程终止 非常非常重要!!!!!!!!!

7.6章节

pthread_exit(posix(标准) thread)

abort():给本进程自己发送自杀信号

一、进程终止

嵌入式软件开发 day17(进程环境)进程环境

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)

//命令行传参:./a.out -y 4
int ch;
ch = getopt(argc,argv,"y:mdH:MS");
           
在选项串前加 -,分析命令行,如果不是选项时返回1(识别非opt的arg)
//命令行传参:./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包含了该指针数组的地址
嵌入式软件开发 day17(进程环境)进程环境
和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);
}

           

继续阅读