终止进程
终止进程可分为正常终止和异常终止两大类,其中常见的正常终止方式有:
从main()函数return返回;
调用exit()函数;
常见的异常终止方式有:
调用abort()函数;
接收到一个信号终止;
main()函数使用return指令返回时会自动调用类exit()函数来终止进程。异常终止的abort()函数通过SIGABRT信号来实现的。
exit()函数的原型如下:
#include <stdio.h>
void exit(int status);
参数status为进程的退出状态,与main()函数中return的返回值有相同的效果,即在程序中:
exit(0);
等价于main函数中的:
return 0;
通过在Shell中,可以使用$?变量来获取上次所运行程序的退出状态。
exec族函数
exec族函数用来修改当前进程的代码空间。
在介绍fork()函数的时候提到,在创建进程后子进程与父进程有相同的代码空间;而在实际应用中,往往需要子进程去执行另外一个程序,就这种情况,可以在子进程中调用exec族函数它的代码段完全替换为新的程序,并从这个新进程的main()函数开始执行。
调用exec族函数并不创建进程,因此前后进程的ID并无改变,exec只事用一个全新的程序替换掉当前进程代码空间里的内容。
exec族函数有6个不同的exec函数,函数原型分别如下:
#include <unistd.h>
extern char ** environ;
int execl( const char * path, const char * arg,…);
int execlp( const char * file, const char * arg,…);
int execle(const char * path, const char * arg, … char * const envp[]);
int execlv(const char * path, char * const argv[]);
int execvp(const cahr * file, char * const argv[]);
int execvpe(const char * file, char * const argv[],char * const envp[]);
以上函数是在exec后面加上如1、p、e、v等元素组成的后缀形式的,这些函数只在参数列表上存在差别。
后缀p:表示使用filename做参数,如果filename中包含“/”则视其为路径名,否则将会在PATH环境变量所指定的各个目录中搜索该文件,如execlp()函数。无后缀p则必须使用路径名来指定执行文件的位置,如execl()函数。
后缀e:表示可以传递一个指向环境字符串指针数组的指针,环境数组需要以NULL结束,如execvpe()函数。而无此后缀的函数则将当前进程的environ变量赋值给新的程序,如execv()函数。
后缀l:表示使用list形式来传递新程序的参数,所有这些参数均以可变参数的形式在exec()中给出,最后一个参数需要是NULL用以表示没有更多的参数了,如execl()函数。
后缀v:表示使用vector形式传递新程序的参数,传给新程序的所有参数放入一个字符串数组中,数组以NULL结束以表示结尾,如execv()函数。
exec族函数只有在出错的时候才会返回,如果成功,该函数无返回,否则返回-1.
下面通过一个范例讲述如何使用exec族函数为子进程装载新程序。
假如在“/heme/peng/”目录下有可执行程序sample3,改程序负责打印参数个数、参数列表和环境变量表:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> extern char ** environ; int main(int argc, char * agv[]) { int I; printf("argc = %d\n", argc); printf("args:"); for(i=0; i< argc; i++) printf("%s", argv[i]); printf("\n"); i = 0; while(envion[i]) puts(envion[i++]); printf("\n"); return 0; } #include <unistd.h> #include <stdlib.h> #include <stdio.h> char * env_init[] = {"USER=peng", "HOME=/home/peng/",NULL}; int main(int argc, char *argv[]) { pid_t pid; if((pid = fork())<0) { perror("fork error"); } else if(pid ==0 ) { ececle("home/peng/sample3","sample3","hello","world",(char *)0, env_init); perror("execle error"); exit(-1); } else { exit(0) } return -1; }