进程控制2 进程程序替换

1.为啥需要进程程序替换

因为父进程创建出来的子进程和父进程拥有相同的代码段,所以,子进程的代码和父进程是一样的。当我们想要让子进程执行不同的程序时候,就需要让子进程调用进程程序替换的接口,从而让子进程执行不一样的代码。

2.原理:替换进程的数据段和代码段,更新堆栈。

3.exec函数簇

3.1 execl函数

int execl(const char* path,const char* argv, ...);

参数:

path:带路径的可执行程序。

arg:传递给可执行程序的命令行参数,(...表示可变参数列表),第一个参数是可执行程序本身,如果需要传递多个参数,则用“,”进行间隔,末尾以NULL结尾。

返回值:

函数如果调用成功,则加载新的程序从启动代码开始执行,不在返回;如果调用出错则返回-1

调用成功:

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   execl("/usr/bin/pwd","pwd",NULL);
   printf("if run here,the execl failed\n");
   return 0;
}

 调用失败:

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   execl("pwd","pwd",NULL);
   printf("if run here,the execl failed\n");
   return 0;
}

扫描二维码关注公众号,回复: 14467495 查看本文章

3.2 execlp函数

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

参数:

file:可执行程序,可以不用带有路径,也可以带有路径。

arg:传递给可执行的程序的命令行参数,第一个参数,需要可执行程序本身,如果需要传递多个参数,则用“,”进行间隔,末尾以NULL结尾。

返回值:函数如果调用成功则加载新的程序从启动代码开始执行,如果调用出错则返回-1。

>1file参数不带路径

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   execl("pwd","pwd",NULL);
   printf("if run here,the execl failed\n");
   return 0;
}

>2 file参数带路径

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   execl("/usr/bin/pwd","pwd",NULL);
   printf("if run here,the execl failed\n");
   return 0;
}

为什么execlp,第一个参数不用带有路径呢?

 原因就是:execlp这个函数会去搜索PATH这个环境变量,看看要替换的可执行程序是否在PATH环境变量对应的路径下能不能找到。能找到:正常替换,执行替换的程序。没找到:报错返回,替换失败了。

环境变量PATH里有/usr/bin这个路径

可执行程序不存在:

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   int ret=execlp("abcde","pwd",NULL);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

总结:

函数名当中带有" ”︰传递给可执行程序的参数是以可变参数列表的方式进行传递。第一个参数,需要可执行程序本身,如果需要传递多个参数,则用“,”进行间隔,末尾以NULL结尾。

函数名当中带有“ ”:可以使用环境变量PATH,无需写全路径。换句话说,函数会搜索环境变量PATH,找到可执行程序,所以不用写路径。

3.3 execle

int execle(const char *path, const char *arg,.. .,char *const envp[ ]);

参数:

path:带路径的可执行程序(需要路径)

arg:传递给可执行的程序的命令行参数,第一个参数需要可执行程序本身,如果需要传递多个参数,则用“,”进行间隔,末尾以NULL结尾。

envp :程序员传递环境变量,换句话说,程序员调用该函数的时候,需要自己组织环境变量传递给函数。

返回值:

函数如果调用成功则加载新的程序从启动代码开始执行,如果调用出错则返回-1。

总结:

函数名当中带有“e”:程序员传递环境变量,换句话说,程序员调用该函数的时候,需要自己组织环境变量传递给函数。

#include <stdio.h>
#include <stdlib.h>

int main(){
    printf("%s:%d\n",__FILE__,__LINE__);
    printf("%s\n",getenv("PATH"));
    return 0;
}
#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   extern char** environ;
   int ret=execle("/home/sy/work/usually/test","test",NULL,environ);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

 参数environ没有被设置

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   extern char** environ;
   int ret=execle("/home/sy/work/usually/test","test",NULL,NULL);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

3.4 execv函数

int execv(const char *path,char *onst argv[ ]);

参数:

path:带路径的可执行程序(需要路径)

argv :传递给可执行的程序能命令行参数,以指针数组的方式进行传递。第一个参数,需要可执行程序本身,多个参数就都放到数组当中!末尾以NULL结尾。

返回值:

函数如果调用成功则加载新的程序从启动代码开始执行,如果调用出错则返回-1。

总结:

函数名字当中带有“v”:说明命令行参数是以字符指针数组的方式进行传递的,字符指针数组需要程序员自己进行定义。

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   char* argv[10]={NULL};
   argv[0]="ls";
   argv[0]="-a";
   argv[0]="-l";
   argv[1]=NULL;
   int ret=execv("/usr/bin/ls",argv);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

3.5 execvp函数

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

参数:

file:可执行程序,可以不用带有路径,也可以带有路径。

argv :传递给可执行的程序的命令行参数,以指针数组的方式进行传递。第一个参数,需要可执行程序本身,多个参数就都放到数组当中末尾以NULL结尾。

返回值:

函数如果调用成功则加载新的程序从启动代码开始执行,如果调用出错则返回-1。

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   char* argv[10]={NULL};
   argv[0]="ls";
   argv[0]="-a";
   argv[0]="-l";
   argv[1]=NULL;
   int ret=execvp("ls",argv);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

 3.6 execve函数

int execve(const char *path, char *const argv[ ], char *const envp[ ]);

参数:

path:带路径的可执行程序(需要路径)。

argv :传递给可执行的程序的命令行参数,以指针数组的方式进行传递。第一个参数,需要可执行程序本身,多个参数就都放到数组当中,末尾以NULL结尾。

envp :程序员传递环境变量,换句话说,程序员调用该函数的时候,需要自己组织环境变量传递给函数。

返回值:函数如果调用成功则加载新的程序从启动代码开始执行,如果调用出错则返回-1。

#include <stdio.h>
#include <unistd.h>

int main(){
   printf("in the main,proecss begin...\n");
   char* argv[10]={NULL};
   argv[0]="ls";
   argv[0]="-a";
   argv[0]="-l";
   argv[1]=NULL;
   extern char** environ;
   int ret=execve("/usr/bin/ls",argv,environ);
   printf("if run here,the execl failed,%d\n",ret);
   return 0;
}

 3.7 这些函数原型看起来很容易混,但只要掌握了规律就很好记。

l(list) : 表示参数采用列表
v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
e(env) : 表示自己维护环境变量

 

3.8进程程序替换+fork+进程等待

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){
   pid_t pid=fork();
       if(pid<0){
          printf("process creat failed\n");
       }
       else if(pid == 0){
           //child
           printf("i am child,exec beginning\n");
           execl("/usr/bin/ls","ls","-a","-l",NULL);
           printf("if run here,failed\n");
       }
       else{
           //father
           printf("i am father,waiting...\n");
           wait(NULL);
           
       }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/sy2453/article/details/123401379