[C]_C技巧: 在一个程序里面运行另一个程序, exec,spawn函数族,system函数

1. 怎样在一个程序运行后面运行另一个程序? 

Refer to: http://campus.chsi.com.cn/xy/com/200812/20081203/11208458.html

  1、 在一个程序里面运行另一个程序的最简单的方法是把它们依次列入一个批处理文件(扩展名为。BAT的文件),在执行该批处理文件时,其中所列程序就会自动运行。 

  在C或DOS中,都没有一种特定的方法来完成“在一个程序结束后运行另一个程序”这样一种函数调用。然而,C提供了两组函数,它们允许一个程序随时可以运行另一个程序,而后者的运行将结束前者的运行。如果你将这样的函数调用放在第一个程序的末尾,就能达到上述目的。C提供的这两组函数是exec()和spawn()函数族,其中的每一个函数都具有一种区别于其它函数的功能。exec()函数族包含这样一些成员:execl()、execle()、execlpe()、execv()、execve()和execvpe()。下面列出了这中中的e,l,p和v等后缀的含义:e 明确地把一个指向环境参数的指针数组传递给子进程l考试,大提示 把命令参数上传递给要执行的程序p 通过环境变量PATH找到要执行的函数v 把命令行参数以一个指针数组的形式传递给要执行的程序在程序中选用哪一个函数完全取决于你以及要执行的程序的需要。下例中的程序调用了其参数由命令行指定的另一个程序: #include<stdio.h> 
  #include<process.h> 
  char *envString[]= 
  "COMM_VECTOR=0x63", 
  "PARENT=LAUNCH.EXE", 
  "EXEC=EDIT.COM", 
  NULL}; 
  void main(int argc,char **argv) 
  { 
  _execvpe("EDIT.COM",argv,envString); 
  printf("If you can read this sentence,the exec did'nt happen!\n"); 
  } 

  上面这个短小的例子调用_execvpe()来执行DOS的文件编辑器EDIT.COM,EDIT程序的参数来自该例的命令行。在调用_execvpe函数后,上例中的程序就结束了EDIT程序退出时,你将返回到DOS提示符。如果printf语句的打印内容出现在屏幕上,则说明_execvpe()函数调用出了/BBS">问题,因为如果它调用成功,就不会有上述结果。注意上例所提供的EDIT.COM的环境变量是没有任何意义的。然而如果上例要执行一个需要环境变量的程序,那么所提供的环境变量就能供给该程序使用了。 

  用spawn函数同样可以完成上例所做的工作。spwan()函数族包括这样一些成员:spawnl()、spawnle()、spawnlp()、spawnlpe()、spawnv()、spawnve()、spawnvp()和spawn()函数。这些函数名中的e,l,p,和v等后缀的含义与exec()函数族函数名中的相同。实际上,spawn()函数族与exec()函数族基本相同,只不过有一点小小的差别——spawn()函数既可以在结束原来的程序后启动另一个程序,也可以启动另一个程序并在该程序结束后返回到原来的程序中。spawn()函数的参数与exec()函数的基本相同,只不过需要增加一个参数——你必须用_P_OVERLAY(结束原来的程序)或_P_WAIT(结束后返回到原来的程序)作为spawn()函数的第一个参数。下例用spawn()函数完成了与前面的例子相同的工作: #include<stdio.h> 
  #include<process.h> 
  char *envString[]={ 
  "COMM_VECTOR=0x63", 
  "PARENT=LAUNCH.EXE", 
  "EXEC=EDIT.COM", 
  NULL}; 
  void main(int argc,char **argv) 
  { 
  _spawnvpe(_P_OVERLAY,"EDIT.COM",argv,envString); 
  printf("If can read this sentence,the exec did'nt happen!\n"); 
  } 

  这里唯一区别是"exec"变为"spawn",并且增加了模式(mode)参数。spawn()函数有复盖和等待两种相对立的功能,它使你可以在spawn()运行期间做出是等待还是离开的决定,如果使用_P_WAIT,那么就是等待。 

  2、还有一种方法可以完成在一个程序运行期间运行另一个程序,即使用system()函数。system()函数与前面讲的函数相似但也有不同的地方。除了挂起(而不是结束)当前程序去执行新的程序外,system()还需要启动COMMAND.COM命令/free/fy">翻译程序(或者其它任何运行在你的上命令/free/fy">翻译程序)。如果system()找不到COMMAND命令,那么它就不去执行所要求的程序(这一点与exec()或spawn()函数是不同的)下面的例子调用EDIT.COM编辑一个文件: #include<stdio.h> 
  #include<process.h> 
  #include<stdlib.h> 
  char argStr[256]; 
  void main(int argc,char **argv) 
  { 
  int ret; 
  sprintf(argStr,"EDIT %s",(argv[1]==NULL?"HELLO":argv[1])); 
  ret=system(argStr); 
  printf("system() returned %d\n",ret); 
  } 

  与上面的例子一样(使用_P_WAIT),在system()调用后面的printf()语句会执行。因为原来的程序只是挂起而不是终止。在每一种情况下,system()都会返回一个表示是否成功地运行了所指定的程序的值,而不会返回所指定的程序的返回值。

 

2. spawn 系列函数 创建并运行子进程

Refer to:http://blog.csdn.net/xiaosi2468/article/details/6401874

spawn 系列函数 

L 系列:

int    spawnl    (int mode, char *path, char *arg0, char *arg1, ... , NULL);

int    spawnlp    (int mode, char *path, char *arg0, char *arg1, ..., NULL);

int    spawnle    (int mode, char *path, char *arg0, char *arg1, ..., NULL, char *envp[]);

int    spawnlpe    (int mode, char *path, char *arg0, char *arg1, ..., NULL, char *envp[]); 

V 系列:

int    spawnv    (int mode, char *path,  char *arg[], NULL);

int    spawnvp    (int mode, char *path, char *arg[] , NULL);

int    spawnve    (int mode, char *path, char *arg[] , NULL, char *envp[]);

int    spawnvpe  (int mode, char *path,  char *arg[] , NULL, char *envp[]);

说明: 原型在 process.h

 spawn...系列函数可以加载并运行称为子进程的其它文件。必须有足够的内存。mode 值用心确定调用函数(父进程)在调用 spawn... 之后 所采取的动作:

P_WAIT      父进程挂起直到子进程执行完毕

P_NOWAIT  父进程和子进程同时运行(目前 TC2 不支持)

P_OVERLAY 子进程将覆盖父进程原有的存储区位置, 这与 exec... 调用相同

 

* path 是被调用子进程文件名。spawn...函数通过标准的 DOS 搜索算法来查找 


path:

1. 如果木有扩展名或者句点:先查找该名;如果没有找到,就加上.com,.exe扩展名再找

2. 如果给定扩展名, 直接查找给定 的文件

3. 如果给出句点, 则查找没有扩展名的文件

4. 如果path没有包含确定的目录, 含有 p 后缀的 spawn...函数 首先在当前目录下查找,

如果找不到,就 再查找DOS环境变量PATH所指定的目录

#include<stdio.h>
#include<process.h>
void main()
{
    int    result;
    result = spawnlp (P_WAIT, "h://o utput// ten2bin.exe", NULL);
    if (result == -1)
    {
        perror("Error from spawnl");
        exit(1);
    }
}

 

加在 spawn...系列函数后的后缀 L, V, P, E 表示命名函数的某种操作能力;

L:

表明指针参数 arg0, arg1, ... 作为独立参数进行传递。通常, L 后缀用于事先知道待传递参数个数的情况

V:

表明扎针参数 arg0], arg[1], ..., arg[n] 作为指针数组进行传递。通常, V 后缀用于待传递参数个数可变的情况

P:

表明如果没有指定目录,则首先在当前目录下查找文件,没有找到时再到环境变量PATH 指定的路径查找

E:

表明参数envp可以传到子进程,用以改变子进程的环境。在没有e后缀的情况下,子进程将继承父进程的环境

 

spawn... 系列函数必须至少传递一个 参数(arg0 或 arg[0])给子进程,该参数约定为 path 的一个拷贝。类似于 main(int argc, char * argv[])中的 argv[0], argn / arg[n] 后的 NULL 表示参数表结束。

 

执行成功时,返回值为子进程的退出状态(0为正常终结)。如果子进程 调用 了非0参数的exit函数,退出状态则为非0值。

出现错误时,spawn...函数返回值 -1, 并将全局变量errno设置为下列之一。

E2BIG                参数表太长

EINVAL              无效参数

ENOENT             路径或者文件名没有找到

ENOEXEC           运行格式错

ENOMEM            无足够内存

 

process.h中的一些定义:

/*  Modes available as first argument to the spawnxx functions. */

#define P_WAIT      0    /* child runs separately, parent waits until exit */
#define P_NOWAIT  1    /* both concurrent -- not implemented */
#define P_OVERLAY 2    /* child replaces parent, parent no longer exists */

 

posted @ 2013-10-09 16:53  金石开  阅读(2810)  评论(0)    收藏  举报