LinuxShell命令模拟器

Posted by Liao on 2019-12-11

LinuxShell命令模拟器

一.原理分析

0.终端执行步骤

​ 1)读取用户从键盘输入的命令,终端会分析是否是内部命令。如果是,则把命令分解为系统调用,并传给linux内核。如果不是,若不是再检查是否是一个应用程序,模拟shell的命令解析器正是这样。上述两种情况也不是的话,则报出错误信息。

​ 2)分析命令,以命令名为文件名,将其他参数改造为系统调用execve()内核级系统调用所要求的形式;

int execve(const char * filename,char * const argv[ ],char * const envp[ ]);

execve()用来执行参数filename字符串所代表的文件路径(用户输入的命令),第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组envp,envp数组里保存的系统的环境变量。

3)终端进程调用fork()建立一个子进程;

4)终端进程本身用系统调用wait()等待子进程完成。子进程执行execve()时,子进程根据命令名到目录中查找相关的文件,把它调入内存,执行程序(解析命令)。(即fork()子进程,调用exec()加载运行命令)

5)当子进程完成后,向父进程(终端进程)报告,唤醒终端进程。在做必要的判断之后,终端向用户发出提示符,让用户输入新命令,重复上述过程进行处理。

文件名与数据,这在 Linux 上被分成两个部分:用户数据 (user data) 与**元数据 (metadata)**。用户数据,即文件数据块 (data block),数据块是记录文件真实内容的地方;而元数据则是文件的附加属性,如文件大小、创建时间、所有者等信息。

在 Linux 中,元数据中的 inode 号(inode 是文件元数据的一部分但其并不包含文件名,inode 号即索引节点号)才是文件的唯一标识而非文件名。文件名仅是为了方便人们的记忆和使用,系统或程序通过 inode 号寻找正确的文件数据块。

1.pwd

1)Linux的文件系统是树形结构,称为目录树,树上的每一个节点被称为inode(索引节点,用于查找所有存放文件内容的块),指针的集合称为目录,叶子节点被称为链接

2)想要查找一个绝对路径,就需要追踪链接,读取目录,通过每个目录的’.’一个目录接着一个目录往上追踪,直达树的根节点。

3)在同一个Linux文件系统根目录中,’.’和’..’指向同一个inode,PWD命令循环执行 2)步骤的操作,知道’.’和’..’的inode相同时,就可以认为到达文件树的根部了。

2.cd

在程序中我通过chdir(const char* path)实现改变当前目录,参数是指向目录的指针,调用的进程要有搜索整个目录的权限。

如果参数的路径名有效,则系统内核定位到该目录的inode(索引节点),并检查其文件类型和权限,若均有权限,系统会用新目标目录的路径名(索引节点)代替原来目录的索引节点。

3.copy

copy命令是用于把一个文件复制到另一个文件。由于在函数库中没有copy的接口,故要实现copy命令,得通过存在于文件系统中某个目录下的单独的程序。父进程终端通过fork()产生子进程后,子进程定位和执行命令cp,通过main(int argc,char *argv,envp),argc是命令行有关参数数目的计数器,包括程序名称;argv是一个指向数组的指针,argv[0]指向字符串“cp”,argv[1]指向字符串“file1”,argv[2]指向字符串”file2”。第三个参数envp是一个指向环境变量的指针,用以将终端的类型和根目录等信息传递给程序。

4. find

为了避免从头到尾对目录搜索,加快查找速度的方法是在每个目录中使用散列表,散列处理文件名,检查链表头在该位置上链表的所有表项,查看要找的文件名是否存在。

读取文件时,要知道文件名和它所在的磁盘块,类似于静态链表的一层层查找。

绝对路径的查找从根目录开始,相对路径从当前路径开始。

未完待续…

https://www.cnblogs.com/chengliangsheng/p/3601762.html

http://www.voidcn.com/article/p-kqdznczj-qz.html

https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html