1.exec家族一共有六个函数,分别是:

  (1)int execl(const char *path, const char *arg, ......);

  (2)int execle(const char *path, const char *arg, ...... , char * const envp[]);

  (3)int execv(const char *path, char *const argv[]);

  (4)int execve(const char *filename, char *const argv[], char *const envp[]);

  (5)int execvp(const char *file, char * const argv[]);

  (6)int execlp(const char *file, const char *arg, ......);

  其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

 exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

  与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。

  

  2.它们之间的区别:

  1)前四个取路径名做为参数,后两个取文件名做为参数,如果文件名中不包含 “/” 则从PATH环境变量中搜寻可执行文件, 如果找到了一个可执行文件,但是该文件不是连接编辑程序产生的可执行代码文件,则当做shell脚本处理。

  2)前两个和最后一个函数中都包括“ l ”这个字母 ,而另三个都包括“ v ”, " l "代表 list即表 ,而" v "代表 vector即矢量,也是是前三个函数的参数都是以list的形式给出的,但最后要加一个空指针,如果用常数0来表示空指针,则必须将它强行转换成字符指针,否则有可能出错。,而后三个都是以矢量的形式给出,即数组。

  3)与向新程序传递环境变量有关,如第二个和第四个以e结尾的函数,可以向函数传递一个指向环境字符串指针数组的指针。即自个定义各个环境变量,而其它四个则使用进程中的环境变量。

  3.实例:

  (1)在平时的编程中,如果用到了exec函数族,一定记得要加错误判断语句。先判断execl的返回值,如果出错,可以用perror( )函数打印出错误信息。

  如:if (execl(“path”,”..””(char *)0) < 0)

  {

        perror(“execl error!”);

     }

  如果调用出错,可输出:execl error!: 错误原因   这样可方便查找出错原因

  (2)注意下面书写格式:

  先定义一个指针数组:char *argv[]={“ls”,”-l”,(char *)0}

  用execv调用ls:    execv(“/bin/ls”,argv)

   如果用execvp

  execvp(“ls”,argv)      //直接写ls就可以了

  注意:

  execl调用shell 时,要在shell脚本中指明使用的shell版本:#!/bin/bash。在命令行下执行shell脚本,系统为它自动打开一个shell,在程序中没有shell,在调用shell脚本时,会出错,所以要在shell脚本中先打开shell。

  (3)

 #ifdef HAVE_CONFIG_H
#include <config.h>
#endif #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h> int main(int argc, char *argv[])
{
//以NULL结尾的字符串数组的指针,适合包含v的exec函数参数
char *arg[] = {"ls", "-a", NULL}; /**
* 创建子进程并调用函数execl
* execl 中希望接收以逗号分隔的参数列表,并以NULL指针为结束标志
*/
if( fork() == )
{
// in clild
printf( "1------------execl------------\n" );
if( execl( "/bin/ls", "ls","-a", NULL ) == - )
{
perror( "execl error " );
exit();
}
} /**
*创建子进程并调用函数execv
*execv中希望接收一个以NULL结尾的字符串数组的指针
*/
if( fork() == )
{
// in child
printf("2------------execv------------\n");
if( execv( "/bin/ls",arg) < )
{
perror("execv error ");
exit();
}
} /**
*创建子进程并调用 execlp
*execlp中
*l希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志
*p是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件
*/
if( fork() == )
{
// in clhild
printf("3------------execlp------------\n");
if( execlp( "ls", "ls", "-a", NULL ) < )
{
perror( "execlp error " );
exit();
}
} /**
*创建子里程并调用execvp
*v 望接收到一个以NULL结尾的字符串数组的指针
*p 是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件
*/
if( fork() == )
{
printf("4------------execvp------------\n");
if( execvp( "ls", arg ) < )
{
perror( "execvp error " );
exit( );
}
} /**
*创建子进程并调用execle
*l 希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志
*e 函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境
*/
if( fork() == )
{
printf("5------------execle------------\n");
if( execle("/bin/ls", "ls", "-a", NULL, NULL) == - )
{
perror("execle error ");
exit();
}
} /**
*创建子进程并调用execve
* v 希望接收到一个以NULL结尾的字符串数组的指针
* e 函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境
*/
if( fork() == )
{
printf("6------------execve-----------\n");
if( execve( "/bin/ls", arg, NULL ) == )
{
perror("execve error ");
exit();
}
}
return EXIT_SUCCESS;
}

  结果:

 ------------execl------------
. .. .deps exec exec.o .libs Makefile
------------execv------------
. .. .deps exec exec.o .libs Makefile
------------execlp------------
. .. .deps exec exec.o .libs Makefile
------------execvp------------
. .. .deps exec exec.o .libs Makefile
------------execle------------
. .. .deps .libs Makefile exec exec.o
------------execve-----------
. .. .deps .libs Makefile exec exec.o
按回车继续!

linux exec函数家族的更多相关文章

  1. Linux下多进程编程之exec函数语法及使用实例

    exec函数族 1)exec函数族说明 fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容,但是,这个新创建的进程如何执行呢?exec函数族就提供了一个在进程中启动另一个程序执行的 ...

  2. linux c语言 fork() 和 exec 函数的简介和用法

    linux c语言 fork() 和 exec 函数的简介和用法   假如我们在编写1个c程序时想调用1个shell脚本或者执行1段 bash shell命令, 应该如何实现呢? 其实在<std ...

  3. Linux exec族函数解析

    背景 在提到 vfork 函数时,我们提到了这个概念.为了更好地学习与运用,我们对exec族函数进行展开. exec函数族 介绍 有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中 ...

  4. 二十五、Linux 进程与信号---exec函数

    25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...

  5. linux fork函数与vfork函数,exit,_exit区别

    man vfork: NAME vfork - create a child process and block parent SYNOPSIS #include <sys/types.h> ...

  6. linux exec函数族

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

  7. fork和exec函数

    #include<unistd.h> pid_t fork(void); 返回:在子进程中为0,在父进程中为子进程IO,若出错则为- fork最困难之处在于调用它一次,它却返回两次.它在调 ...

  8. Linux exec与文件描述符

    看到好几篇文章讲述exec都是一知半解,所以我尽量说的清楚明白一些.本文首先讲述Linux文件描述符,然后是exec,最后举例说明exec I/O重定向及其用法. 概念:exec命令用于调用并执行指令 ...

  9. 实例分析exec函数

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

随机推荐

  1. How to Map Distinct Value Types Using Java Generics--reference

    原文:http://www.codeaffine.com/2015/03/04/map-distinct-value-types-using-java-generics/ Occasionally t ...

  2. Pitfalls of the Hibernate Second-Level / Query Caches--reference

    This post will go through how to setup the Hibernate Second-Level and Query caches, how they work an ...

  3. linux vi 撤销重做于前进后退--转

    在vi中按u可以撤销一次操作 u   撤销上一步的操作Ctrl+r 恢复上一步被撤销的操作 注意:如果你输入“u”两次,你的文本恢复原样,那应该是你的Vim被配置在Vi兼容模式了.重做如果你撤销得太多 ...

  4. Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件

    一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...

  5. swift和oc区别----属性部分(参考官方swift2.1文档)

    对于实用过OC的人来说实用swift上手时非常容易的,swift包括了oc的大部分功能,但是swift毕竟是一门新的编程语言,它和OC还是 有很多不同的地方,而且提供了不少新功能,所以本人在读swif ...

  6. swift项目中嵌入oc

    参考资料 需要注意的是  与oc包含swift不同的是  swift包含oc需要在桥接文件中包含要使用的oc的头文件 demo:swiftPlayOc(提取码:37c6)

  7. 关于git的基本命令

    git环境的搭建这里就先不说.本篇主要是普通开发工作者在开发过程中所使用的命令. 作为开发者,别人搭建git服务器之后,你呢就配置个人的客户端: 设置Git的配置变量,这个是一次性的工作.即这些设置会 ...

  8. [转载]删除所有的.svn文件夹

    Windows 下,在DOS窗口中运行如下命令 dos 代码 for /r <你项目的路径> %i in (.svn) do rd /s /q %i Linux 下,可以先运行 显示出当前 ...

  9. dagger和butterknife使用冲突

    两者会冲突的主要原因是因为两者都有:javax.annotation.processing.Processor 于是在build.gradle中添加如下配置即可: // 注释冲突 packagingO ...

  10. Effective C++ 沉思录

    1.视C++是一个联邦语言.由C,Object-Oriented C++,Templete C++,和STL组成.其中面对不同的语言,采用不同的规约这样编程效率会提高很多.例如C和STL 都是有C-S ...