(2)DIY Shell之——内建命令与外部命令

Linux TOMORROW 2年前 (2017-12-03) 2742次浏览 2个评论 扫描二维码

 

这是本博客的第一个文章专辑。主要介绍如何用 C 语言基于Linux系统来实现一个简单shell,DIY 一个shell。通过自己编程实现一个Linux下的shell,可以使得个人对进程的概念、进程的通信和操作系统的运行的理解更加的深刻。还会大大增加个人学习的成就感,提供学习兴趣。

这一个文章专辑被命名为 StupidShell ,这也是作者所实现的shell的名称,已经开源放到了 GitHub:StupidShell 代码仓 上,感兴趣的读者可以自行前去查看下载,也欢迎对该项目进行星标、提出改善建议、或者自行 fork 之后改善。

这是 StupidShell 专辑本章里的第二篇文章,主要介绍内建命令和外部命令,以及外部命令的实现方法。

内部命令

内部命令实际上是shell程序本身的一部分,通常都是一些比较简单的系统命令。这些命令所实现的功能与所做工作都是由shell程序本身来完成的,也就是在shell程序的源码里面实现的,其执行速度要比外部命令快很多,因为执行内部命令时,shell无需创建新的进程产生多余的开销。常见的外部命令有:

exit
cd
echo

外部命令

外部命令区别于内建命令,通常是一些功能较为强大、复杂的命令。它由shell分析然后通过Linux内核 API 创建新的进程,在新的进程中执行,在新的进程中所执行的代码是不属于 shell 的,所以在 shell 加载时并不随之一起被加载到内存中,而是在外部命令执行时才将其调入内存中。

例如,命令 ls ,它是一个列出当前工作目录下所有文件和文件夹的命令,但是实际上 ls 本身就是一个可执行二级制程序文件,通常存放在系统的/bin 文件夹下。shell 在执行该命令时是把 ls 的可执行二级制程序文件加载到内存当中执行。常见的Linux下 shell 外部命令有:

ls
cat
more
grep

外部命令的调用方法

外部命令在被调用时通常是通过Linux操作系统所提供的 exec 函数族来完成的。exec 函数族的作用是根据指定的文件名和相关参数找到可执行文件,如果找到了可执行文件,那么该函数执行之后是不会有返回的,它会用可执行文件来取代当前进程的内容。换句话说,就是在进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

exe 函数族有以下函数:

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[]);

外部命令执行举例

例如,我要通过 shell 来执行外部命令

ls -l -a

ls 就是一个在Linux系统下已经存在了的二进制可执行文件,-l 就是执行该文件时要传入的参数,那么我们就可以通过 exe 族函数中的一个函数 execvp()(其他函数也可以),来执行该外部命令。

char *argv[] = {"ls","-l","-a",NULL};
execvp("ls",argv);

execvp()函数的第一个参数是要执行的命令的文件名,第二个参数就是一个指针数组,该数组一个个元素指向命令的字符串,中间的元素指向参数的字符串,因为参数是不定的,所以数组长度也是不定,但是要以 NULL 空指针结尾。

调用 execvp()函数并且找到对应的 ls 可执行文件后,当前的进程的内容就会被 ls 可执行文件的内容所取代,也就是说原来的调用 execvp()的那个进程已经不存在了,即使 execvp()下面还有其他的代码,全都不会被执行了。当 ls 命令执行完之后,进程就结束了。

那么,问题来了,不管 shell 程序中用不用循环结构,都是只能调用一个外部命令?如果还要执行其他命令,只能重新运行 shell 程序?

但是,我们都知道,实际上不管是 Windows 下的命令提示符,还是Linux下的 shell 都是可以循环执行无限多的命令的,不管是外部命令还是内建命令。

那么,这又是怎么实现的呢?

具体参考下一章的内容:

DIY Shell 之——创建子进程执行外部命令

exec 族函数具体说明与用法参考:

https://blog.csdn.net/guoping16/article/details/6583383


TOMORROW 星辰 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:(2)DIY Shell 之——内建命令与外部命令
喜欢 (6)
TOMORROW
关于作者:
一个从石头坑掉到泥坑里的攻城狮。
单薄的微笑发表我的评论  请填写正确的 个人信息
取消评论
表情 加粗 斜体 签到
(2)个小伙伴在吐槽
  1. 好文章!666,学习了
    zhuiliang72019-05-05 21:21 回复 Windows 7 | 未知浏览器
  2. 好文章!666,学习了
    kygqmsu2019-05-05 19:52 回复 Windows 7 | 未知浏览器