2016-07-17 15:23:21 hello_bravo_ 阅读数 12249

     exec函数有六个但是实际上掌握好一个自己熟悉的就好了,因为他们作用都是一样的,我在这里最喜欢用的是execv,所以就只讨论这个函数的用法。

     期间代码要和fork交相使用,fork有两个返回值,父进程返回子进程的pid,子进程返回0,因为子进程可以用getppid()知道父进程的pid(父进程唯一是这个理论的支持),而父进程可以拥有多个子进程,所以无法用函数去单纯获得子进程pid。

      函数原型

      #include <unistd.h>

      int exevc(const char *pathname,char *const argv[]);

      关于argv里面的参数,之前我一直有所疑惑,先用一个简单的代码看看如果这样写里面会有什么::

#include <unistd.h>

#include <stdio.h>

int main(int argc,char* argv[])
{
  printf("argv[0]::%s\n",argv[0]);
  printf("argv[1]::%s\n",argv[1]);
  printf("argv[2]::%s\n",argv[2]);
  execv("/bin/ls",argv);
  return 0;
}


      运行结果和使用方法::

截图有点不清晰但是不影响观看,可以看出argv的结尾一定是空指针,而里面存放的就是命令要调用的参数。


以下是我对第二个参数进行的测试:

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


int main(int argc,char* argv[])
{
  char *my[3] = {0};
  my[0] = "nihao";
  my[1] = "-l";
  //my[2]空指针
  execv("/bin/ls",my);
  return 0;
}

运行结果:


可见运行结果并没有受到影响,所以可以得出结论


关于execv的第二个参数数组,他的第一个位置存放的东西对于程序没有影响(但是应该存应用程序名字本身,可是我发现里面不管放什么都不影响程序结果所以得出这个结论,因为我不知道它放程序名字的意义何在),但是第二个及第二个以后存放的就是她应该使用的参数,最终结尾是空指针。




2017-04-13 22:56:00 jiaxinhong 阅读数 1687

在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序。exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,execlp,execv,execvp)都是调用execve的库函数。

#include<unistd.h>

函数定义 int execve(const char *filename, char *const argv[ ], char *const envp[ ]);

返回值 函数执行成功时没有返回值,执行失败时的返回值为-1.

函数说明 execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。

 

  1. #include<unistd.h>   
  2. main()   
  3. {   
  4.   char *argv[ ]={"ls", "-al", "/etc/passwd", NULL};   
  5.   char *envp[ ]={"PATH=/bin", NULL}   
  6.   execve("/bin/ls", argv, envp);   
  7. }  

运行结果为:-rw-r--r-- 1 root root 1659 Feb 27 20:13 /etc/passwd

这与在bin目录下执行 ls -al /etc/passwd 所得到的结果是一样的。

 

 

linux fork()和execve()的区别

fork是分身,execve是变身。

 exec系列的系统调用是把当前程序替换成要执行的程序,而fork用来产生一个和当前进程一样的进程(虽然通常执行不同的代码流)。通常运行另一个程序,而同时保留原程序运行的方法是,fork+exec。

看看手册里面的例子就知道怎么用了。

exec系列的系统调用已经是变成别的程序了,已经和本程序无关了

2020-03-18 23:13:51 qq_44226094 阅读数 22

进程的替换

exec 函数族, 是由六个 exec 函数组成的
        exec 函数族提供: 六种在进程中启动另一个程序的方法
        exec 函数族可根据 指定的文件名或目录名找到 可执行文件
        调用 exec 函数的进程并不创建新的进程, 故调用 exec 前后, 进程的进程号并不会改变, 其执行的程序完全由新的程序替换, 而新程序则从其 main 函数开始执行
     exec 函数族取代调用进程的数据段、 代码段和堆栈段

exec 函数族
 

#include <unistd.h>

int execl(const char *pathname,
          const char *arg0,...
          NULL);

int execlp(const char *filename,
           const char *arg0,...
           NULL);

int execle(const char *pathname,
           const char *arg0,..
           NULL,
           char *const envp[]);

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

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

     六个 exec 函数中只有 execve 是真正意义的系统调用(内核提供的接口), 其它函数都是在此基础上经过封装的库函数
  l(list):
          参数地址列表, 以空指针结尾。
     参数地址列表:
          char *arg0, char *arg1, ..., char *argn, NULL

v(vector):
         存有各参数地址的指针数组的地址
        使用时,先构造一个指针数组, 指针数组存各参数的地址, 然后将该指针数组地址作为函数的参数
p(path): 
       按 PATH 环境变量指定的目录搜索可执行文件
       以 p 结尾的 exec 函数取文件名做为参数

       当指定 filename 作为参数时, 若 filename 中包含/, 则将其视为路径名, 并直接到指定的路径中执行程序
e(environment):
      存有环境变量字符串地址的指针数组的地址

      execle 和 execve 改变的是 exec 启动的程序的环境变量( 新的环境变量完全由 environment 指定), 其他四个函数启动的程序则使用默认系统环境变量
注意:
       exec 函数族与一般的函数不同, exec 函数族中的函数执行成功后不会返回

       只有调用失败了, 它们才会返回- 1

      失败后从原程序的调用点接着往下执行

       在平时的编程中, 如果用到了 exec 函数族, 一定要记得加错误判断语句


getenv函数:

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

int main(int argc, char *argv[])
{
    printf("USER = %s\n",getenv("USER"));
    printf("GONGSI = %s\n",getenv("GONGSI"));
    return 0;
}

打印: 

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

int main(int argc, char *argv[])
{
    execl("/bin/ls","ls","-a","-l","-h",NULL);
        perror("execl");
    return 0;
}

打印:

 execlp函数:

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

int main(int argc, char *argv[])
{
    execlp("ls","ls","-a","-l","-h",NULL);
        perror("execlp");
    return 0;
}

打印:

 execv函数

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

int main(int argc, char *argv[])
{
    char *arg[] = {"ls", "-a", "-l", "-h", NULL};

    execv("/bin/ls",arg);
        perror("execv");
    return 0;
}

打印:

execvp函数: 

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

int main(int argc, char *argv[])
{
    char *arg[] = {"ls","-a","-l","-h",NULL};

    execvp("ls",arg);
        perror("execvp");
    return 0;
}

 打印:

execve函数:

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

int main(int argc, char *argv[])
{
    char *arg[]={"test", NULL};
    char *env[]={"USER=ME", "GONGSI=AIPU", NULL};

    execve("./test", arg, env);
        perror("execve");

    return 0;
}

一个进程调用 exec 后, 除了进程 ID, 进程还保留了下列特征不变:
        父进程号 , 进程组号 , 控制终端 , 根目录 , 当前工作目录 , 进程信号屏蔽集 , 未处理信号

 

Linux exec函数

阅读数 4585

Linux getpid函数

阅读数 581

没有更多推荐了,返回首页