网站建设与网站设计,辽宁省建设信息网官网,服装电子商务网站建设3000字,中国机械加工网17sexec族函数解析
作用 我们用fork函数创建新进程后#xff0c;经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时#xff0c;该进程被完全替换为新程序。因为调用exec函数并不创建新进程#xff0c;所以前后进程的ID并没有改变。
功能 在调用进程内部…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 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[]);返回值 exec函数族的函数执行成功后不会返回调用失败时会设置errno并返回-1然后从原程序的调用点接着往下执行。
参数说明
path可执行文件的路径名字arg可执行程序所带的参数第一个参数为可执行文件名字没有带路径且arg必须以NULL结束file如果参数file中包含/则就将其视为路径名否则就按 PATH环境变量在它所指定的各目录中搜寻可执行文件
exec族函数参数极难记忆和分辨函数名中的字符会给我们一些帮助
l使用参数列表p使用文件名并从PATH环境进行寻找可执行文件v先构造一个指向各参数的指针数组然后将该数组的地址作为这些函数的参数e多了envp[]数组使用新的环境变量代替调用进程的环境变量
将exac函数归为带l、带p、带v三类来说明参数特点
一、带l的一类exac函数l表示list包括execl、execlp、execle要求将新程序的每个命令行参数都说明为 一个单独的参数。这种参数表以空指针结尾。
1.新建一个echoarg并使用execl函数调用
//文件17.c
#include unistd.h
#include stdio.hint main()
{printf(before execl\n);if(execl(./echoarg,echoarg,hello,word,NULL) -1){printf(open execl failed\n);//调用execl失败会返回-1则会执行if里的代码perror(why);}printf(after execl\n);return 0;
}//文件echoarg.c
#include stdio.hint main(int agrc,char *argv[])
{int i;for(i 0;i agrc;i){printf(argv[%d]:%s\n,i,argv[i]);}return 0;
}先用gcc编译echoarg.c生成可执行文件echoarg并放在当前路径下。文件echoarg的作用是打印命令行参数。然后再调用execl用execl 找到并执行echoarg将当前进程main替换成进程echoarg就会执行ehcoarg里面的代码所以”after execl” 没有在终端被打印出来。
路径对应不上的情况
//文件16.c
#include unistd.h
#include stdio.hint main()
{printf(before execl\n);if(execl(/bin/echoarg,echoarg,hello,word,NULL) -1){printf(open execl failed\n);perror(why);//perror函数会打印错误原因输入内容后结尾会自动加冒号(:)并换行}printf(after execl\n);return 0;
} 可见echoarg存在于当前路径并不存在于bin路径下所以调用execl函数无法找到echoarg并执行echoarg调用失败返回值为-1则会继续执行if函数里的代码。
注当前文件格式是./可执行文件名字其他路径为 /其他路径/可执行文件名字
2.使用execl函数调用ls指令
//文件18.c
#include unistd.h
#include stdio.hint main()
{printf(before execl\n);if(execl(/bin/ls,ls,NULL) -1)//不需要参数则找到并使用ls后以NULL结尾{printf(open execl failed\n);perror(why);}printf(after execl\n);return 0;
}whereis ls//查看ls的路径
可见打印完“before execl”后使用execl函数使用execl函数找到并调用date可执行文件编译运行代码会直接显示出当前所有文件实现功能调用。不会执行if中的代码。
3.使用execl函数调用date指令
//文件19.c
#include unistd.h
#include stdio.hint main()
{printf(we can use execl to know the time\n);//不需要参数则找到并使用ls后以NULL结尾if(execl(/bin/date,date,NULL) -1){printf(open execl failed\n);perror(why);}printf(after execl\n);return 0;
}date//查看系统时间可见一开始直接用date指令可以看到系统时间在上述代码中通过使用execl函数找到并调用date可执行文件编译运行代码会直接显示出系统时间实现功能调用。
二、带p的一类exac函数包括execlp、execvp、execvpe如果参数file中包含/则就将其视为路径名否则就按 PATH环境变量在它所指定的各目录中搜寻可执行文件。
1.使用execlp函数调用date指令
//文件20.c
#include unistd.h
#include stdio.hint main()
{printf(we can use execl to know the time\n);if(execlp(date,date,NULL) -1){printf(open execl failed\n);perror(why);}printf(after execl\n);return 0;
}上述代码如果调用execl函数则会调用失败原因是没有输入可执行文件的正确路径。
而在file参数位置直接输入可执行文件名字调用execlp函数能通过环境变量PATH查找到可执行文件date并执行。
2.环境变量PATH解读
如果使用的可执行文件在PATH里则使用execlp函数可以不用详细描述绝对路径。
打印环境变量
echo $PATH 修改环境变量
export PATH$PATH:/home/CLC/Linux1
//通过pwd查看执行文件的路径并将其添加进环境变量PATH路径 修改完毕后结果是运行/hone/CLC/Linux1下的可执行文件不需要加./便可直接运行 在当前Linux1文件下运行可执行文件不需要加./使用cd回到目录文件夹也是输出结果一样
三、带v不带l的一类exac函数包括execv、execvp、execve应先构造一个指向各参数的指针数组然后将该数组的地址作为这些函数的参数。
如char *arg[]这种形式且arg最后一个元素必须是NULL例如char *arg[] {“ls”,NULL};
1.execvp
#include unistd.h
#include stdio.hint main()
{printf(we can use execl to know the time\n);char *agrv[] {ls,NULL};//定义一个指针数组if(execvp(ls,agrv) -1)//将指针数组的地址作为参数{printf(open execl failed\n);perror(why);}printf(after execl\n);return 0;
}定义一个指针数组并将其地址作为execvp函数后面的参数同时要以NULL结尾便可以找到并执行ls可执行文件。同时file参数位置可直接输入可执行文件名字不需要加路径。
2.execv
#include unistd.h
#include stdio.hint main()
{printf(before execv\n);char *agrv[] {date,NULL};if(execv(/bin/date,agrv) -1){printf(open execl failed\n);perror(why);}printf(after execvp\n);return 0;
}跟execvp一样需要定义一个指针数组并将其地址作为参数部分但需要加上可执行文件路径名字date在bin下所以需要加上/bin/才能正确使用execv函数找到并执行date可执行文件。
exec族函数与fork函数的配合
流程图如下 当父进程检测到输入为1的时候创建子进程把配置文件的字段值修改掉。
代码如下
#includestdio.h
#include unistd.h
int main()
{int a 0;int fork_r0;while(1){printf(please input a num\n);scanf(%d,a);if(a1)//输入为1创建子进程{fork_rfork();if(fork_r0)//返回值为两次等于0为子进程{execl(./changeData,changeData,NULL);//找到并执行changeData}}else{printf(no change success\n);}}return 0;
}
上述代码调用execl函数找到并执行的changeData函数如下
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.h
#include string.h
#include stdlib.hint main(int argc,char **argv)
{int fdSrc;char *readBuf NULL;fdSrc open(config,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);char *p strstr(readBuf,leng);if(p NULL){printf(not found\n);exit(-1);}p pstrlen(leng);*p 9;lseek(fdSrc,0,SEEK_SET);int n_write write(fdSrc,readBuf,strlen(readBuf));close(fdSrc);return 0;
}
编译格式是
gcc changeData.c -o changeData//-o后面的可执行文件才能被execl调用
原配置文件config的值如下
peed5
leng1
SCORE90
LEVEL95 只有当输入的值为1时才会创建子进程并使用execl函数找到并执行changeData可执行文件从而将原配置文件config中“leng1”改成“leng9”。