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,直接执行命令内容。
- linux0.11init进程及shell原理分析
- linux0.11进程调度分析
- linux0.11分析之创建进程
- 对Linux0.11 中 进程0 和 进程1分析
- linux0.11中的进程
- linux0.11 进程切换
- Linux0.11 进程0
- Linux0.11内核分析三之进程调度
- linux0.11相关进程数据结构
- Linux0.11内核进程数据结构
- android init 进程分析
- Init进程分析
- Android init进程分析
- Android Init进程分析
- Android Init进程分析
- busybox init进程分析
- busybox init进程分析
- init进程源码分析
- 4.查找最小的k 个元素
- Android WebView开发问题及优化汇总
- lesson19
- 人,说到底还是要靠自己。
- CAD中如何删除顽固图层?
- linux0.11init进程及shell原理分析
- OC内存管理剖析
- java只有值传递(P123)
- Windows终止线程的四种方法
- C语言之结构体
- coreText 的简单使用~
- Actor::updateMassFromShapes: Compute mesh inertia tensor failed for one of the actor's mesh shapes!
- stardict 词典下载
- WORD 文档中复选框的使用方法