程序替换:
替换一个进程正在运行的程序,重新加载一个新的程序到物理内存中,对一个进程的代码段通过页表在物理内存中的地址进行修改映射关系,让程序的代码经过页表转换后,指向了新的程序位置
让一个进程pcb通过页表转换映射到物理内存上另一个程序地址;进程将运行另一个程序
以前的数据和代码都失效了,所以需要重新初始化页表和虚拟地址空间的代码段和数据段
如何进行程序替换:
exec函数族
带p和不带p的区别: 要加载的程序是否需要提供路径
v和l的区别: 程序的运行参数是否是参数平铺或者直接组织为字符串指针数组给予
带e与不带e的区别: 要运行的程序是否需要重新需要重新自定义环境变量,不带e使用默认环境变量
execl 第一个参数是程序路径,之后的参数是程序参数
execlp 第一个参数是文件名,之后参数是程序参数
execv 第一个参数是程序路径,之后参数使用字符串指针数组
自制minishell:
shell命令处理外部命令是通过创建子进程后程序替换完成功能
还有一部分是内建命令,也就是shell自带的命令;比如cd
思路分析:
<1>首先模拟出shell的样子,打印出终端的命令行[luzihan@TecentCloud]$
<2>刷新行缓冲区,将内容显示出来
<3>创建一个字符串数组,存放我们输入的命令名称和参数
%[^\n] 读取字符串内容,直到遇到\n结束
%*c 读取缓冲区内剩下的\n,*表示跳过输入该值
<4>解析输入的字符串的内容
<5>创建子进程,进行程序替换
代码实现:
#include<stdio.h>
#include <unistd.h>
#include <string.h>
#include<ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
while (1)
{
printf("[luzihan@TecentCloud]$");
fflush(stdout);
char tmp[1024] = { 0 };
scanf("%[^\n]%*c",tmp);
printf("%s\n", tmp);
//创建一个指针放在tmp的起始位置
char* ptr = tmp;
int argc = 0;
//创建一个字符串指针数组存放参数
char* argv[32] = { NULL };
while (*ptr != '\0')
{
//ptr指向非空白字符串
if (!isspace(*ptr))
{
//把参数存到argv数组中
argv[argc] = ptr;
argc++;
//ptr指向非空字符串而且没遇到\0,说明参数没读取完,继续往后读取
while (!isspace(*ptr) && *ptr != '\0')
{
ptr++;
}
//手动分割
*ptr = '\0';
//ptr往后走一步,重新循环,准备读取之后的参数
ptr++;
continue;
}
//循环结束,参数解析完毕,手动置空
argv[argc] = NULL;
}
//创建子进程,进行程序替换
int pid = fork();
if (pid == 0)
{
execvp(argv[0], argv);
//进程创建失败直接退出
exit(0);
}
//避免产生僵尸进程
wait(NULL);
}
return 0;
}
代码测试运行图:
基础IO:
标准IO库接口:FILE* fp
int fd
文件描述符:
文件流指针,文件描述符
重定向的原理
静态库和动态库的生成与使用