• 进程控制之解释器文件


    所有现今的UNIX系统都支持解释器文件(interpreter file)(也可称为解释器脚本)。这种文件是文本文件其起始行格式是:

    #! pathname [optional-argument]

    感叹号和pathname之间的空格是可选的。最常见的解释器文件以下列行开始:

    #!/bin/sh

    pathname通常是绝对路径名,对它不进行什么特殊的处理(即不使用PATH进行路径搜索)。对这种文件的识别是由内核作为exec系统调用处理的一部分来完成的内核调用exec函数的进程实际执行的并不是该解释器文件,而是该解释器文件第一行中pathname所指定的文件。一定要将解释器文件(文本文件,它以#!开头)和解释器(由该解释器文件第一行中的pathname指定)区分开来。(我们可以认为:解释器文件就是在首行指定了其所使用的解释器的文本文件。)

    要知道很多系统对解释器文件的第一行有长度限制。这些限制包括#!、pathname、可选参数、终止换行符以及空格数。在Linux中支持该限制为127字节。

    实例

    让我们观察一个实例,从中可了解当被执行的文件是解释器文件时,内核如何处理exec函数的参数及该解释器文件第一行的可选参数。程序清单8-10调用exec执行一个解释器文件。

    程序清单8-10 执行一个解释器文件的程序

    [root@localhost apue]# cat prog8-10.c
    #include "apue.h"
    #include <sys/wait.h>
    
    int
    main(void)
    {
            pid_t   pid;
            if((pid = fork()) < 0)
            {
                    err_sys("fork error");
            }
            else if(pid == 0)       /* child */
            {
                    if(execl("/home/zhu/apue/testinterp",
                            "testinterp", "myarg1", "MY ARG2", (char *)0) < 0)
                            err_sys("execl error");
            }
            if(waitpid(pid, NULL, 0) < 0)   /* parent */
                    err_sys("waitpid error");
            exit(0);
    }

    程序清单8-10中被执行的解释器文件内容如下(只有一行):

    [root@localhost apue]# cat testinterp
    #!/home/zhu/apue/echoarg foo

    程序echoarg(解释器)回送每一个命令行参数(它就是程序清单7-3,参见:http://www.cnblogs.com/nufangrensheng/p/3507949.html)。

    程序清单8-10运行结果:

    [root@localhost apue]# ./prog8-10
    argv[0]: /home/zhu/apue/echoarg
    argv[1]: foo
    argv[2]: /home/zhu/apue/testinterp
    argv[3]: myarg1
    argv[4]: MY ARG2

    注意,当内核exec该解释器(/home/zhu/apue/echoarg)时,argv[0]是该解释器的pathname,argv[1]是解释器文件中的可选参数,其余参数是pathname(/home/zhu/apue/testinterp),以及程序清单8-10中调用execl的第二个和第三个参数(myarg1和MY ARG2)。调用execl时的argv[1]和argv[2]已右移了两个位置(?)。注意,内核取execl调用中的pathname而非第一个参数(testinterp),因为一般而言,pathname包含了比第一个参数更多的信息(通常第一个参数只是pathname的一部分)。

    总的来说,当内核exec解释器时,其命令行参数依次是该解释器的pathname、解释器的可选参数、解释器文件的pathname、exec函数调用参数列表中argv[0]以后的参数(不包括argv[0],通常argv[0]只是解释器文件pathname中的一部分)。(http://www.cnblogs.com/nufangrensheng/p/3510821.html中有提到我们可将argv[0]设置为任何字符串。

    另外还有一篇关于解释器和解释器文件比较简明扼要的一篇文章,可参考:http://www.cnblogs.com/beacer/archive/2012/09/16/2687659.html

    实例

    在解释器pathname后可跟随可选参数。如果一个解释器程序支持-f选项,那么在pathname后经常使用的可选参数就是-f。

    例如,可以以下列方式执行awk(1)程序:

    awk -f myfile

    它告诉awk从文件myfile中读取awk程序。

    如果在解释器文件中使用-f选项,则可以写成:

    #!/bin/awk -f
    ......

    如果我们在myfile的第一行写:#!/bin/awk -f,那么我们想要执行awk程序myfile时,不必再输入命令awk –f myfile,而是直接输入命令myfile即可。

    例如,程序清单8-11为/usr/local/bin/awkexample这样一个解释器文件。

    程序清单8-11 作为解释器文件的awk程序

    #!/bin/awk -f
    BEGIN {
        for(i=0; i<ARGC; i++)
            printf "ARGV[%d] = %s
    ", i, ARGV[I]
        exit
    
    }

    如果路径前缀之一是/usr/local/bin,则可以用下列方式执行程序清单8-11:

    [root@localhost apue]# awkexample file1 FILENAME2 f3
    ARGV[0] = awk
    ARGV[1] = file1
    ARGV[2] = FILENAME2
    ARGV[3] = f3

    其实,shell会这样调用exec:

    exec("/usr/local/bin/awkexample",
            "awkexample", "file1", "FILENAME2", "f3", NULL);

    但是,实际上exec执行的是解释器/bin/awk而不是解释器文件awkexample,并且其命令行参数是:

    /bin/awk -f /usr/local/bin/awkexample file1 FILENAME2 f3

    是否一定需要解释器文件呢?那也不完全如此。但是它们确实使用户得到效率方面的好处,其代价是内核的额外开销(因为识别解释器文件的是内核)。

    由于下述理由,解释器文件是有用的:

    (1)有些程序是用某种语言编写的脚本,解释器文件可将这一事实隐藏起来。例如,为了执行程序8-11,只需使用下列命令行:

    awkexample opitonal-arguments

    而并不需要知道该程序实际上是一个awk脚本,否则就需要以下列方式执行该程序:

    awk -f awkexample optional-arguments

    (2)解释器脚本在效率方面也提供了好处。通常,用一个shell脚本代替解释器脚本需要更多的开销。

    (3)解释器脚本使我们可以使用除/bin/sh以外的其他shell来编写shell脚本。(当execlp找到一个非机器可执行的可执行文件时(shell脚本是一个可执行文件,但却不是机器可执行的),它总是调用/bin/sh来解释执行该文件。)此时,我们只需要在解释器脚本首行指明所用的shell即可。

    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

  • 相关阅读:
    EXTJS 基本使用
    EXTJS 常用控件的使用
    EXTJS 验证与表单提交
    EXTJS 常用方法
    禁用USB移动盘的方法
    常用sql 函数练习示例
    .Net 中的反射(反射特性) Part.3
    Delphi調用.NET的WebService
    c#写的串口通讯
    打印控制
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3511768.html
Copyright © 2020-2023  润新知