linux命令行调用每次起进程,Linux环境编程之进程(一):main函数调用、进程终止以及命令行参数和环境表...

(一)main函数调用

main函数作为程序运行时的入口函数,它是如何被调用的呢?首先必须清楚一点,main函数也是一个函数,它只有被调用才能够执行。其实,在执行可执行程序时,在调用main函数之前,内核会先调用一个特殊的启动例程,将此启动例程作为可执行程序的起始地址。启动例程是如何作为可执行程序的起始地址的?这是由链接编译器设置的,而链接编译器则是由C编译器(如gcc编译器)调用的。启动例程作为可执行程序的起始地址主要做哪些工作呢?启动例程从内核取得命令行参数和环境变量值,以此来为main函数的调用做准备。

(二)命令行参数

当执行一个程序时,调用exec的进程可以将命令行参数传递给该程序。示例如下:

/*

*File Name : argdemo.c

*Author : libing

*Mail : libing1209@126.com

*Function : show the arguments you input

*/

#include

#include

int

main(int argc, char *argv[])

{

int i;

for(i = 0; i < argc; i++){

printf("argv[i] = %s.\n", argv[i]);

}

exit(0);

}编译测试结果:./a.out fdj fda li

argv[i] = ./a.out.

argv[i] = fdj.

argv[i] = fda.

argv[i] = li.(三)环境表

每个程序都会接收到一张环境表。与上面的命令行参数一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量environ则包含了该指针数组的地址。

0818b9ca8b590ca3270a3433284dd417.png

从表中可以看出,每个字符串的结尾处都显示地有一个null字符。称environ为环境指针,指针数组为环境表,其中各指针指向的字符串为环境字符串。通常用getenv和putenv函数来访问特定的环境变量,而不是environ变量。但如果要查看整个环境,则必须使用environ指针。

#include

char *getenv(const char *name); // 返回值:指向与name关联的value指针,若未找到则返回NULL

int putenv(char *string);                 // 返回值:若成功则返回0, 若出错则返回非0值

int setenv(const char *name, const char *value, int overwrite);

int unsetenv(const char *name);// setenv和unsetenv,若成功则返回0, 若出错则返回-1

说明如下:

1、putenv取形式为“name=value”(等号两边不要留空格)的字符串,将其放到环境表中。如果name已经存在,则先删除其原来的定义。

2、setenv将name设置为value。如果在环境中name已经存在,那么a:若rewite非0,则首先删除其现有定义;b:若rewrite为0,则不删除其现有定义(name不设置为新的value,而且不出错)。

3、unsetenv删除name的定义。即使不存在这种定义也不出错。

示例代码如下:

/*

*File Name : envdemo.c

*Author : libing

*Mail : libing1209@126.com

*Function : test some function of env

*/

#include "apue.h"

#include

int

main(int argc, char *argv[])

{

char *value;

int i;

value = getenv("PWD");

printf("%s\n", value);

if(!getenv("libing")){

printf("can't find env libing.\n");

}

putenv("libing=libing1209@126.com");

value = getenv("libing");

printf("%s\n", value);

unsetenv("libing");

if(getenv("libing") == NULL)

printf("can't find env libing.\n");

exit(0);

}程序测试结果:gcc envdemo.c

/work/tmp/apue/chapter7

can't find env libing.

libing1209@126.com

can't find env libing.(四)进程终止

既然一个程序又开始,就一定有终止。有8种方式使进程终止,其中5种为正常终止:从main返回、调用exit、调用_exit或_Exit、最后一个线程从其启动例程返回、最后一个线程调用pthread_exit;3种异常终止方式:调用abort、接到一个信号并终止、最后一个线程对取消请求做出响应。

1、exit类函数。有三个函数用于正常终止一个程序:_exit和_Exit立即进入内核,exit则先执行一些清理处理(包括调用执行各类终止处理程序,关闭所有标准I/O流等),然后进入内核。

#include

void exit(int status);

void _Exit(int status);

#include

void _exit(int status);

2、atexit函数。一个进程可以登记多达32个函数,这些函数将由exit自动调用。我们称这些函数为终止处理程序,并调用atexit函数来登记这些函数。

#include

int atexit(void (*func)(void));  // 若成功则返回0, 若出错则返回非0值

atexit参数是一个函数地址,当调用此函数时无需向他传送任何参数,也不期望它返回一个值。exit调用这些函数的顺序与它们登记时的顺序相反。同一函数如若登记多次,则也返回多次。

0818b9ca8b590ca3270a3433284dd417.png

示例代码:

/*

*File Name : atexit.c

*Author : libing

*Mail : libing1209@126.com

*function : test the function atexit

*/

#include

#include

#include

static void my_exit1(void);

static void my_exit2(void);

int

main()

{

if((atexit(my_exit2)) != 0)

printf("can't register my_exit2");

if((atexit(my_exit1)) != 0)

printf("can't register my_exit1");

if((atexit(my_exit1)) != 0)

printf("can't register my_exit1");

printf("main is done.\n");

return 0;

}

编译测试结果:

main is done.

first exit handler

first exit handler

second exit handler

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值