标签:
fork、vfork和clone三个函数主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定的程序替换当前进程的所有内容。所以exec()系列函数经常在前三个函数使用之后调用,来创建一个全新的程序运行环境。Linux用init进程启动其他进程的过程一般都是这样的。
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,主要是在fork()之后,它会诱导fork后的子进程另起炉灶,但是PID不变,自己开创一片新天地,清空原来的堆栈区、代码区和数据区,让新的可执行程序完全替代现有的资源。换句话说,就是在调用进程内部执行一个可执行文件,这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。
6个exec函数族:
(1)int execl(const char *path, const char *arg, ......); (2)int execle(const char *path, const char *arg, ...... , char * const envp[]); (3)int execv(const char *path, char *const argv[]); (4)int execve(const char *filename, char *const argv[], char *const envp[]); (5)int execvp(const char *file, char * const argv[]); (6)int execlp(const char *file, const char *arg, ......);注:其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL}; char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL}; execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); execv("/bin/ps", ps_argv); execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp); execve("/bin/ps", ps_argv, ps_envp); execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); execvp("ps", ps_argv);请注意exec函数族形参展开时的前两个参数,
在使用exec函数族时,一定要加上错误判断语句。因为exec很容易执行失败:
判断execl的返回值,如果出错,可以用perror( )函数打印出错误信息。
如:因为错误返回-1;成功没有返回值;
if (execl(“path”,”..””(char *)0) < 0) { perror(“execl error!”); }如果调用出错,可输出:execl error!: 错误原因 这样可方便查找出错原因
其中最常见的原因有:
标签:
原文地址:http://blog.csdn.net/gogokongyin/article/details/51334773