说明:只供学习交流,转载请注明出处
一,exec函数族
Linux系统提供了exec函数族用于对创建新进程中的数据段、代码段和堆栈段进行替换。进程调用exec函数族中的函数后,其代码段会被替换成新的代码段。同时,获得新程序的数据段和堆栈段,进程的进程号保持不变。exec函数族中的函数定义主要包括如下的几种形式:
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 execv(const char *path, char *constargv[]);
int execve(const char *filename, char*const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
可以看到这几种形式都是以exec开头。如果exec后面的字符是“l”(list的缩写),表示该种形式的exec函数可以使用可变参数(参数的个数可变);包含v字符,表示支持使用参数数组;如果是以p结尾表示如果给出的程序没有给出路径,将自动搜索系统的PATH路径。对于execl、execv、execle或execve这些不以p结束的函数,给出的要执行的可以执行的文件必须给出具体的文件所在路径。
注意:当进程调用一种exec函数时,该进程完全由新程序代替,而新程序则从其main()函数开始执行。
execl函数
头文件 | #include <unistd.h> |
函数原型 | int execl(const char *path, const char *arg, …); |
返回值 | 如果执行成功则函数不会返回,执行失败者直接返回-1,失败原因存在于errno中 |
参数说明:
path:可执行文件的全路径,包含文件名本身。
arg:执行该文件的参数列表。参数列表中第一个参数就是该可执行文件的名称,最后要以(char*)0结束。
实例:
#include <unistd.h>
int main(void)
{
execl("/bin/ls", "ls", "-al", "/etc/passwd", (char*)0);
return (0);
}
运行结果:
[root@localhost test]# ./test
-rw-r--r-- 1 root root 1508 Dec 3 05:34 /etc/passwd
[root@localhost test]#
相当于执行了/bin/ls –al/etc/passwd
头文件 | #include <unistd.h> |
函数形式 | int execv(char *pathname, char *argv[]); |
返回值 | 如果指向成功则函数不会返回,执行失败则直接返回-1,失败原因存在于errno中。 |
参数说明:
path:可执行文件的全路径。
arg:执行该文件的参数列表。它是一个数组指针,参数列表中第一个参数就是该可执行文件的名称,最后要以NULL结束。
实例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char *exec_argv[4];
exec_argv[0] = "ls";
exec_argv[1] = "-al";
exec_argv[2] = "/etc/passwd";
exec_argv[3] = NULL;
execv("/bin/ls", exec_argv);
return (0);
}
运行结果:
[root@localhost test]# ./execv
-rw-r--r-- 1 root root 1508 Dec 3 05:34 /etc/passwd
[root@localhost test]#
execlp函数举例:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if ( argc < 2 )
{
printf("Usage: %s path\n", argv[0]);
return (1);
}
execlp("ls", "ls", argv[1], (char *)NULL);
return (0);
}
运行结果:
[root@localhost test]# ./execlp /home
madplay motion smb tanghui
[root@localhost test]#
说明:并没有给出ls命令的全部路径,函数会通过文件名从PATH环境变量中查找复合第一个参数的文件名来执行。
execvp函数使用范例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc < 2 )
{
printf("Usage: %s arg list...\n", argv[0]);
exit(EXIT_FAILURE);
}
execvp(argv[1], &argv[1]);
return (0);
}
运行结果:
[root@localhost test]# ./execvp ls /home/
madplay motion smb tanghui
[root@localhost test]#
如果PATH环境变量中没有待执行文件的路径,我们还可以通过execle和execve这两个函数来指定环境变量。这两个函数对比其他的两组函数多了一个参数。
execve函数使用举例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char *argv[] = {"ls", "-al", "/etc/passwd", (char *)0};
char *envp[] = {"PATH = /bin", 0};
execve("/bin/ls", argv, envp);
return (0);
}
运行结果:
[root@localhost test]# ./execve
-rw-r--r-- 1 root root 1508 Dec 3 05:34 /etc/passwd
[root@localhost test]#
execle函数这里就不举例子了,因为跟execve函数差不多,只是不用数组形式而已。
system函数:
#include <stdlib.h>
int system(const char *string);
功能:调用fork产生子进程,由子进程来调用/bin/sh –C string来执行参数string所代表的命令。
使用范例:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
system("ls -al /home");
return (0);
}
运行结果:
[root@localhost test]# ./system
total 36
drwxr-xr-x 6 root root 4096 Feb 24 19:50 .
drwxr-xr-x 28 root root 4096 May 4 04:50 ..
drwxr-xr-x 4 root root 4096 Feb 4 06:07 madplay
drwxr-xr-x 2 root root 4096 Feb 24 19:50 motion
drwx------ 20 smb smb 4096 May 8 21:15 smb
drwx------ 17 tanghui tanghui 4096 May 4 04:51 tanghui
[root@localhost test]#
exec函数族和system函数的区别:
system是用shell来调用程序=fork+exec+waitpid,而exec是直接让你的程序是直接让你的程序代替用来的程序运行。
system是在单独的进程中执行命令,完了还会回到你的程序中。而exec函数族是直接在你的程序中执行新的代码。新的程序会覆盖你原来的程序。除非调用出错,否则你再也回不到exec后面的代码,就是说你的程序就变成了exec调用的那个程序了。看下面的例子:
例子1:
execl(“/bin/ls”, “ls”, “-al”, “/”, NULL);
printf(“hello linux”);
例子2:
System(“ls –al /”);
printf(“hello linux”);
在例子1中,执行完exec函数后不会输出“hello linux”,因为execl里的内容代替了原程序。而例子2中会输出“hello linux”。在Linux中exec函数族一般和fork一起使用。
综合实例:
file_create.c:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
void create_file(char *filename)
{
if (creat(filename, 0666) < 0)
{
printf("Create file %s failure!\n", filename);
exit(EXIT_FAILURE);
}
else
{
printf("Cteate file %s success!\n", filename);
}
}
int main(int argc, char *argv[])
{
if ( argc != 2 ) {
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
create_file(argv[1]);
return (0);
}
file_exec.c:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc != 2 )
{
printf("Usage : %s filename!\n", argv[0]);
exit(EXIT_FAILURE);
}
execl("./file_create", "file_create", argv[1], (char *)0);
printf("hello linux");
return (0);
}
运行结果:
[root@localhost test]# ls
exec file_create file_create.c file_exec file_exec.c
[root@localhost test]# ./file_exec hello
Cteate file hello success!
[root@localhost test]#
[root@localhost test]#