本文介绍: ececl,execlp,execle,execv,execvp //库函数execve //系统调用//pathname:新替换程序路径+名字//arg :传给新程序主函数的第一个参数,一般为程序的名字//arg 后面是剩余参数列表参数个数可变,必须以空指针作为最后一个参数//系统调用//前五个是库函数,最后一个系统调用,所以本质上上面5个都是通过第六个系统调用实现的也就是说,上面5个都是调用execve,不过都是。

内核设计实现43页;

执行了3次ps -f ,ps -f的父进程的ID(PPID)都是一样的,即bash.

实际上Linux上这个bash就是不断的复制自身,然后复制出来的用exec替换成想要执行的程序(比如ps);

运行ps,发现psbash一个进程;原因就是bash把自己复制一份,然后替换ps;

#include <stdio.h>
#include <stdlib.h&gt;
#include <unistd.h&gt;
int main()
{
   printf(“main pid=%dn”,getpid());
   execl(“/usr/bin/ps“,”ps“,”-f”,(char *)0);
   exit(0);
}

execl(“/usr/bin/ps“,”abc“,”-f”,(char *)0);

execl(“/usr/bin/abc“,”ps“,”-f”,(char *)0);

printf(“exec  error!n”);

execlp(“ps“,”ps”,”-f”,(char *)0);

//int main(int argc,char *argv[],char *envp[])
execle(“/usr/bin/ps”,”ps”,”-f”,(char *)0,envp);

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={“ps”,”-f”,0};
execv(“/usr/bin/ps”,myargv);

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={“ps”,”-f”,0};
execvp(“ps”,myargv);

int execve(const char * path, char* const argv[],char* const envp[]); //系统调用

//int main(int argc,char *argv[],char *envp[])

char *myargv[]={“ps”,”-f”,0};
execve(“/usr/bin/ps”,myargv,envp);

//pathname:新替换的程序的路径+名字
//arg :传给新程序主函数的第一个参数,一般为程序的名字
//arg 后面是剩余参数列表,参数个数可变,必须以空指针作为最后一个参数
int execl(const char* pathname, const char * arg,…);
int execlp(const char* file, const char * arg,…);
int execle(const char* pathname, const char * arg,…,char* const envp[]);
int execv(const char * pathname, char* const argv[]);
int execvp(const char * file, char* const argv[]);
int execve(const char * pathname, char* const argv[],char* const envp[]); //系统调用

//前五个是库函数,最后一个是系统调用,所以本质上上面5个都是通过第六个系统调用实现

助记:
l(list)     参数地址列表,以空指针结尾
v(vector)   存放各个参数地址指针数组地址
p(path)   按PATH环境变量指定目录搜索可执行文件
e(enviroment)  存放环境变量字符地址指针数组地址

4.环境变量可以自己添加

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <assert.h>
int main()
{
   //存放传给新程序主函数的参数
   char * myargv[]={“ps”,”-f”,(char *)0};
   //存放传给新程序主函数的环境变量
   char *myenvp[]={“MYSTR=hello“,”VAL=100”,(char *)0};
   printf(“main pid=%dn”,getpid());
   //excel执行成功不返回,失败返回错误
   execve(“/bin/ps”,myargv,myenvp);
   perror(“execve errorn”);
   exit(0);
}

//test.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 
int main(int argc,char *argv[])
 {
 printf(“test start and test_pid=%dn”,getpid());

 int i=0;
 for(;i<argc;i++)
 {
 printf(“argv[%d]=%sn”,i,argv[i]);
 }

 printf(“test endn”);
 exit(0);
 }

//main.c
#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int main(int argc,char *argv[],char *envp[])
 {
    printf(“main start and mainpid=%dn”,getpid());

    execl(“./test“,”./test“,”a”,”b“,”c”,(char *)0);
    perror(“execl error”);执行结果如下: 

    printf(“main endn”);//执行了之后替换了程序,这一句不会被执行到;
    exit(0);
 }

 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<assert.h>
 #include<wait.h>

int main()
{
    printf(“main pid=%d,ppid=%dn”,getpid(),getppid());
    pid_t pid=fork();
    assert(pid!=-1);

   if(pid==0)
   {
     printf(“child pid=%d,ppid=%dn”,getpid(),getppid());
    // execl(“/bin/ps”,”-f”,(char *)0);//省略了ps也对,但是最好写成上面的;
    execl(“/usr/bin/ps”,”ps”,”-f”,NULL);
    printf(“execl error”);
    exit(0);
   }

   wait(NULL);

   exit(0);
 }

    printf(“child end!n”);

//main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <wait.h>
int main(int argc,char *argv[],char *envp[])
{
    printf(“main pid=%dn”,getpid());
    pid_t pid=fork();
    assert(pid!=-1);
    if(pid==0)
   {
         char *myargv[]={“newmain”,”hello“,”abc“,”123”,(char *)0};
         //char *myenvp[]={“MYSTR=hello“,”VAL=100”,(char *)0};
         execve(“./newmain”,myargv,envp);
         perror(“execl error”);
         exit(0);
   } 
    wait(NULL);
    printf(“main overn”);
    exit(0);

//newmain.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc,char *argv[],char *envp[])
{
    printf(“newmain pid=%dn”,getpid());
    int i=0;
    printf(“argc=%dn”,argc);
    
    for(;i<argc;i++)
    {
      printf(“argv[%d]=%sn”,i,argv[i]);
    }
    for(i=0;envp[i]!=NULL;i++)
   {
        printf(“envp[%d]=%sn”,i,envp[i]);
   } 
    exit(0);
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注