linux系统编程-进程-exec族函数

exec族函数函数的作用:

     1.一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当这种请求到达的时候,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达。

      2.一个进程要执行一个不同的程序。这对shell是非常常见的情况。在这种情况下,子进程从fork返回后立即调用exec.

exec族函数包含以下:

#include <unistd.h>
extern char **environ;

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 execvpe(const char *file, char *const argv[],char *const envp[]);

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量
下面我们逐个介绍

1.execl:(l表示list),包括execl、execlp、execle,要求将新程序的每个命令行参数都说明为 一个单独的参数。这种参数表以空指针结尾。

函数原型:

int execl(const char *path, const char *arg, ...);
//文件echoarg.c
#include <stdio.h>

int main(int argc,char *argv[])
{
    int i = 0;
    for(i = 0; i < argc; i++)
    {
        printf("argv[%d]: %s\n",i,argv[i]); 
    }
    return 0;
}
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("./newpro","newpro","abc","efg",NULL) == -1)
    {
        printf("execl failed!\n");      
	perror("Fault:");
    }
    printf("after execl\n");
    return 0;
}

 

结果:

 

在调用execl()函数后,当前进程的映像会被新程序(newpro)的映像所替代,控制权会完全转移到新程序中。因此,如果execl()函数成功执行,它将不会返回,后续的代码也不会被执行。

只有当execl()函数调用失败时(返回值为-1),才会输出"execl failed!"这一行,并打印出具体的错误信息。

2.execlp:函数会根据环境变量PATH的设置来查找可执行文件的路径,而不需要指定完整的文件路径。

函数原型:

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

 执行ls-l指令:此时我们不需要输入绝对路径,它从PATH环境进行寻找可执行文件

//文件execlp.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execlp("ls","ls","-l",NULL) == -1)
    {
        printf("execl failed!\n");      
	perror("Fault:");
    }
    printf("after execl\n");
    return 0;
}

 执行结果:

 

3.execle:函数是exec函数族的另一个成员,用于执行另一个程序,并允许您指定新程序的环境变量。与execlp()函数不同的是,execle()函数可以显式地指定新程序的环境变量数组。

下面是execle()函数的函数原型:

int execle(const char *path, const char *arg,..., char * const envp[]);
//文件execle.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execle(const char *path, const char *arg,..., char * const envp[]);

char *env_init[] = {"AA=aa","BB=bb",NULL};
int main(void)
{
    printf("before execle****\n");
        if(execle("./echoenv","echoenv",NULL,env_init) == -1)
        {
                printf("execle failed!\n");
        }       
    printf("after execle*****\n");
    return 0;
}
  1 //文件echoenv.c
  2 #include <stdio.h>
  3 #include <unistd.h>
  4 extern char** environ;
  5 int main(int argc , char *argv[])
  6 {
  7     int i;
  8     char **ptr;
  9     for(int i =0;i<argc;i++){
 10         printf("canshu =%s\n",argv[i]);
 11 
 12         }
 13     for(ptr = environ;*ptr != 0; ptr++)
 14         printf("%s\n",*ptr);
 15     return 0;
 16 }
~        

 运行结果:

 

 

主程序部分调用了 execle 函数来执行 ./echoenv 可执行文件,同时传递了参数 echoenv 和自定义的环境变量 env_init

env_init 是一个字符串数组,其中每个字符串都表示一个环境变量。在这个例子中,定义了两个环境变量 "AA=aa""BB=bb",并通过最后一个元素为 NULL 来标记环境变量数组的结尾。

执行 execle 函数后,当前进程会被替换为 ./echoenv 的程序。在新程序中,通过访问全局变量 environ,可以获取到父进程传递过来的环境变量。然后新程序使用一个循环遍历输出所有的环境变量。

 

extern char** environ; 是一个声明语句,它声明了一个名为 environ 的全局变量,该变量是一个指向字符指针的指针。

在C语言中,extern 关键字用于声明一个全局变量或函数,表示该变量或函数是在其他文件中定义的。这样做可以在当前文件中引用其他文件中定义的全局变量或函数。

environ 是一个全局变量,它是一个指向字符串指针的指针数组。它包含了当前进程的环境变量。每个字符串指针都指向一个以 key=value 格式表示的环境变量。

通过声明 extern char** environ;,你可以在当前文件中引用 environ 变量,以访问和操作环境变量。例如,在你给出的代码中,通过遍历 environ 可以输出所有的环境变量。

需要注意的是,environ 变量通常是由操作系统在程序启动时设置的,并且它是一个只读变量。因此,你不能直接修改 environ 数组中的内容,但可以通过其他方式来操作环境变量,比如使用标准库中的函数来获取、设置或删除环境变量。

4.execv:是一个用于执行指定路径下可执行文件的函数。该函数会将当前进程替换为指定路径下的可执行文件,并传递给新程序一个参数列表。

int execv(const char *path, char *const argv[]);
  • path:表示要执行的可执行文件的路径名。
  • argv:参数列表,是一个字符串数组,其中每个元素都是一个参数。最后一个元素必须为 NULL,用于标记参数列表的结束
    //文件execv.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    //函数原型:int execl(const char *path, const char *arg, ...);
    
    int main(void)
    {
        char *argv[]={"ls",NULL,NULL};
        printf("before execl\n");
        if(execvp("/bin/ls",argv) == -1)
        {
            printf("execl failed!\n");      
    	perror("Fault:");
        }
        printf("after execl\n");
        return 0;
    }

运行结果: 

 

 5:execvp:是一个用于执行指定可执行文件的函数。与 execv 函数相比,execvp 函数的参数有所不同,但功能类似。execvp 函数会在系统的 PATH 环境变量指定的路径中搜索可执行文件。当调用execvp 函数时,系统将自动搜索可执行文件并执行它。新程序接收到的命令行参数将由 argv 提供。可以通过遍历 argv 数组来获取传递给新程序的参数。

int execvp(const char *file, char *const argv[]);
//文件execvp.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    char *argv[]={"ls","-l",NULL};
    printf("before execl\n");
    if(execvp("ls",argv) == -1)
    {
        printf("execl failed!\n");      
	perror("Fault:");
    }
    printf("after execl\n");
    return 0;
}

 运行结果:(实现ls-l)

 

 这个函数有兴趣的可以研究下,目前没用过

int execvpe(const char *file, char *const argv[],char *const envp[]);

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MichstaBe#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值