一,exec族函数
当我们用fork创建子进程后,经常调用exec族函数去执行新的可执行文件。
注:调用exec族函数并不创建新进程所以进程ID不变。
exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe
#include
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族函数调用成功后不会返回,失败返回-1;
函数参数值说明:
path:可执行文件所在路径(/绝对路径比如/bin/ls ./当前路径)
arg:可执行程序所带参数,第一个为可执行文件名,第二个即为参数,没有带路径必须以NULL结尾比如:execl("./bin/echoarg",“echoarg”,“abc”,NULL)。
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量
带l(参数列表)得exec组函数(以execl函数为例)文件参数必须以NULL结尾
#include
#include
#include int main(void)
{printf("test before!\n");if(execl("/bin/ls","ls",NULL,NULL) == -1){printf("execl failed!\n");perror("why");}printf("test after!\n");return 0;
}
~
执行结果:
test before!
10.c 11.c 12.c 13.c 1.c 2.c 3.c 4.c 5.c 6.c 7.c 8.C 9.c a.out test test.c
如果execl函数不指定路径名,执行结果如下
#include
#include
#include int main(void)
{printf("test before!\n");if(execl("/bin/ls","ls",NULL,NULL) == -1){printf("execl failed!\n");perror("why");}printf("test after!\n");return 0;
}
结果:
test before!
execl failed!
why: No such file or directory
test after!
但是调用带p函数,以execlp函数为例则无需指定可执行文件路径(如果此路径包含在环境变量PATH中)
#include
#include
#include int main(void)
{printf("test before!\n");if(execlp("ls","-l",NULL) == -1){printf("execl failed!\n");perror("why");}printf("test after!\n");return 0;
}
如果是在环境变量下,可以直接运行,如果不是,调用带P函数的时候需要,将所要执行的可执行文件添加到环境变量:
使用pwd命令得到当前路径
使用echo $PATH命令查看当前环境变量PATH
使用sudo export PATH=$PATH:(可执行文件路径)
带v不带l的一类exac函数,包括execv、execvp、execve,应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
#include
#include
#include
int main(void)
{printf("before execlp\n");char *argv[] = {"ls","-l",NULL};if(execvp("lS",argv) == -1) {printf("execvp failed!\n"); }printf("after execlp\n");return 0;
}
注:exec族函数调用失败是会产生一个错误码可以用perror()函数来查看;
二,system函数(封装后的exec函数)
直接将需要执行的命令格式作为参数输入:
#include
#include
#include int main(void)
{printf("test before!\n");system("ls -l");printf("test after!\n");return 0;
}
直接调用指令ls -l
三,popen函数(和system相比它可以获取运行结果)
popen执行玩命令后将结果放在管道中以流的形式读取进一个数组,并且不会在终端显示命令执行结果(system会把所有结果打印在终端上)
如system函数结果
test before!
10.c 11.c 12.c 13.c 14.c 15.c 1.c 2.c 3.c 4.c 5.c 6.c 7.c 8.C 9.c a.out test test.c
test after!
popen函数代码
#include
#include
#include int main(void)
{char str[1024] = {0};FILE *fp;fp = popen("date","r");int n_read = fread(str,1,1024,fp);printf("read str %d byte,str = %s \n",n_read,str);return 0;
}
代码执行结果如下(输出数组str)
read str 29 byte,str = Sat Aug 22 08:50:16 PDT 2020
如果不输出数组则在终端不输出结果!