1,解释器文件
前面提到的exec文件都是以一个可执行文件为输入参数,但是实际上其输入参数也可以是一个文本文件。文本文件如何执行?我们在该文件的第一行指定一个可执行程序(解释器)即可。而这个文本文件就被成为解释器文件。
解释器文件的第一行的格式如下:
#! pathname [option-argument]
解释器文件总是以#!开头。
pathname指定解释器所在的目录,通常是绝对路径名。
option-argument是传递给该解释器的参数,可选。
注意,解释器文件也必须拥有合适的可执行权限,否则无法执行。
所以最常见的解释器文件就是如下:
#! /bin/sh
2, 例子
这回我们实际上要准备好3个文件:
1,狸猫程序;
2,解释器文件,里面要写上狸猫程序的完整路径;
3,主程序,调用execl,实现狸猫换太子,不过现在传递给execl的是解释器文件的目录;
2.1 狸猫程序
我们写一个打印所有输入参数的文件echoarg.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
for(int i = 0; i < argc; i++){
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
将其编译成echoarg.
2.2 解释器文件
新建文本文件testinterp,内容如下:
#! /home/huangyang/code/echoarg HuangYang
在这里指定了第一步编译出的狸猫程序的目录,并且指定了一个输入参数HuangYang
然后,别忘了为这个文件加上可执行权限。
2.3 主程序
这个主程序和上一节的差不多,只不过execl的输入参数变了。如下:
int main(){
pid_t pid;
//用fork产生一个与自己一模一样的子进程
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
} else if(pid == 0){ //注意,是在子进程内调用execl
//这里指定的是解释器文件,第一个参数XXX作用不明。通常就写解释器文件的名字
//但换成其他的貌似也没影响
if(execl("/home/huangyang/code/testinterp", "XXX","Bihan", (char*)0) < 0){
printf("execl error!\n");
exit(1);
}
}
printf("parent process\n");
//这里waitpid还能等到hello,说明hello的pid就是原先子进程的pid,
//父进程就把hello当自己的子进程,狸猫换太子成功
if(waitpid(pid, NULL, 0) < 0){
printf("wait error!\n");
exit(1);
}else{
printf("wait end\n");
}
return 0;
}
执行的结果如下:
可以看到,
第0个输入参数,是最终狸猫的完整路径;
第1个输入参数,是解释器文件里给狸猫传递的参数(option-argument·)
第2个输入参数,是解释器文件的完整路径;
第3个输入参数,是主程序里传递给解释器的第2个输入参数,第一个输入参数“XXX”被忽略了。