linux0.11init进程及shell原理分析

来源:互联网 发布:定制婴儿知乎 编辑:程序博客网 时间:2024/05/16 16:24

static char * argv_rc[] = { "/bin/sh", NULL };static char * envp_rc[] = { "HOME=/", NULL };static char * argv[] = { "-/bin/sh",NULL };static char * envp[] = { "HOME=/usr/root", NULL };void init(void){int pid,i;setup((void *) &drive_info);(void) open("/dev/tty0",O_RDWR,0);(void) dup(0);(void) dup(0);printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,NR_BUFFERS*BLOCK_SIZE);printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);//fork将创建一个子进程(pid=2),注意if括弧里面执行是子进程的内容。//首先子进程关闭句柄0,然后以只读方式打开/etc/rc文件,接着调用execve函数//将进程自身替换成/bin/sh程序,然后执行/bin/sh程序。//注意:argv_rc和envp_rc分是/bin/sh程序的参数和环境变量。//ps:关闭句柄0,打开/etc/rc文件的作用是把标准输入stdin重定向到/etc/rc文件中,//这样shell程序/bin/sh就可以运行rc文件中的命令。//由于这里的sh是非交互的(参数前面没有"-"符号),也就是说它只是作为一个命令程序来//运行/etc/rc文件,所以执行完rc文件中命令之后就会立刻退出,进程2也随之结束。if (!(pid=fork())) {close(0);if (open("/etc/rc",O_RDONLY,0))_exit(1);execve("/bin/sh",argv_rc,envp_rc);_exit(2);}if (pid>0)while (pid != wait(&i))/* nothing */;while (1) {if ((pid=fork())<0) {printf("Fork failed in init\r\n");continue;}if (!pid) {close(0);close(1);close(2);setsid();(void) open("/dev/tty0",O_RDWR,0);(void) dup(0);(void) dup(0);_exit(execve("/bin/sh",argv,envp));}while (1)if (pid == wait(&i))break;printf("\n\rchild %d died with code %04x\n\r",pid,i);sync();}_exit(0);/* NOTE! _exit, not exit() */}

可以看到linux0.11执行/bin/sh产生shell程序。现在linux版本的shell种类已经很多了,除了我们熟悉的 sh、ksh、csh、bash ... 外,还有各种 free 或商业版本如: RC、ES、EShell、psh、Zoidberg 等等。实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。

在上面init进程中/etc/rc文件其实就是shell脚本,该脚本中的内如如下:

/etc/update &
echo "/dev/fd1  /" > /etc/mtab
echo "=== Ok. "

首先执行update程序,后面单一个& 符号(放在完整指令列的最后端)表示将该指令程序放入后台中工作,至于它了干了什么就不得而知了。然后执行两个echo命令,第一个输出重定向到/etc/mtab文件,第二个输出到终端界面上。

关于/bin/sh程序,这里再说几点,首先对于一个操作系统来说,我们要使用它必然要涉及到交互,shell就作为用户与内核进行交互的接口,也可以说shell就是系统的用户界面。而shell本身也是一个程序,只不过它比较特别,操作系统启动之后就一直在运行,等待用户输入,然后解释用户输入的参数,这里的参数大部分都是独立的命令程序名,比如mkdir,mkfs等,shell会将这种命令程序调入内存执行,因此这些命令程序都是shell的子程序,完成对应的功能之后就会退出(当然有些在后台程序运行),然后shell又会继续等待用户输入参数

但是shell的有一个参数比较特殊,再回到上面init函数中,可以发现两个地方执行/bin/sh程序,但参数不一样,区别在于“/bin/sh”参数前面是否带"-"符号,注释中也说明了,不带"-"表示以非交互方式执行,也就是说带"-"表示以交互方式执行,什么意思呢?实际测试下。

首先去掉argv参数的“-”,运行linux0.11的情况如下图所示:


可以看到linux一样能运行,但是这样用起来似乎不对劲,可以发现命令提示符无法根据当前目录进行相应的显示,想知道当前目录必须要pwd一下,所以缺乏了与用户的交互。

按照这种说法,如果加上“-”符号就会像我们普通的shell操作一样了,不过我们还是再测试下。如下图所示:


确实是这样,命令提示符文字会随着当前目前的切换而自动修改。


关于shell的原理还有一个“鲜为人知”(网上看到有一个网友说用了几年shell都不知道这回事儿)的知识再提下:shell的内建(build-in)命令。

首先上面也说了shell是一个特殊的程序,作为内核的一个“壳”一直存在,解释用户输入的各种命令,这些命令大多是独立的程序,但是有一些命令就不是的了。比如cd命令,当你“which cd”时,将不会得到目录输出,那么既然“cd”不是独立的一个程序,那么它又是怎么回事呢?不买关子了,其实它是shell程序的一个内建命令,也就是说cd这个功能嵌在shell里面,在shell程序里面实现的。这种内建命令除了cd之外,还有很多,其中就有一个最常见的echo命令。如果你尝试也 which echo,你会发现有目录打印出来,然后会说,哦,这个不是的嘛。但是shell里面也有echo实现。为什么要这种内建命令,一个说法是为了提高效率,因为如果不是内建命令,就需要先fork出一个进程执行该命令,然后才执行命令内容,内建命令就不用fork,直接执行命令内容。




0 0