41.1 创建子进程的函数

有三个原语可用于创建运行程序的新子进程。其中之一 make-process 会创建异步进程并返回进程对象(see 创建异步进程)。另外两个 call-processcall-process-region 会创建同步进程且不返回进程对象(see 创建同步进程)。还有多种高层函数使用这些原语来运行特定类型的进程。

同步与异步进程将在后续小节说明。由于这三个函数的调用方式相似,此处先描述它们共用的参数。

在所有情况下,函数都会指定要运行的程序。若文件不存在或无法执行,则会发出错误信号。如果文件名为相对路径,变量 exec-path 包含用于搜索的目录列表。Emacs 启动时会根据环境变量 PATH 的值初始化 exec-path。标准文件名构造 ‘~’、‘.’ 与 ‘..’ 在 exec-path 中按常规方式解析,但不识别环境变量替换(如 ‘$HOME’);可使用 substitute-in-file-name 完成替换(see 文件名展开相关函数)。列表中的 nil 代表 default-directory

执行程序时还会尝试为指定名称添加后缀:

User Option: exec-suffixes

该变量是一个后缀(字符串)列表,用于尝试添加到指定的程序文件名后。若希望按指定名称原样尝试,列表中应包含 ""。默认值与系统相关。

注意: 参数 program 仅包含程序文件名,不可包含任何命令行参数。你必须使用单独的参数 args 来提供这些参数,具体如下文所述。

每个创建子进程的函数都有一个 buffer-or-name 参数,用于指定程序输出的去向。它应为缓冲区或缓冲区名;若为缓冲区名,不存在时会自动创建。也可以是 nil,表示丢弃输出,除非有自定义过滤器函数处理(See 进程过滤器函数Lisp 对象的读取与打印)。通常应避免多个进程向同一缓冲区输出,否则输出会随机混杂。对于同步进程,可将输出发送到文件而非缓冲区(因此对应的参数更适合称为 destination)。默认情况下,标准输出与标准错误流会指向同一目标,但三个原语均支持可选地将标准错误流导向不同目标。

三个创建子进程的函数均支持为进程指定命令行参数。对于 call-processcall-process-region,参数以 &rest 参数 args 的形式提供。对于 make-process,要运行的程序及其命令行参数均以字符串列表指定。命令行参数必须全部为字符串,并以独立参数字符串的形式传递给程序。通配符与其他 Shell 构造在这些字符串中无特殊含义,因为字符串会直接传递给指定程序。

子进程从 Emacs 继承环境,但你可以通过 process-environment 指定覆盖项。See 操作系统环境。子进程的当前目录取自 default-directory 的值。

Variable: exec-directory

该变量的值为字符串,表示包含 GNU Emacs 自带且供 Emacs 调用的程序的目录名。程序 movemail 就是此类程序的例子;Rmail 使用它从收件箱获取新邮件。

User Option: exec-path

该变量的值为目录列表,用于搜索在子进程中运行的程序。每个元素为目录名(字符串)或 nilnil 代表默认目录(即 default-directory 的值)。See executable-find, 查看搜索细节。

program 参数不是绝对文件名时,call-processstart-process 会使用 exec-path 的值。

通常不应直接修改 exec-path。而应在启动 Emacs 前正确设置 PATH 环境变量。尝试独立于 PATH 修改 exec-path 可能导致令人困惑的结果。

Function: exec-path

此函数是变量 exec-path 的扩展。若 default-directory 指向远程目录,该函数返回用于在对应远程主机上搜索程序的目录列表。若为本地 default-directory,函数仅返回变量 exec-path 的值。

启动属于 Emacs 分发套件的程序时,必须考虑到程序可能因系统上的可执行文件命名限制而被重命名。

例如,不应直接启动 ctags,而应使用 ctags-program-name 的值。同样,不应直接启动 movemail,而应启动 movemail-program-nameetagshexlemacsclientrcs2logebrowse 同理。