exec族函数函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
功能:
在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
函数族:
exec函数族分别是: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 execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
返回值:
exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
一、带l的一类exac函数(l表示list),包括execl、execlp、execle,要求将新程序的每个命令行参数都说明为 一个单独的参数。这种参数表以空指针结尾。
如下图代码所示:在execl( )中第一个参数是程序的地址程序名,第二个和第三个是给echoarg程序的参数,然后以第四个参数NULL结尾。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("before execl\n");
if(execl("./bin/echoarg","echoarg","abc",NULL) == -1){
printf("execl failed!");
perror("why");
}
printf("after execl\n");
return 0;
}
当execl成功时,会去执行echoarg程序,程序代码如下所示:功能是打印所有参数
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < argc; i++){
printf("argc[%d]: %s\n", i, argv[i]);
}
return 0;
}
当execl成功,程序执行结果如下图所示:
当execl失败,程序执行结果如下图所示:用perror打印错误的原因
下面再演示一下用execl执行根目录底下的 ls 指令去查看当前目录的文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("before execl\n");
if(execl("/bin/ls","ls",NULL,NULL) == -1){
printf("execl failed!");
perror("why");
}
printf("after execl\n");
return 0;
}
由此我们可以发现: execl("/bin/ls","ls",NULL,NULL) ,第一个参数为第二个参数(程序名)的所在地,第二个参数就是要执行的程序名,第三个参数就是要执行的程序名跟的参数,比如要使用ls -l把所有文件清单列出来,则第三个参数就是“-l”。execl("/bin/ls","ls",“-l”,NULL);
下面演示的是打印系统时间:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("this is system date\n");
if(execl("/bin/date","date",NULL,NULL) == -1){
printf("execl failed!");
perror("why");
}
printf("after execl\n");
return 0;
}
exec配合fork使用:
实现功能,当父进程检测到输入为1的时候,创建子进程把配置文件的字段值修改掉。
代码展示:直接用execl调用另一个程序,转到那个程序继续执行。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int data = 10;
while(1){
printf("please input a data");
scanf("%d", &data);
if(data == 1){
pid = fork();
if(pid > 0){
wait(NULL);
}
if(pid == 0){
execl("./changeData","changeData","config.txt",NULL);
}
}else{
printf("wait, do nothing\n");
}
}
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fdSrc;
char *readBuf = NULL;
char *p;
if(argc != 2){
printf("param error\n");
exit(-1);
}
fdSrc = open(argv[1], O_RDWR);
int size = lseek(fdSrc, 0, SEEK_END);
lseek(fdSrc, 0, SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc, readBuf, size);
p = strstr(readBuf, "LENG = ");
if(p == NULL){
printf("no fund\n");
exit(-1);
}
p = p+strlen("LENG = ");
*p = '9';
lseek(fdSrc, 0, SEEK_SET);
int n_write = write(fdSrc, readBuf, strlen(readBuf));
close(fdSrc);
return 0;
}
结果如下所示:5被修改为了9