替换原理
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
int main()
{
printf("我是一个进程,我的pid=%d\n", getpid());
execl("/usr/bin/ls", "ls", NULL);
printf("我是一个进程,我的pid=%d\n", getpid());
return 0;
}
例如在这样的一个进程替换中,最后一行的printf不会执行
使用进程替换函数
以下几个为常用的进程替换函数
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
execl
int main()
{
printf("我是一个进程,我的pid=%d\n",getpid());
execl("/usr/bin/ls","ls","-l",NULL);
return 0;
}
execv
int main()
{
printf("我是一个进程,我的pid=%d\n", getpid());
char* const argy[] = { (char*)"ls",(char*)"-l",NULL };
execv("/usr/bin/ls",argy);
return 0;
}
execlp
int main()
{
printf("我是一个进程,我的pid=%d\n", getpid());
execlp("ls","ls", "-l",NULL);
return 0;
}
execvp
int main()
{
printf("我是一个进程,我的pid=%d\n", getpid());
char* const argy[] = { (char*)"ls",(char*)"-l",NULL };
execvp("ls", argy);
return 0;
}
Xshell的基本原理
Xshell在执行我们的命令时,会将我们的命令进行解析,在创建一个子进程(fork),再进行子进程的替换(execvp),父进程等待子进程的退出(wait)
简易Xshell
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#define Max_Num 1024
#define Max_Size 128
char line_command[Max_Num] = "\0";
char* command_args[Max_Size];
int main()
{
while (1)
{
//打印提示符
printf("[zjq@主机 当前目录#]");
fflush(stdout);
//获取用户输入
//
memset(line_command, 0, Max_Num * sizeof(char));
fgets(line_command, Max_Num, stdin);
line_command[strlen(line_command) - 1] = 0;
printf("%s", line_command);
fflush(stdout);
int index = 0;
command_args[index++] = strtok(line_command, " ");
while (command_args[index++] = strtok(NULL, " "));
//创建新进程
pid_t id = fork();
//子进程
if (id == 0)
{
execvp(command_args[0], command_args);
}
else
{
int ret = waitpid(id, NULL, 0);
printf("等待成功\n");
}
}
return 0;
}