顾得泉:个人主页
个人专栏:《Linux操作系统》??《C/C++》??《LeedCode刷题》
键盘敲烂,年薪百万!
?
#include <unistd.h>`
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[]);
int execve(const char *path, char *const argv[], char *const envp[]);
???????这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
???????如果调用出错则返回-1;
???????所以exec函数只有出错的返回值而没有成功的返回值。
????这些函数原型看起来很容易混,但只要掌握了规律就很好记:
? ? ? ? ?l(list):表示参数采用列表
? ? ? ? v(vector):参数用数组
? ? ? ? p(path):有p自动搜索环境变量PATH
? ? ? ? e(env):表示自己维护环境变量
#include <unistd.h>
int main()
{
char *const argv[] = {"ps", "-ef", NULL};
char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-ef", NULL);
// 带p的,可以使用环境变量PATH,无需写全路径
execlp("ps", "ps", "-ef", NULL);
// 带e的,需要自己组装环境变量
execle("ps", "ps", "-ef", NULL, envp);
execv("/bin/ps", argv);
// 带p的,可以使用环境变量PATH,无需写全路径
execvp("ps", argv);
// 带e的,需要自己组装环境变量
execve("/bin/ps", argv, envp);
exit(0);
}
下图exec函数族一个完整的例子:
[root@localhost epoll]# ls
client.cpp readme.md server.cpp utility.h
[root@localhost epoll]# ps
PID TTY TIME CMD
3451 pts/0 00:00:00 bash
3514 pts/0 00:00:00 ps
???????然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序并等待这个进程结束。所以要写一个shell,需要循环以下过程:
???????1.获取命令行
???????2.解析命令行
???????3.建立一个子进程 (fork)
???????4.替换子进程(execvp)
???????5.父进程等待子进程退出(wait)
???????根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#define MAX_CMD 1024
char command[MAX_CMD];
int do_face()
{
memset(command, 0x00, MAX_CMD);
printf("minishell$ ");
fflush(stdout);
if (scanf("%[^\n]%*c", command) == 0)
{
getchar();
return -1;
}
return 0;
}
char **do_parse(char *buff)
{
int argc = 0;
static char *argv[32];
char *ptr = buff;
while(*ptr != '\0')
{
if (!isspace(*ptr))
{
argv[argc++] = ptr;
while((!isspace(*ptr)) && (*ptr) != '\0')
{
ptr++;
}
}
else
{
while(isspace(*ptr))
{
*ptr = '\0';
ptr++;
}
}
}
argv[argc] = NULL;
return argv;
}
int do_exec(char *buff)
{
char **argv = {NULL};
int pid = fork();
if (pid == 0)
{
argv = do_parse(buff);
if (argv[0] == NULL)
{
exit(-1);
}
execvp(argv[0], argv);
}
else
{
waitpid(pid, NULL, 0);
}
return 0;
}
int main(int argc, char *argv[])
{
while(1)
{
if (do_face() < 0)
continue;
do_exec(command);
}
return 0;
}
???????一个C程序有很多函数组成。一个函数可以调用另外一个函数,同时传递给它一些参数。被调用的函数执行一定的操作,然后返回一个值。每个函数都有他的局部变量,不同的函数通过call/return系统进行通信。
?
结语:Linux系统关于进程程序替换的分享到这里就结束了,没有进行展示的操作大家可以自行练习,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~?