00. 目录

文章目录

  • 00. 目录
  • 01. exec函数族
  • 02. 参考示例
    • 2.1 execl函数示例
    • 2.2 execv函数示例
    • 2.3 execlp() 或 execvp()函数示例
    • 2.4 execle() 或 execve()函数示例
  • 03. 附录

01. exec函数族

在 Windows 平台下,我们可以通过双击运行可执行程序,让这个可执行程序成为一个进程;而在 Linux 平台,我们可以通过 ./ 运行,让一个可执行程序成为一个进程。

但是,如果我们本来就运行着一个程序(进程),我们如何在这个进程内部启动一个外部程序,由内核将这个外部程序读入内存,使其执行起来成为一个进程呢?这里我们通过 exec 函数族实现。

exec 函数族,顾名思义,就是一簇函数,在 Linux 中,并不存在 exec() 函数,exec 指的是一组函数,一共有 6 个:

#include <unistd.h>extern char **environ;int execl(const char *path, const char *arg, .../* (char  *) NULL */);
int execlp(const char *file, const char *arg, .../* (char  *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

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

exec 函数族提供了六种在进程中启动另一个程序的方法。exec 函数族的作用是根据指定的文件名或目录名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。

进程调用一种 exec 函数时,该进程完全由新程序替换,而新程序则从其 main 函数开始执行。因为调用 exec 并不创建新进程,所以前后的进程 ID (当然还有父进程号、进程组号、当前工作目录……)并未改变。exec 只是用另一个新程序替换了当前进程的正文、数据、堆和栈段(进程替换)。

exec 函数族的 6 个函数看起来似乎很复杂,但实际上无论是作用还是用法都非常相似,只有很微小的差别。

l(list):参数地址列表,以空指针结尾。

v(vector):存有各参数地址的指针数组的地址。

p(path):按 PATH 环境变量指定的目录搜索可执行文件。

e(environment):存有环境变量字符串地址的指针数组的地址。

exec 函数族装入并运行可执行程序 path/file,并将参数 arg0 ( arg1, arg2, argv[], envp[] ) 传递给此程序。

exec 函数族与一般的函数不同,exec 函数族中的函数执行成功后不会返回,而且,exec 函数族下面的代码执行不到。只有调用失败了,它们才会返回 -1,失败后从原程序的调用点接着往下执行。

02. 参考示例

2.1 execl函数示例

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("before exec\n");/* /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意-a,-l,-h:给外部程序 ls 传的参数NULL:这个必须写上,代表给外部程序 ls 传参结束*/execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);// 如果 execl() 执行成功,下面执行不到,因为当前进程已经被执行的 ls 替换了perror("execl");printf("after exec\n");return 0;
}

执行结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
before exec总用量 23K
drwxrwxrwx 1 root root 4.0K 11月  5 15:38 .
drwxrwxrwx 1 root root 4.0K 11月  4 18:05 ..
-rwxrwxrwx 1 root root  576 11月  5 15:38 1.c
-rwxrwxrwx 1 root root  704 11月  5 13:42 1.c.bak
drwxrwxrwx 1 root root 4.0K 11月  3 20:46 4sys
-rwxrwxrwx 1 root root 8.2K 11月  5 15:38 a.out
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.2 execv函数示例

execv() 和 execl() 的用法基本是一样的,无非将列表传参,改为用指针数组。

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{// execv() 和 execl() 的用法基本是一样的,无非将列表传参,改为用指针数组// execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);/* 指针数组ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意-a,-l,-h:给外部程序 ls 传的参数NULL:这个必须写上,代表给外部程序 ls 传参结束*/char *arg[]={"ls", "-a", "-l", "-h", NULL};// /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)// arg: 上面定义的指针数组地址execv("/bin/ls", arg);perror("execv");return 0;
}

测试结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
总用量 23K
drwxrwxrwx 1 root root 4.0K 11月  5 15:40 .
drwxrwxrwx 1 root root 4.0K 11月  4 18:05 ..
-rwxrwxrwx 1 root root  643 11月  5 15:40 1.c
-rwxrwxrwx 1 root root  576 11月  5 15:38 1.c.bak
drwxrwxrwx 1 root root 4.0K 11月  3 20:46 4sys
-rwxrwxrwx 1 root root 8.2K 11月  5 15:40 a.out
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.3 execlp() 或 execvp()函数示例

execlp() 和 execl() 的区别在于,execlp() 指定的可执行程序可以不带路径名,如果不带路径名的话,会在环境变量 PATH指定的目录里寻找这个可执行程序,而 execl() 指定的可执行程序,必须带上路径名。

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{// 第一个参数 "ls",没有带路径名,在环境变量 PATH 里寻找这个可执行程序// 其它参数用法和 execl() 一样execlp("ls", "ls", "-a", "-l", "-h", NULL);/*char *arg[]={"ls", "-a", "-l", "-h", NULL};execvp("ls", arg);*/perror("execlp");return 0;
}

执行结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
总用量 22K
drwxrwxrwx 1 root root 4.0K 11月  5 15:42 .
drwxrwxrwx 1 root root 4.0K 11月  4 18:05 ..
-rwxrwxrwx 1 root root  354 11月  5 15:42 1.c
-rwxrwxrwx 1 root root  643 11月  5 15:40 1.c.bak
drwxrwxrwx 1 root root 4.0K 11月  3 20:46 4sys
-rwxrwxrwx 1 root root 8.2K 11月  5 15:42 a.out
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

2.4 execle() 或 execve()函数示例

execle() 和 execve() 改变的是 exec 启动的程序的环境变量(只会改变进程的环境变量,不会影响系统的环境变量),其他四个函数启动的程序则使用默认系统环境变量。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // getenv()int main(int argc, char *argv[])
{// getenv() 获取指定环境变量的值printf("before exec:USER=%s, HOME=%s\n", getenv("USER"), getenv("HOME"));// 指针数据char *env[]={"USER=TEST", "HOME=/tmp", NULL};/* ./test:外部程序,当前路径的 test 程序,通过 gcc test.c -o test 编译test:这里没有意义NULL:给 test 程序传参结束env:改变 test 程序的环境变量,正确来说,让 test 程序只保留 env 的环境变量*/execle("./test", "test", NULL, env);/*char *arg[]={"test", NULL};       execve("./test", arg, env);   */perror("execle");return 0;
}

外部程序,test.c 示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("\nin the test fun, after exec: \n");printf("USER=%s\n", getenv("USER"));printf("HOME=%s\n", getenv("HOME"));return 0;
}

03. 附录

3.1 参考博客:【Linux系统编程】进程替换:exec 函数族

【Linux系统编程】进程替换:exec 函数族相关推荐

  1. Linux系统编程——进程替换:exec 函数族

    在 Windows 平台下.我们能够通过双击运行可运行程序.让这个可运行程序成为一个进程:而在 Linux 平台.我们能够通过 ./ 运行,让一个可运行程序成为一个进程. 可是,假设我们本来就执行着一 ...

  2. Linux系统编程--3(exec 函数族,僵尸进程和孤儿进程,wait和wait_pid回收子进程)

    exec 函数族 fork 创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支) ,子进程往往要调用一种 exec 函数以执行另一个程序.当进程调用一种 exec 函数时,该进程的用户 ...

  3. Linux系统编程——进程基础知识

    Linux系统编程--进程基础知识 1.程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁-) 进程,是一个抽象的概念,与操作系统原理联系紧密.进程 ...

  4. Linux 系统编程 -进程概念篇

    Linux系统编程-进程篇 冯诺依曼体系结构 冯诺依曼的两个重要思想 当代计算机的三级缓存 操作系统 操作系统的概念 操作系统的组成 操作系统作用 Linux下的操作系统体系 进程 进程概念 进程特性 ...

  5. Linux系统编程——进程

    一.进程概念 基础 程序:死的.只占用磁盘空间. --剧本 进程:活的.运行起来的程序.占用内存,cpu等系统资源. --戏 并发 并发的出现基于CPU的发展.然后有了多道程序设计(多进程并发执行). ...

  6. execve系统调用_Linux系统编程——进程替换:exec 函数族

    在 Windows 平台下,我们可以通过双击运行可执行程序,让这个可执行程序成为一个进程:而在 Linux 平台,我们可以通过 ./ 运行,让一个可执行程序成为一个进程. 但是,如果我们本来就运行着一 ...

  7. Linux系统编程 进程控制

    文章目录 01. 学习目标 02. 进程和程序 (理解) 03. 单道.多道程序设计(了解) 3.1 单道程序设计 3.2 多道程序设计 04. 并行和并发(理解) 05. MMU(了解) 06. 进 ...

  8. Linux学习之系统编程篇:exec 函数族

    函数能力:"换核不换壳"(能够替换进程虚拟地址空间中.text 代码段). 作用:让父子进程执行不相干的操作. 效果:有一个运行的程序 A,在 A 中调用另一个程序 B,程序有父子 ...

  9. Linux系统编程-进程概念、进程管理、信号处理

    1. 进程知识点 操作系统里的进程是程序一次执行的过程,是操作系统动态执行的基本单元:每当创建新的进程后,操作系统会为新的进程分配一个唯一的标识符,方便后续管理进程. 进程的概念主要有两点: 第一,进 ...

  10. Linux系统编程—进程—system函数

    system函数 system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程.在调用sys ...

最新文章

  1. 对于装饰器Decorator的理解
  2. 104. Leetcode 337. 打家劫舍 III (动态规划-打家劫舍)
  3. python--pandas 分位数
  4. 微抖动,繁忙的等待和绑定CPU
  5. mysql xp系统时间_mysql时间类型year
  6. matlab 设计带阻型陷波滤波器_Q值可调、最大增益恒定的带通滤波器
  7. “数据资产化”线上论坛圆满结束!
  8. SpringCloud 从菜鸟到大牛之二 服务注册与发现 Sping Cloud Eureka
  9. cim系统 是什么_CIM和IBM i:它是什么以及它如何工作
  10. 婚姻中,不去表达爱,比不爱更可怕
  11. 360的困兽之斗——探讨奇虎Tecent商业模式
  12. php 计算壬子,壬子日是哪一天 壬子日怎么算
  13. 教你如何写原创歌词和卖你的原创歌曲
  14. 关于计算机学院的毕业论文致谢,计算机学院毕业生论文致谢范文
  15. Introduce Python to data sience/Python 在数据科学中的应用
  16. C++ MFC万能的类向导
  17. 互联网程序员行话(黑话)合集
  18. Java XML转换为JSON XML解析 转换为JSON Java 实现JSON转换为XML json转xml
  19. 基于SSM的仓库管理系统(含完整源码+论文)
  20. 计算机专业调研报告ppt,武侯区四年级调研报告 电脑基础知识 it计算机 专业资料.ppt...

热门文章

  1. oracle status
  2. SharePoint【调试,诊错系列】-- 开发环境中不同调试对象的Attach方式
  3. 咋样路linux分区,linux下磁盘分区方法详解
  4. python 自动化办公 uibot_使用 Python 扩展丰富 UiBot 的功能及在 UiBot 中引用 Python 模块...
  5. 布局技巧3:创建高效布局
  6. c++stl应用入门
  7. [转载]线上应用故障排查之一:高CPU占用
  8. windows下使用docker(一)—— 安装
  9. 【Linux】scp“免密” 远程copy较多文件
  10. (转)简单代码生成器原理剖析(二)