Linux学习笔记14 ——execl

1,原型

前面我们提到,可以用fork创建一个子进程。但是,这个子进程与原先的父进程共享程序段。也就是说两个进程执行的是同一段代码。这好像并没有太大的用处。正常来说,我们希望的不是创建的新进程可以执行完全不同的功能吗?这要怎么做呢?

这就要用到我们今天讲的exec系列函数。

通常的做法是,先用fork起一个子进程,再调用execXXX函数将子进程替换成一个指定的程序。这样狸猫换太子之后,新的程序就获得了原先子进程的pid和父进程。完全顶包了原先的子进程。

exec系列共有7个函数。今天的例子以最简单的execl为例子。7个函数的原型如下:

#include<unistd.h>
int execl(const char* pathname, const char* arg0, ...); //arg以空指针结尾
int execv(const char* pathname, char* const argv[]);
int execle(const char* pathname,const char* arg0, ...);//arg以空指针结尾,再接环境变量
int execve(const char* pathname, char* const argv[], char* const envp[]);
int execlp(const char* filename, const char* arg0, ...); //arg以空指针结尾
int execvp(const char* filename, char* const argv[]);
int fexecve(int fd, char* const argv[], char* const envp[]);

返回值:出错返回-1,成功不返回。

2,例子:

2.1 hello程序

先装备好一个简单的hello程序做狸猫,便于待会被exec用来换太子。

先新建一个hello.c:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
    printf("Hello");
    if (argc > 0){
        printf(", %s!\n", argv[0]);
    } else {
        printf("\n");
    }
}

它只是简单滴打印第一个输入参数,并在前面加上一个hello而已。

将其编译成hello,就放在当前目录下。

 

2.2 入正题

有了狸猫,开始准备太子。在study_Linux.c下写入以下代码。

int main(){
    pid_t pid;
    //用fork产生一个与自己一模一样的子进程
    if((pid = fork()) < 0) {
        printf("fork error!\n");
		exit(1); 
    } else if(pid == 0){ //注意,是在子进程内调用execl
        //将子进程替换成hello,并给hello传递输入参数Bihan,注意最后一个输入参数一定是NULL
        if(execl("./hello", "Bihan", NULL) < 0){
            printf("execle error!\n");
		    exit(1); 
        }
    } 
    
    printf("parent process\n");
    //这里waitpid还能等到hello,说明hello的pid就是原先子进程的pid,
    //父进程就把hello当自己的子进程,狸猫换太子成功
    if(waitpid(pid, NULL, 0) < 0){
        printf("wait error!\n");
		exit(1); 
    }else{
        printf("wait end\n");
    }

    return 0;
}

执行结果:

➜  code ./study_linux                                       
parent process
Hello, Bihan!
wait end
 

可以看到hello被执行,输入参数也被传递,最后hello终止时父进程还能wait到。

注意一个细节。通常,当我们在命令行里调用hello的时候,比如这样:

➜  code ./hello Bihan
则hello的main函数的argv[0]并不是Bihan,而是“./hello”,当前程序名。所以刚才的执行效果是这样的:

➜  code ./hello Bihan
Hello, ./hello!
 

而我们在exec中指定hello的输入参数时,argv[0]就是“Bihan”,没有当前程序名自动成为argv[0]这一说法了。

3,7个exec之间的关系

注意:只有execve是系统调用,其他的只是库函数。其他6个最终也是通过调用execve实现的。

这组函数的名字是有规律的:

  1. 除了最后一个,其他都以exec开头;
  2. l代表list,表示狸猫的输入参数要一个一个列出来;与之相对,v代表vector,表示狸猫的输入参数是个数组;
  3. e代表environment,环境 变量,表示重新设定狸猫的环境变量而不使用当前的环境变量;
  4. p代表exec的第一个输入参数不是路径而是文件名,其会在环境变量path的指定下去寻找该文件名的文件,p代表path;
  5. 最后一个的f代表文件描述符。所以总结起来指定狸猫有文件名、路径名、文件描述符三种方法。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值