专栏首页程序员Linux下使用exec族函数进行进程替换

Linux下使用exec族函数进行进程替换

版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.net/zy010101/article/details/83692324

在Linux下使用fork或者vfork函数创建的子进程是完全复制父进程的代码来执行的。虽然我们可以使用fork函数返回值的不同来使得父进程和子进程执行的代码不同。但是有时候父进程是一段c程序,子进程却是个shell。这个时候,fork就没法解决这个问题。因此exec函数是必须的。

exec函数族共包括6个函数,函数形式如下:

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[]);

注意:只有execve函数是系统调用,其余的5个都是在execve基础上封装而来的库函数。

函数参数的意义:

path:指定要执行的程序的名称和路径

file:指定要执行的程序的名称,可以不指定路径,但是必须配置环境变量PATH。

arg...:以逐个列举的方式表示要执行的程序的格式:例如准备执行“创建子进程”这个程序,那么应该传递参数为:“./创建子程序”, NULL.

argv[]:以指针数组的形式表示要执行的程序的格式。

envp[]:环境变量参数。

当一个程序中使用exec函数来调用了另外的可执行文件后,那么该进程中所有的资源完全由新进程替换。所以使用的时候应当注意,如果还想回到原来的进程继续执行,那么需要先使用fork函数来创建一个进程,在这个进程中使用exec函数来完成进程替换。这样才能保证原进程能在exec调用后不被破坏。

exec函数调用后虽然替换了进程,但是却保留PID。来段代码跑一跑

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    pid_t pid;
    pid = fork();
    if(0 == pid)
    {
        execl("./创建子进程","创建子进程",NULL);
    }
    if(0 < pid)
    {
        sleep(2);
        printf("I am father!\n");
    }

    return 0;
}

运行结果如下:

代码里的创建子进程是上一篇博客提到的代码,在这里

使用fork,而不是vfork的原因是vfork会于原进程共享地址空间,fork则是复制原进程,从而创建一个原进程的副本。vfork则在exec函数调用之前的这段时间是和父进程共享数据的,直到遇到exec函数(或者是exit函数),才会成为一个独立进程,拥有自己的地址空间。不再和父进程共享地址空间。因此使用fork可以避免很多错误。

但是使用fork的的缺点是必须无法确定执行顺序,在这里我让父进程挂起2秒,从而使得子进程先于父进程执行。另外使用exec函数也可以完成shell命令。例如下面的代码。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    pid_t pid;
    pid = fork();

    if(0 == pid)
    {
        execl("/bin/pwd","pwd",NULL);
    }
    if(0 < pid)
    {
        sleep(1);
        printf("I am father process!\n");
    }

    return 0;
}

执行结果如下:

成功执行了shell命令。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • VHDL硬件描述语言(一)——基本结构

    实体的作用是给出实际电路的外部视图(引脚的数目,引脚的作用等),它描述了电路的封装结构。一般一个实体的结构大致如下所示:

    zy010101
  • 结构体的大小与内存对其

    最近在群里看到了有人问起结构体的大小问题,好多人的都不太明白。因此写篇文章总结一下。顺便再提一下结构体本身。

    zy010101
  • HTTP协议

    版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.ne...

    zy010101
  • 栈与堆的区别及其探讨

    一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据...

    阳光岛主
  • Stack and Heap 堆和栈的区别include

    在和计算机内存打交道时,我们一定会碰到堆和栈,这两个东西很容易搞混,那么现在就来梳理一下二者的关系。 栈(Stack)是用来静态分配内存的而堆是动态分配内存的,...

    Albert陈凯
  • exec族

    这个一直没搞太明白,相识度高是一回事,不会用又是另一回事儿。 所以今天又温故了一遍:

    看、未来
  • 3.2 VR扫描:Oculus Rift市场占有率2月首超HTC Vive;Twitter前CEO或将加入苹果AR团队

    VRPinea
  • java练习本(2019-08-14)

    “Those that go searching for love, only manifest their own lovelessness. And the...

    微笑的小小刀
  • 快速上手三大基础 React Hooks

    Hooks 出了有段时间了,不知盆友们有在项目中开始使用了吗❓如果还没了解的童鞋,可以瞧瞧这篇文章,对比看下三大基础 Hooks 和传统 class 组件的区别...

    JS菌
  • 3.21 VR扫描:联想VR一体机将于5月5日登陆美国;天奥科技完成数百万元A轮融资

    VRPinea

扫码关注云+社区

领取腾讯云代金券