执行程序

原创
2016/11/27 23:07
阅读数 57

一、执行一个新程序

Linux下使用exec()函数执行一个新程序,该函数在文件系统中搜索指定路径的文件,并将该文件内容复制到调用exec()函数的地址空间,取代原进程的内容。

exec()函数并不创建一个新进程。

Linux提供6个exec()函数的泛型,exec()函数原型如下:

#include <unistd.h>
int execl(const char *pathname, const char *arg0, ...);
int execle(const char *pathname, const char *arg0, .../*char*const envp[]*/);
int execv(const char *pathname, char* const argv[]);
int execve(const char *pathname, char * cosntargv[], char * const envp[]);
int execlp(const char *filename, const char *arg0, ...);
int execvp(const char *filename, char * const argv[]);

参数列表中:

  • "l"表示list,说明执行程序的命令行参数以列表的方式提供,并且以NULL结尾,参数个数没有限制。
  • "v"表示vector,说明命令行参数要以二维数组的形式提供给新程序。这个数组的每一行是一个命令行参数。
  • "e"表示传递给新程序的环境变量列表,这个列表是一个二维数组,每一行是一个环境变量。如果没有显示地传递一个环境变量表,那么新程序将复制父进程的环境表。
  • 以"p"结尾的exec()函数表示第一个参数不是完整的路径名,而是一个程序名。这样就需要从环境表中的PATH变量中取得每一项,与第一个参数组合成一个完整的路径。

下面演示使用exec函数。使用execvp()函数,执行当前目录下的hello程序,该程序调用fork()函数创建一个子进程,子进程代码中调用execvp()函数加载hello程序,并使用其代码覆盖子进程的代码。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
  pid_t pid;
  pid = fork();
  if(pid < 0){
    printf("fail to fork\n");
    exit(1);
  }else if(pid == 0){
    /**
     * 调用exec()函数,运行当前目录下的hello程序
     * 该程序不需要任何命令行参数,并且继承父进程的环境表
     */
    if(execl("/home/daowm/WorkSpace/C/linux/ch11/hello", NULL) < 0){
      printf("fail to exec\n");
      exit(0);
    }
    //这里应该永远不会被执行,因为调用exec()函数后这里的代码被hello程序所取代了
    printf("the child is not hello\n");
    exit(0);
  }
  printf("the parent\n");
  return 0;
}

运行结果:

 

二、执行解释器文件

Linux下使用最多的shell脚本,其脚本文件的起始形式为:

#!/bin/sh

shell脚本需要shell解释器来解释执行,而Linux shell程序的路径是/bin/sh。

下面实例使用exec执行shell脚本:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  pid_t pid;
  pid = fork();
  if(pid < 0){
    printf("fail to fork\n");
    exit(1);
  }else if(pid == 0){
    /**
     * 使用execl()函数执行程序,命令行参数表使用NULL结尾
     */
    execl("args.sh", "arg1", "arg2", "arg3", NULL);
    _exit(0);
  }
  exit(0);
}

shell脚本:

#!/bin/sh
#args.sh  输出参数列表
echo No.1 $0
echo No.2 $1
echo No.3 $2
echo No.4 $3

运行结果:

 

三、在程序中执行shell命令

Linux环境编程往往需要调用shell命令进行一些操作,例如需要取得一个目录下的文件名列表时,使用shell命令ls可以轻松地完成。如果不使用shell命令则需要使用opendir()函数打开目录,堆目录中的每一项调用stat()函数取得其文件名。

Linux下使用system()函数调用shell指令,原型如下:

#include <stdlib.h>
int system(const char *cmdstring);

参数cmdstring是需要执行shell命令。system()函数是一个库函数,其中封装了fork、exec、waitpid这3个系统调用。

使用system()函数可以方便地执行shell命令完成一些功能。下面的程序演示了使用system()函数执行ls命令病将其输出到temp.txt文件中,然后打开该文件,输出其内容:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#define MAX 1024

int main(int argc, char *argv[])
{
  int fd, n;
  char buf[MAX];
  if(system("ls > temp.txt") == -1){  //exec ls
    perror("fail to exec command");
    exit(1);
  }

  if((fd = open("temp.txt", O_RDWR)) == -1){  //open temp.txt
    perror("fail to open");
    exit(1);
  }
  if((n = read(fd, buf, MAX)) == -1){  //read file
    perror("fail to read");
    exit(1);
  }
  buf[n] = '\0'; 
  printf("%s\n", buf);
  
  return 0;
}

运行结果:

system()函数的实现原理

system()函数的执行流程分两步,首先调用system()函数的进程创建一个子进程,并调用wait()函数等待进程执行完毕;然后由这个子进程调用exec()函数加载shell运行cmdstring指定的命令。如下所示:

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部