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