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