zoukankan      html  css  js  c++  java
  • Linux下使用exec族函数进行进程替换

    在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!
    ");
        }
    
        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!
    ");
        }
    
        return 0;
    }
    

    执行结果如下:

    成功执行了shell命令。

  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/zy666/p/10504278.html
Copyright © 2011-2022 走看看