exec函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
功能:
在调用进程内部执行一个可执行文件。可执行文件既可以是一个二进制文件,也可以是任何linux下可执行的脚本文件。
函数族:
分别是:execl,execlp,execle,execv,execvp,execvpe
函数族原型:
#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 execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
execle,execvpe比较少用
返回值:
exec函数族的函数执行成功后不会返回,调用失败时,会设置ermo并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字。
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件。
1、execl用法:
代码实例:
whereis ls:查看出ls的路径
ls: /bin/ls /usr/share/man/man1/ls.1.gz
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("before execl\n");
if(execl("/bin/ls","ls",NULL,NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
编译运行结果:相当于成功调用ls来运行
before execl
a.out demo12.c demo15.c demo2.c demo5.c demo8.c echoarg newpro
demo10.c demo13.c demo18.c demo3.c demo6.c demo9.c echoarg.c
demo11.c demo14.c demo19.c demo4.c demo7.c demo.c forktest
修改实现:ls -l效果
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("before execl\n");
if(execl("/bin/ls","ls","-l",NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
编译运行结果:
before execl
total 124
-rwxr-xr-x 1 CLC book 8481 Apr 9 20:51 a.out
-rw-r--r-- 1 CLC book 458 Apr 9 12:26 demo10.c
-rw-r--r-- 1 CLC book 457 Apr 9 16:25 demo11.c
-rw-r--r-- 1 CLC book 471 Apr 9 16:35 demo12.c
-rw-r--r-- 1 CLC book 555 Apr 9 16:46 demo13.c
-rw-r--r-- 1 CLC book 589 Apr 9 17:15 demo14.c
-rw-r--r-- 1 CLC book 444 Apr 9 17:28 demo15.c
-rw-r--r-- 1 CLC book 343 Apr 9 20:31 demo18.c
-rw-r--r-- 1 CLC book 335 Apr 9 20:41 demo19.c
-rw-r--r-- 1 CLC book 335 Apr 9 20:51 demo20.c
-rw-r--r-- 1 CLC book 160 Apr 9 00:54 demo2.c
-rw-r--r-- 1 CLC book 187 Apr 9 00:56 demo3.c
-rw-r--r-- 1 CLC book 309 Apr 9 11:43 demo4.c
-rw-r--r-- 1 CLC book 351 Apr 9 01:14 demo5.c
-rw-r--r-- 1 CLC book 277 Apr 9 01:21 demo6.c
-rw-r--r-- 1 CLC book 393 Apr 9 10:30 demo7.c
-rw-r--r-- 1 CLC book 336 Apr 9 10:51 demo8.c
-rw-r--r-- 1 CLC book 311 Apr 9 11:48 demo9.c
-rw-r--r-- 1 CLC book 161 Apr 9 00:17 demo.c
-rwxr-xr-x 1 CLC book 8381 Apr 9 17:59 echoarg
-rw-r--r-- 1 CLC book 172 Apr 9 17:59 echoarg.c
-rwxr-xr-x 1 CLC book 8536 Apr 9 11:21 forktest
-rwxr-xr-x 1 CLC book 8585 Apr 9 16:17 newpro
获取系统时间:date
CLC@Embed_Learn:~/jincheng$ date
Sun Apr 9 20:53:58 CST 2023
whereis date:查看date在哪
date: /bin/date /usr/share/man/man1/date.1.gz
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("this is system date\n");
if(execl("/bin/date","date",NULL,NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
实现ps:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("this is system date\n");
if(execl("/bin/ps","ps",NULL,NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
运行结果:
this is system date
PID TTY TIME CMD
22183 pts/1 00:00:01 bash
25728 pts/1 00:00:00 ps
2、execlp使用:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("this is system date\n");
if(execlp("ps","ps",NULL,NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
使用execlp时,将文件路径的绝对路径去掉,依旧可以运行
p为环境变量:使用时需要调用环境变量,方法如下:
pwd:查看当前路径
echo $PATH:显示当前PATH环境变量,该变量的值由一系列以冒号分隔的目录名组成。
export PATH=$PATH:路径名:环境变量的配置
3、execvp使用:(不需要添加绝对路径)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("this is system date\n");
char *argv[]={"ps",NULL,NULL};
if(execvp("ps",argv) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
编译运行结果:
this is system date
PID TTY TIME CMD
22183 pts/1 00:00:01 bash
25906 pts/1 00:00:00 ps
CLC@Embed_Learn:~/jincheng$ ./a.out
4、execv使用(需要添加绝对路径)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);
int main(void)
{
printf("this is system date\n");
char *argv[]={"ps",NULL,NULL};
if(execv("/bin/ps",argv) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl\n");
return 0;
}
编译运行结果:
this is system date
PID TTY TIME CMD
22183 pts/1 00:00:01 bash
25940 pts/1 00:00:00 ps