Linux5.4、实现一个简单shell

个人主页:Lei宝啊 

愿所有美好如期而遇


前言:

在实现简单shell前,我们需要掌握进程创建,进程终止,进程等待,进程替换。


先理解一下整体思路:我们的bash是个进程,在我们登陆的时候就会启动起来,然后输出命令行提示符,接着我们输入指令和选项,bash会将他们当成整体的字符串接收,然后将这个字符串根据空格分割成一个个的子串,比如"ls" "-a" "-l",然后创建子进程,由子进程进行程序替换去执行我们的指令,因为我们的指令也是程序,当然可以替换执行。

我们将会分五步进行实现:

Linux5.4、实现一个简单shell_第1张图片

1. 命令行提示符

我们先来看shell的命令行提示符

Linux5.4、实现一个简单shell_第2张图片

接下来我们试着打印一行我们的命令行提示符

Linux5.4、实现一个简单shell_第3张图片

首先,我们在打印的命令行提示符后不能加换行符,因为我们输入的指令就是跟在他后面的,但是我们不加换行符,这句话又无法打印,因为缓冲区是行缓冲区,需要我们手动去刷新缓冲区。

2. 命令行参数的接收

因为fgets会接收换行符,而我们不需要换行符,所以需要去掉他。

Linux5.4、实现一个简单shell_第4张图片

3. 命令行参数的分割

Linux5.4、实现一个简单shell_第5张图片

5. 子进程执行进程替换

Linux5.4、实现一个简单shell_第6张图片

我们可以看效果了

Linux5.4、实现一个简单shell_第7张图片

但是没有颜色看起来不好看,我们这样做

Linux5.4、实现一个简单shell_第8张图片

看效果

Linux5.4、实现一个简单shell_第9张图片

4. 父进程执行的指令

我们来执行cd指令,看看效果

Linux5.4、实现一个简单shell_第10张图片

 我们发现cd指令没有切换路径,为什么呢?首先我们的myshell是父进程,pwd是子进程替换执行的结果,而父子进程都有自己的工作目录,cd指令只是子进程切换了他自己的工作目录,对父进程是没有影响的,所以我们需要让父进程去执行cd指令。

Linux5.4、实现一个简单shell_第11张图片

chdir函数改变当前进程的工作目录,我们看效果

Linux5.4、实现一个简单shell_第12张图片

那么我们现在想说的是我们实现的myshell是不是bash的子进程呢?所以myshell切换路径会不会影响bash的路径呢?我们来看

Linux5.4、实现一个简单shell_第13张图片

6.关于环境变量的传递

Linux5.4、实现一个简单shell_第14张图片

Linux5.4、实现一个简单shell_第15张图片

我们可以看到子进程确实得到了父进程传递下来的环境变量,其实就算我们不传,也会通过进程地址空间继承父进程的环境变量,因为进程程序替换不会替换环境变量。

Linux5.4、实现一个简单shell_第16张图片

那么我们现在要想在原有环境变量的基础上新增环境变量呢?

Linux5.4、实现一个简单shell_第17张图片

Linux5.4、实现一个简单shell_第18张图片

接着我们就会发现,父进程新增的环境变量没有传递给子进程,那么父进程有没有新增环境变量呢?

Linux5.4、实现一个简单shell_第19张图片Linux5.4、实现一个简单shell_第20张图片

 我们来看结果

Linux5.4、实现一个简单shell_第21张图片

也就是说,我们的父进程是导入了我们新增的环境变量,那么为什么子进程得不到我们新增的环境变量呢?我们接着尝试

Linux5.4、实现一个简单shell_第22张图片

Linux5.4、实现一个简单shell_第23张图片

Linux5.4、实现一个简单shell_第24张图片

我们现在再来理一下思路,之前的putenv(cutup[1])存的是子串的地址,而我们当时确实是给父进程导入了新的环境变量,但是当我们continue后,再开始时,origin数组被清空,而我们的指针仍然指向这块空间,所以当我们再去根据这个指针去找的时候,什么都找不到,所以也就传不到子进程那里,甚至我们都已经无法再在父进程中找到我们上一次导入的环境变量,我们来看结果。

Linux5.4、实现一个简单shell_第25张图片

Linux5.4、实现一个简单shell_第26张图片

我们发现第二次开始的时候,果然已经无法找到上次导入的环境变量。

你可能感兴趣的:(Linux,linux,shell)