作者:王姗姗,华清远见嵌入式学院讲师。

exec用被执行的程序完全替换调用它的程序的影像。fork创建一个新的进程就产生了一个新的PID,exec启动一个新程序,替换原有的进程,因此这个新的被exec执行的进程的PID不会改变,和调用exec函数的进程一样。
        下面来看下exec函数族:
        #include <unistd.h>
        int execl(const char *path, const char *arg, ...);
        int execlp(const char *file, const char *arg, ...);
        int execle(const char *path, const char *arg, ..., char *const envp[]);
        int execv(const char *path, char *const argv[]);
        int execvp(const char *file, char *const argv[]);
        int execve(const char *path, char *const argv[], char *const envp[]);
        exec函数族装入并运行程序pathname,并将参数arg0(arg1,arg2,argv[],envp[])传递给子程序,出错返回-1。在exec函数族中,后缀l、v、p、e添加到exec后,所指定的函数将具有某种操作能力有后缀:

其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
        我们来看下面的一个实例:
        #include <stdio.h>
        #include <unistd.h>
        #include <string.h>
        #include <errno.h>

int main(int argc,char *argv[],char *envp[])
        {
             char *arg[]={"ls","-a",NULL};
             if(fork()==0)
             {
                 printf("execl...........\n");
                 if(execl("/bin/ls","ls","-a",NULL)<0)
                 {
                      fprintf(stderr,"execl failed:%s",strerror(errno));
                      return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execv...........\n");
                 if(execv("/bin/ls",arg)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execlp...........\n");
                 if(execlp("ls","ls","-a",NULL)<0)
                 {
                     fprintf(stderr,"execl failed:%s",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execvp...........\n");
                 if(execvp("ls",arg)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execle...........\n");
                 if(execle("/bin/ls","ls","-a",NULL,envp)<0)
                 {
                     fprintf(stderr,"execl failed:%s",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execve...........\n");
                 if(execve("/bin/ls",arg,envp)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }

return 0;
        }
        程序里调用了ls这个Linux常用的系统命令。
        由于各个子进程执行的顺序无法控制,所以有可能出现一个比较混乱的输出--各子进程打印的结果交杂在一起,而不是严格按照程序中列出的次序。
        编译并运行:

下面我们来分析下所写的程序。
        其实我们留心看一下这6个函数,可以发现前3个函数都是以execl开头的,后3个都是以execv开头的。
        首先来比较前两个函数execv和execl。execv开头的函数是把参数以"char *argv[]"这样的形式传递命令行参数。而execl开头的函数采用了我们更容易习惯的方式,把参数一个一个列出来,然后以一个NULL表示结束,也可以写成(char *)0。
        其次紧跟着的2个以p结尾的函数execlp和execvp。与其他几个函数相比,除execlp和execvp之外的4个函数都要求,它们的第1个参数path必须是一个完整的路径,如"/bin/ls";而execlp和execvp的第1个参数file可以简单到仅仅是一个文件名,如"ls",这两个函数可以自动到环境变量PATH制定的目录里去寻找。
        最后两个函数execle和execve,都使用了char *envp[]来传递环境变量。在全部6个函数中,只有execle和execve需要传递环境变量,其它的4个函数都没有这个参数,这并不意味着它们不传递环境变量,这4个函数将把默认的环境变量不做任何修改地传给被执行的应用程序。而execle和execve会用指定的环境变量去替代默认的那些。
        最后要强调一点,大家在平时的编程中,如果用到了exec函数族,一定记得要加错误判断语句。因为与其他系统调用比起来,exec很容易受伤,被执行文件的位置,权限等很多因素都能导致该调用的失败。最常见的错误是:

1.    找不到文件或路径,此时errno被设置为ENOENT;
        2.    数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT;
        3.    没有对要执行文件的运行权限,此时errno被设置为EACCES。

exec函数族的使用的更多相关文章

  1. exec函数族实例解析

    exec函数族实例解析 fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的 ...

  2. exec函数族,守护进程,线程同步和互斥

    2015.3.2 进程和程序有三点不同:1,存在位置不同,程序:硬盘,磁盘.进程:内存2. 程序是静态的,进程是动态的 执行./a.out -->bash->bash程序调用fork()- ...

  3. linux exec函数族

    1.简介 在Linux中,并不存在exec()函数,exec指的是一组函数,一共有6个,分别是: #include <unistd.h>   extern char **environ; ...

  4. Linux进程控制——exec函数族

    原文:http://www.cnblogs.com/hnrainll/archive/2011/07/23/2114854.html 1.简介 在Linux中,并不存在exec()函数,exec指的是 ...

  5. Linux 环境下 fork 函数和 exec 函数族的使用

    前言 接触 Linux 已经有几个月了,以前在网上看各路大神均表示 Windows 是最烂的开发平台,我总是不以为然,但是经过这段时间琢磨,确实觉得 Linux 开发给我带来不少的便利.下面总结一下学 ...

  6. Linux进程实践(3) --进程终止与exec函数族

    进程的几种终止方式 (1)正常退出 从main函数返回[return] 调用exit 调用_exit/_Exit (2)异常退出 调用abort   产生SIGABOUT信号 由信号终止  Ctrl+ ...

  7. exec函数族

    进程程序替换 进程程序替换原理 fork创建子进程执行的是和父进程相同的程序(也有可能是某个分支),通常fork出的子进程是为了完成父进程所分配的任务,所以子进程通常会调用一种exec函数(六种中的任 ...

  8. exec函数族的作用与讲解

    apue看到第八章,对exec函数族的理解一直都很混乱,总觉得不对劲儿,其实不能理解的先暂时跳过,看到后面,再结合实例也就慢慢的理解了. 以下内容转自:http://www.cppblog.com/p ...

  9. 1.2 Linux中的进程 --- fork、vfork、exec函数族、进程退出方式、守护进程等分析

    fork和vfork分析: 在fork还没有实现copy on write之前,Unix设计者很关心fork之后立即执行exec所造成的地址空间浪费,也就是拷贝进程地址空间时的效率问题,所以引入vfo ...

随机推荐

  1. MemAdmin 轻量级可视化Memcached管理工具

    蛮好用的 具体功能看图 开源地址:https://github.com/junstor/memadmin

  2. HTTP Error 500.22 - Internal Server Error 错误解决方案

    1. 首先进入IIS ,配置IIS 应用程序池的.Net Framework版本 2. 点击左侧应用程序池,再单机右侧设置,选择版本 3. 设置为经典模式 如若遇到以下错误: 解决方案:删除confi ...

  3. Nginx报错: "Too many open files accept" 和 "could not build the server_names_hash"

    一.访问Nginx时,报错:"accept() failed (24: Too many open files)"原因时:nginx的连接数超过了系统设定的最大值造成的. 处理办法 ...

  4. Redis数据"丢失"讨论及规避和解决的几点总结

    Redis大部分应用场景是纯缓存服务,请求后端有Primary Storage的组件,如MySQL,HBase;请求Redis的键未命中,会从primary Storage中获取数据返回,同时更新Re ...

  5. 几何学观止(Riemann流形部分)

    上承这个页面,相较之前,增加了古典的曲线曲面论,这部分介绍得很扼要,Riemann流形介绍得也很快,花了仅仅30页就介绍到了Gauss-Bonnet公式.同时配上了提示完整的习题. 几何学观止-Rie ...

  6. D. Mysterious Crime

    链接 [http://codeforces.com/contest/1043/problem/D] 题意 给你一个m*n的矩阵(m<=10,n<=1e5), 每一行的数字是1到n里不同的数 ...

  7. 跟踪分析Linux内核的启动过程--实验报告 分析 及知识重点

    跟踪分析Linux内核的启动过程 攥写人:杨光  学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.stud ...

  8. C程序设计教学小结(选择结构)

    1. 函数使用的三个问题 函数声明语句   void add();   或  int add(int x,int y); 函数调用            add();     c=add(a,b) 函 ...

  9. 第三个Sprint ------第四天

    出题代码 package com.app.senior_calculator; import java.io.Serializable; public class Question implement ...

  10. WIN10护眼色

    参看文章:http://www.xitongcheng.com/jiaocheng/win10_article_10326.html WIN10:[HKEY_CURRENT_USER\Control ...