目录
1. 程序替换的原因
2. 程序替换原理
3. 替换函数
4. 函数解释
5. 命名理解
6.简陋版shell的制作
补充:
Linux🌷
1. 程序替换的原因
进程自创建后只能执行该进程对应的程序代码,那么我们若想让该进程执行另一个“全新的程序”这
便要用到程序替换技术。
2. 程序替换原理
用
fork
创建子进程后执行的是和父进程相同的程序
(
但有可能执行不同的代码分支
),
子进程往往要调
用一种
exec
函数以执行另一个程序。当进程调用一种exec
函数时
,
该进程的用户空间代码和数据完
全被新程序替换
,
从新程序的启动例程开始执行。调用exec
并不创建新进程
,
所以调用
exec
前后该进
程的
id
并未改变。
程序替换图解如下:
3. 替换函数
其实有六种以
exec
开头的函数
,
统称
exec
函数:都可以达到进程替换的目的。
#include <unistd.h>
//path:路径+文件名
//file:文件名
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[]);
4. 函数解释
- 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回;
- 如果调用出错则返回-1;
- 所以exec函数只有出错的返回值而没有成功的返回值。
5. 命名理解
这些函数原型看起来很容易混
,
但只要掌握了规律就很好记。
- l(list) : 表示参数采用列表;
- v(vector) : 参数用数组;
- p(path) : 有p自动搜索环境变量PATH;
- e(env) : 表示自己维护环境变量;
exec
调用举例如下
:
#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("/bin/ps", "ps", "-ef", NULL, envp);
execv("/bin/ps", argv);
// 带p的,可以使用环境变量PATH,无需写全路径
execvp("ps", argv);
// 带e的,需要自己组装环境变量
execve("/bin/ps", argv, envp);
exit(0);
}
事实上
,
只有
execve
是真正的系统调用
,
其它五个函数最终都调用
execve,
所以
execve
在
man
手册第
2
节
,
其它函数在man手册第
3
节。这些函数之间的关系如下图所示
6.简陋版shell的制作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define NUM 128
#define CMD_NUM 64
int main()
{
char command[NUM]={0};
for(;;)
{
printf("[renhaha@mini_shell mydir#]");
fflush(stdout);
fgets(command,NUM,stdin);
command[strlen(command)-1]='\0';
const char* sep=" ";
char* argv[CMD_NUM]={NULL};
argv[0]=strtok(command,sep);
int i=1;
while(argv[i]=strtok(NULL,sep))
{
i++;
}
if(strcmp(argv[0],"cd")==0)
{
if(argv[1]!=NULL)
chdir(argv[1]);
}
if(fork()==0)
{
execvp(argv[0],argv);
exit(1);
}
waitpid(-1,NULL,0);
}
return 0;
}
补充:
makefile一次make多个文件
坚持打卡!😃