exec族函数的作用
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
详细参考精彩博文:
exec族函数精彩博文
直接上例子:
echoarg.c
#include <stdio.h>
int main(int argc,char *argv[])
{
int i = 0;
for(i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n",i,argv[i]);
}
return 0;
}
结果:
这只是一个传参的例子,编译生成一个可执行文件
execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("before execl!\n");
if(execl("./echoarg","echoarg","abvfd",NULL) == -1)
{
printf("execl failed!\n");
perror("why");
}
printf("after execl!\n");
return 0;
}
结果:
既然exec函数族执行的是一个可执行文件,那么linux底下的ls执行也是一个可执行文件,那么我们就用exec函数来调用一下linux底下的相关指令。
ls:
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
printf("this is ls\n");
if(execl("/bin/ls","ls",NULL) == -1)
{
printf("no this file\n");
}
printf("after execl\n");
return 0;
}
结果:
这样就把指令ls给调用起来了。
ls -al:
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
printf("this is ls\n");
if(execl("/bin/ls","ls","-al",NULL) == -1)
{
printf("no this file\n");
}
printf("after execl\n");
return 0;
}
结果:
这样也把指令ls -al给调用起来了
那我们来调用一下获取时间的指令date:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("this is Beijing Time:\n");
if(execl("/bin/date","date",NULL) == -1)
{
printf("faild to open execl!\n");
}
printf(".....\n");
return 0;
}
结果:
execlp
execlp
跟execl
的区别就是execl
要加绝对路径,而execlp
不用加路径,直接写对应的可执行文件即可
ps:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("this is ps\n");
if(execlp("ps","ps",NULL) == -1)
{
printf("faild to open execl!\n");
perror("why");
}
printf(".....\n");
return 0;
}
结果:
execv:
execv函数跟execl不同之处就是后面的参数用一个指针数组来保存起来
ls:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("this is execv!\n");
char *arv[] = {
"ls","-l",NULL};
if(execv("/bin/ls",arv))
{
printf("faild to open execv!\n");
perror("why");
}
printf("......\n");
return 0;
}
execvp:
execv跟execvp的区别也是一个需要加路径,一个不需要加路径
ls -l:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("this is execv!\n");
char *arv[] = {
"ls","-l",NULL};
if(execvp("ls",arv))
{
printf("faild to open execv!\n");
perror("why");
}
printf("......\n");
return 0;
}
2.exec配合fork使用
实现功能,当父进程检测到输入为1的时候,创建子进程把配置文件的字段值修改掉
代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
pid_t pid;
int data;
int fd;
int n_read;
char *readBuf = NULL;
char *pstr = NULL;
while(1)
{
printf("Please Input a data:\n");
scanf("%d",&data);
if(data == 1)
{
pid = fork();
if(pid > 0)
{
wait();
}
else if(pid == 0)
{
fd = open("./test.txt",O_RDWR);
n_read = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*n_read + 5);
read(fd, readBuf, n_read);
pstr = strstr(readBuf,"LOIJ=");
if(pstr == NULL)
{
printf("fail to change the file!\n ");
exit(-1);
}
pstr = pstr + strlen("LOIJ=");
*pstr = '3';
lseek(fd,0,SEEK_SET);
write(fd, readBuf, n_read);
close(fd);
}
}
else
{
printf("Wait,Please Input again!\n");
}
}
return 0;
}
这样写的话其实是很冗余的。
调用exec函数来实现:
include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
pid_t pid;
int data;
int fd;
int n_read;
char *readBuf = NULL;
char *pstr = NULL;
while(1)
{
printf("Please Input a data:\n");
scanf("%d",&data);
if(data == 1)
{
pid = fork();
if(pid > 0)
{
wait();
}
else if(pid == 0)
{
if(execl("./changeDate","changeDate","test.txt",NULL) == -1)
{
printf("Sorry, fail to change the data!\n");
}
}
}
else
{
printf("Wait,Please Input again!\n");
}
}
return 0;
}
生成changeDate
可执行文件的代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
char* change(char *read,char *str)
{
char *pstr = NULL;
pstr = strstr(read,str);
if(pstr == NULL)
{
printf("Sorry ,faild to found\n");
exit(-1);
}
pstr = pstr + strlen(str);
*pstr = '3';
return pstr;
}
int main(int argc, char **argv)
{
if(argc != 2)
{
printf("parameter error!!\n");
exit(-1);
}
int fd;
int fd_size;
char *readBuf = NULL;
char *pstr = NULL;
fd = open(argv[1],O_RDWR);
fd_size = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*fd_size+3);
read(fd,readBuf,fd_size);
pstr = change(readBuf,"LOIJ=");
lseek(fd,0,SEEK_SET);
write(fd,readBuf,fd_size);
close(fd);
return 0;
}
修改前的test.txt:
修改后的test.txt:
这只是学习中的点点代码,详细参考开头介绍到的那个精彩博文。
学习笔记,仅供参考