引入

  创建子进程后,我们并不希望子进程执行父进程后续相同的内容,这时我们可以用exec函数族进行子进程的执行内容替换。

exec函数族

Linux下的exec函数族,是指6个以exec开头的函数。分别是

int execl(const char *path,const char *arg,...)
int execv(const char *path,char *cosnt arg[])
int execle(const char *path,const char *arg,...,char *const envp[])
int execve(const char *path,char *const argv[],char *const envp[])
int execlp(const char *file, const char *arg,...)
int execvp(const char *file, char *const argv[]);

复习:牢记const修饰的是谁?指针标记的优先级低于偏移符号[]。
const char *p:p是一个指针,指向常字符类型
char const *p:同上,const修饰的是*p
char * const p:p是一个常指针,指向字符类型。const修饰的是p
char *p[]:p是一个数组,其内容是字符指针
char (*p)[]:p是一个指针,指向的内容是字符数组(字符串)
char * const p[]:p是一个数组,数组的内容是常字符指针

我们介绍最常用的第一个程序:

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

执行原理

为什么说exec函数族可以使子进程执行不同的程序呢?
——“换核不换壳”:进程在调用exec函数时,进程用户空间的代码和数据空间的代码会完全被新的替代。也就是说原有的text和data会被替换掉,但是调用exec函数并不会产生新的进程,也不会改变PID。
  直白地讲,就是原有的箱子不变。但是调用exec函数后,其中原有的苹果被换成了梨。

使用场景

  1. 进程认为自己不能再为系统和用户作出任何贡献时,就可以调用任何exec函数族让自己重生
  2. 如果一个进程想要执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生。

我们依旧举一些例子:

//main.c文件
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>int main(void)
{   //int execl(const char *pathname, const char *arg, ...//                   /* (char  *) NULL */);//第一个参数是要执行的执行文件的路径(包含文件名),第二个是要执行文件的文件名//之后的变长参数就是要带的参数。最后要以(char *)NULL作为最后一个参数pid_t pid;pid=fork();if(pid<0){   printf("process create failed!");}   else if(pid == 0){   printf("This is child process!");printf("PID=%d parent PID=%d\n",getpid(),getppid());execl("/home/czc/Desktop/LinuxExp/process/subproc","subproc",(char *)NULL);exit(1);}   else{   printf("This is parent process!");printf("PID=%d Its child PID=%d\n",getpid(),pid);}printf("This is father process remaining part!\n");return 0;
}
//./subproc.c文件
#include<stdio.h>
int main(void)
{printf("enter a new subProcess!\n");return 0;
}

调用main.c编译的可执行文件结果如下:

可以发现,父进程剩下的部分,子进程并没有执行。子进程在调用exec函数族后,就只执行subproc.c编译出来的可执行文件了。这里使用exit(1)的目的只是在exec调用失败后,也主动结束子进程。

命令即可执行文件

  之前已经提到,Linux下的命令就是可执行文件。那么同样地,我们在调用exec函数族时不仅可以使用我们自己编写的可执行文件,也可以调用系统命令(也就是系统自带的可执行文件)。我们对上面的C源文件稍作修改:

//main.c文件
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>int main(void)
{   //int execl(const char *pathname, const char *arg, ...//                   /* (char  *) NULL */);//第一个参数是要执行的执行文件的路径(包含文件名),第二个是要执行文件的文件名//之后的变长参数就是要带的参数。最后要以(char *)NULL作为最后一个参数pid_t pid;pid=fork();if(pid<0){   printf("process create failed!");}   else if(pid == 0){   printf("This is child process!");printf("PID=%d parent PID=%d\n",getpid(),getppid());//ls命令在路径/bin/下execl("/bin/ls","ls","-al",(char *)NULL);exit(1);}   else{   printf("This is parent process!");printf("PID=%d Its child PID=%d\n",getpid(),pid);}printf("This is father process remaining part!\n");return 0;
}

Linux下的exec函数族相关推荐

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

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

  2. Linux下使用exec命令将文件与文件描述符关联

    在shell脚本下exec为系统自带的脚本命令,其作用是用来执行其他程序: 语法格式: exec (选项)(参数) 选项: -c:在当前环境下执行命令,即在当前shell脚本下执行,而不是打开一个新的 ...

  3. linux操作系统之exec函数族

    当我们想在进程中执行另外一个函数或程序时,可以使用exec函数.进程调用exec函数,则该进程中用户空间所有代码和数据会完全被新程序替换,但是不会创建新进程,因此进程id不会发生改变. 函数族的头文件 ...

  4. 小何讲进程:Linux中的exec函数族讲解

    1.  exec函数族-exec()函数族说明 使用exec函数族主要有两种情况 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec函数族中的任意一个函数让自己重生: 如果一个进程想执 ...

  5. 12.Linux:exec函数族

    (1)exec函数说明 fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法.它可以根据指定的 ...

  6. Linux多任务编程(三)---exec函数族及其基础实验

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

  7. exec函数族用法总结

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

  8. 【系统编程】进程--exec函数族(execl、execlp、execle、execv、execvp、execve)

    1.exec族函数说明 fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我的程序们希望子进程去执行另外,exec函数族就提供了一个在进程中启动另一个程序执行的方法.它可以根据指定的 ...

  9. Linux下进程的建立 并附Linux exec函数族

    我们都知道,进程就是正在执行的程序.而在Linux中,可以使用一个进程来创建另外一个进程.这样的话,Linux的进程的组织结构其实有点像Linux目录树,是个层次结构的,可以使用pstree命令来查看 ...

最新文章

  1. 2021年春季学期-信号与系统-第一次作业参考答案-第六题
  2. android子view获取父布局,Android获取布局父ID(Android get layout parent id)
  3. Spring依赖注入(DI)
  4. java反射重要么_JAVA反射----这些知识你需要知道
  5. 现代软件工程讲义 11 项目管理 - 事后诸葛亮会议
  6. hibernate 三种状态的转换
  7. 使用UIBinder的GWT自定义按钮
  8. Java和线性代数的关系_高等数学,线性代数与计算机的关系?
  9. pytorch: Tensor的创建与调整
  10. Jay Simons谈Atlassian收购Trello
  11. 最全Redis49个面试题目及答案:线程设计+哨兵+复制+事务+集群+持久化等
  12. java如何对一个表达式开根号_Java中,如何对大数开根号啊!
  13. 矩阵操作(转置、相加、相乘)
  14. 软考-架构师知识总结
  15. C++ 遇到reference to ' *** ' is ambiguous 错误
  16. python爬虫汽车之家全车型及基本参数入数据库(截止50524个数据)(详解)
  17. 【操作系统】第2章 进程与线程
  18. 2022广州大学计算机网络实验--Windows网络测试工具
  19. 教你十秒钟学会剪映抠绿幕
  20. 微电子电路——反相器网表详解

热门文章

  1. Solaris中vi的用法
  2. Ubuntu常用快捷键-快速打开关闭终端以及更多常用指令
  3. @AutoConfiguration注解详解
  4. 【ARC064-F】【XSY2575】Rotated Palindromes(DP)(字符串)
  5. 前端HTML CSS合并行、合并列
  6. ecu根据什么信号对点火提前角_点火提前角ECU根据()信号对点火提前角实 – 手机爱问...
  7. 查看windows操作系统的默认编码(字符集)-chcp
  8. 鳄鱼线在期货中用法_警察在监视您的电话吗? 问鳄鱼猎人
  9. 神经网络的深度、宽度和分辨率
  10. 五分钟的技巧让你避免糟糕的设计