exec族函数
为什么要用exec族函数,有什么作用
(1) 一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的一父 进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下-一个服务请求到达。
(2) 一个进程要执行一一个不同的程序。 这对shell是常见的情况。在这种情况下、子进程从for k返回后立即调用exec 。
使用exec函数族主要有两种情况:
(1)当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec函数族中的任意一个函数让自己重生。
(2)如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用exec函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。
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 execle(const char *path, const char *arg, ...);
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[]);
返回值:一1表明调用exec失败,无返回表明调用成功。
参数说明:
path:要执行的程序路径。可以是绝对路径或者是相对路径。在execv、execve、execl和execle这4个函数中,使用带路径名的文件名作为参数。
file:要执行的程序名称。如果该参数中包含“/”字符,则视为路径名直接执行;否则视为单独的文件名,系统将根据PATH环境变量指定的路径顺序搜索指定的文件。
argv:命令行参数的矢量数组。
envp:带有该参数的exec函数可以在调用时指定一个环境变量数组。其他不带该参数的exec函数则使用调用进程的环境变量。
arg:程序的第0个参数,即程序名自身。相当于argv[O]。
exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量
exec配合fork使用
实现功能,当父进程检测到输入为1的时候,创建子进程把配置文件的字段值修改掉。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int data=10;
while(1){
printf("please input a data\n");
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;
}
execl里调用的changedata可执行文件代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdsrc;
char *readbuf=NULL;
if(argc<2){
printf("param error\ni");
exit(-1);
}
fdsrc=open(argv[1],O_RDWR);
int size=lseek(fdsrc,0,SEEK_END);
lseek(fdsrc,0,SEEK_SET);
readbuf=(char *)malloc(sizeof(size)+8);
int n_read=read(fdsrc,readbuf,size);
char *p=strstr(readbuf,"LENG=");
if(p==NULL){
printf("not found\n");
exit(-1);
}
p=p+strlen("LENG=");
*p='5';
lseek(fdsrc,0,SEEK_SET);
int n_write=write(fdsrc,readbuf,strlen(readbuf));
close(fdsrc);
return 0;
}
代码执行后,输入1后,配置文件将9已结成功改成5