linux都支持解释器文件(interpreter file),文件是文本文件,格式为:
#! pathname[ optional-argument]
感叹号和pathname之间空格可选,最常见的是: #! /bin/sh
pathname一般是绝对路径(它不会使用PATH做路径搜索),对这个文件识别是由内核做为exec系统调用处理的。内核exec执行并不是解释器文件,而是第一行pathname制定的文件。一定要将解释器文件(文本文件,以#!开头),和解释器(由pathname指定)区分开。
如下,我自己写一个解释器程序echoarg.c:
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char* argv[])
{
int i;
for (i=0; i< argc; i++)
{
printf("argv[%d]: %s \n", i, argv[i]);
}
exit(0);
}
这个解释器的目的就是将程序的所有参数打印出来,使用gcc将程序编译为echoarg。
编写一个脚本程序testsh调用该解释器程序:
#! /home/clou-tcu/kongchengbo/test-code/testshell/echoarg foo1 foo2
编写一个程序test.c,调用脚本并执行程序,如下
#include "stdio.h"
#include "stdlib.h"
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
if (pid = vfork() < 0)
{
printf("fork error \n");
}
else if (pid == 0)
{
if (execl("/home/clou-tcu/kongchengbo/test-code/testshell/testsh", "testsh", "my arg-1", "MY ARG-2", (char *)0) < 0)
printf("excel error \n");
}
if (waitpid(pid, NULL, 0) < 0)
printf("waitpid error \n");
exit(0);
}
执行如下:
kongcb@tcu-Lenovo:/home/clou-tcu/kongchengbo/test-code/testshell$ gcc test.c -o test.out
kongcb@tcu-Lenovo:/home/clou-tcu/kongchengbo/test-code/testshell$ ./test.out
argv[0]: /home/clou-tcu/kongchengbo/test-code/testshell/echoarg
argv[1]: foo1 foo2
argv[2]: /home/clou-tcu/kongchengbo/test-code/testshell/testsh
argv[3]: my arg-1
argv[4]: MY ARG-2
argv[0]: /home/clou-tcu/kongchengbo/test-code/testshell/echoarg
argv[1]: foo1 foo2
argv[2]: /home/clou-tcu/kongchengbo/test-code/testshell/testsh
argv[3]: my arg-1
argv[4]: MY ARG-2
kongcb@tcu-Lenovo:/home/clou-tcu/kongchengbo/test-code/testshell$
如上可知:
1:参数0,实际上是testsh脚本调用的echoarg,参数1就是脚本testsh给的参数foo1 foo2
2:在execl调用的参数1和2,实际第一个参数是完整路径的,所以只需要第一个参数即可
但有两个问题还需要思考下:
1:为啥为打印两遍呢?
难道是printf将数据放置到缓存中,导致parent退出的时候也打印一次,那尝试printf之后,冲洗下内存试试,修改echoarg.c,如下:
int main(int argc, char* argv[])
{
int i;
// setbuf(stdout, NULL);
for (i=0; i< argc; i++)
{
printf("argv[%d]: %s \n", i, argv[i]);
}
fsync(STDOUT_FILENO);
exit(0);
}
打印完成后fsync,实际运行的时候,还是打印两次,setbuf将输出不设置缓存,也会打印,这是啥问题呢?还需要再研究试试!