首页 > 代码库 > Linux系统编程_9_进程控制之exec 函数

Linux系统编程_9_进程控制之exec 函数

exec函数

当进程调用exec函数时,该进程的执行程序完全的替换为新程序。新程序从它的main函数开始执行;

使用fork函数创建一个子进程后,子进程往往会使用exec函数去执行另一个程序。

注意:调用exec函数并不会创建新进程,所以创建前后的进程ID不会改变,exec只是用一个全新的程序替换了当前正在运行的程序的代码段、数据段、堆、栈。

  #include <unistd.h>

       extern char **environ;
       int execl(const char *path, const char *arg, ...);
       int execv(const char *path, char *const argv[]);       

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

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

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

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

这么多函数如何记忆?

  带有字母p的,代表第一个参数是filename,并根据PATH环境变量搜索可执行文件;

  带有字母l的,代表函数取一个参数表;(与字母v互斥;希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志)

  带有字母v的,代表函数取一个argv[]; (希望接收到一个以NULL结尾的字符串数组的指针)

  带有字母e的,代表函数取一个envp[]数组;(函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境)


下面是例子:

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

int main()
{
    pid_t pid;
    int status;
    char *arg[] = {"ps" "-l", NULL};

    // execl
    pid = fork();
    if(-1 == pid)
    {
        printf("Fork error!\n");
        return -1;
    }
    else if(0 == pid)
    {
        if(-1 == execl("/bin/ls", "ls", "-a", NULL))
        {
            perror("execl error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execv
    if(0 == (pid=fork()))
    {
        if(-1 == execv("/bin/ps", arg))
        {
            perror("execv error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execle
    if(0 == (pid=fork()))
    {
        if(-1 == execle("/bin/ps", "ps", "-l", NULL, NULL))
        {
            perror("execle error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execve
    if(0 == (pid=fork()))
    {
        if(-1 == execve("/bin/ps", arg, NULL))
        {
            perror("execve error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    // execlp
    if(0 == (pid=fork()))
    {
        if(-1 == execlp("ps", "ps", "-l", NULL))
        {
            perror("execle error!");
            exit(-1);
        }
    }
    waitpid(pid, &status, 0);

    return 0;
}

运行结果:

.  ..  echo.sh  main
  PID TTY          TIME CMD
11120 pts/1    00:00:01 bash
20964 pts/1    00:00:00 main
20966 pts/1    00:00:00 ps
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   506 11120 11119  0  80   0 -  1745 -      pts/1    00:00:01 bash
0 S   506 20964 11120  0  80   0 -   459 -      pts/1    00:00:00 main
0 R   506 20967 20964  0  80   0 -   694 -      pts/1    00:00:00 ps
  PID TTY          TIME CMD
11120 pts/1    00:00:01 bash
20964 pts/1    00:00:00 main
20968 pts/1    00:00:00 ps
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   506 11120 11119  0  80   0 -  1745 -      pts/1    00:00:01 bash
0 S   506 20964 11120  0  80   0 -   459 -      pts/1    00:00:00 main
0 R   506 20969 20964  3  80   0 -  1618 -      pts/1    00:00:00 ps


Linux系统编程_9_进程控制之exec 函数