os内核入门-linux0.11诞生的故事和源码初探

张开发
2026/4/15 1:09:16 15 分钟阅读

分享文章

os内核入门-linux0.11诞生的故事和源码初探
直接去解读源码可能比较枯燥而且对阅读公众号的文章不友好这里只是引导入门拓展知识阅读源码还是需要自己下一些苦功夫。所以后续文章尽量会用形象的语言以源码为中心进行点到为止、深入浅出的描述。1. Linux诞生的历史演进Multics-UNIX-MINX-Linux下面要讲一个很长的故事时间要倒退到20世纪60年代这是一个大型、复杂操作系统盛行的年代比如IBM 的OS/360这个是商用成功了的但是Honey well霍尼韦尔的Multics系统虽然持续存在了多年却从来没有被广泛应用过Multics项目的参与者之一贝尔实验室因为该项目太复杂和进展缓慢而于1969年退出Multics失败了但是其影响深远。贝尔实验室退出了Multics开发但是这里牛人聚集这里主要提两个人一个是Ken Thompson在1969年夏天他媳妇回娘家了他闲着没事干但是非常喜欢打游戏为了在闲置的一个计算机上玩星际“星际旅行”游戏之前在Multics上玩一个月时间借鉴Multics开发出了UNIX的原型是用B语言写的。第二个人DennisRitchie为了对UNIX进行改造发明了C语言利用C语言对UNIX进行了重写。给了很多C程序员饭碗开创高级语言书写程序的一个新时代。UNIX出来后贝尔实验室向学校提供源码并发展了很多分支例如BSD版本、System V版本、Solaris版本等这个时代同样出现了微软的DOS系统和苹果的MAC系统后面作为插曲进行介绍。7080年代突然冒出来这么多OS上层应用写的代码要在这些不同系统上适配由于提供的API不一样就很麻烦。IEEE电气和电子工程师协会就开始标准化这些接口称作POSIX标准表示可移植操作系统接口Portable Operating SystemInterface of UNIX缩写为 POSIX 。UNIX出名后逐渐商业化没有授权就看不到源码了。这个时候有个美国人Andrew S. Tanenbaum在加州伯克利分校读的博士上面说的BSD就是这个学校研究出来的时间是重叠的。Andrew S. Tanenbaum虽然出生在美国但是祖上是荷兰人后来他又回到荷兰Vrije大学教书了这可是个大牛为了给学生教OS原理的课他在1987年写了一个MINIX操作系统自称没参考UNIX的代码。他还写了书介绍这个MINX操作系统完全公开。虽然只是教学的OS但是一时大家找不到其他的可以免费阅读的源码资料其他的OS源码都被软件商垄断保密起来了并且商用OS价格非常的贵。1991年Linus Torvalds在赫尔辛基大学计算机科学系上大二这个同学从小喜欢计算机爷爷是教授从小就会计算机编程。他为了学习MINIX自己购买了Intel 80386的电脑由于80386的一个硬件支持的新特性任务切换功能使他编写自己的OS有了可能。另外GUN开源软件的兴起带来了很多免费的工具比如GUN C编译器、bash shell、gdb等。他想把GUN的这些软件移植到MINIX上在这个过程中遇到很多问题他去找同在荷兰的Andrew S.Tanenbaum请教但是Andrew S. Tanenbaum不修改而GUN组织也计划写一个OS但是GUN一时半会还造不出来这个OS。所以迫使Linus Torvalds自己写一个OS来解决。经过快一年的折腾1991年10月5日LinusTorvalds在comp.os.minix上对外宣布Free minix-like Kernel sources for 386-AT诞生同样声称没有是使用MINIX一行代码。ftp服务器管理员命名文件夹的时候使用了缩写Linux就这样Linux正式诞生了。我们这里使用的0.11是1991年12月8日比较稳定可以正常运行的一个内核版本。Linux设计的接口符合POSIX并且得益于Internt的发展开源软件运动的兴起随后Linux在世界各地广泛传播应用最终到我们这个时代成为一方霸主。上面我们了解一下linux0.11诞生的基础这样有助于更好的去看待这份代码。下面配一张个性程序员的图来开始闭源OS插曲的说明插曲主流的windows和mac系统介绍windows DOS系统1979年微软从ATT获取授权并开发了运行于intel平台的Xenix基于UNIX7。1981年IBM的人问比尔盖茨有可以在IBM PC机上运行的OS不比尔盖茨推荐Digital Research公司的系统但是Digital Research公司托大不见IBM的人员。IBM回头又找到了比尔盖茨比尔盖茨找到了一家本地西雅图电脑产品公司有一个DOS系统一锤子价格5万美元买了过来卖给IBM的时候变聪明了是按照IBM卖出的机器按每台进行提成导致了后来大赚。DOS系统是一个蒂姆·帕特森Tim Paterson的程序员花费了四个月时间编写比尔盖茨又把这个人挖了过来比尔盖茨商业的确很厉害。MAC系统要从图形界面说起图形界面是美国的施乐在1981年推出的“施乐之星Xerox Star”电脑上携带的但是卖的比较贵买的人少。一天乔布斯到施乐公司访问见到了GUI界面的系统马上意识到前景很好于是1983年推出了图形界面操作系统Lisa OS基于BSD并配备了鼠标也是跟施乐学的。1983 年底盖茨宣布微软即将推出 Windows 1.0乔布斯得知后大发雷霆差人将盖茨叫到了苹果总部当着十来个研发团队成员的面呵斥盖茨“你在盗用我们的东西”接着盖茨便平静地说出了后来成为硅谷经典反驳台词的那句话——“我们都有个有钱的邻居叫施乐我闯进他们家准备偷电视机的时候发现你已经把它盗走了”。上面的历史回顾以UNIX为核心充满了江湖纷争但是不论什么都阻止不技术的发展。Multics-》UNIX-》MINX-》Linux虽然都宣传没有使用对方一行代码但是思想是相通的有的是看不上别人的实现而重写的。从哲学角度思考操作系统是人类设计的所以操作系统的设计思想跟我们人类的思维办事方式是一致的越深入了解其机制会越有同感。2. Linux源码初探下面回归正题从几个角度对代码有一个初步的接触激发下对代码的兴趣。2.1 如果你在电脑上看电影电脑在做什么计算机有哪些硬件CPU、内存、硬盘、网卡、键盘、鼠标、USB、屏幕、主板、风扇等。如果你在电脑上看电影电脑在做什么fs-blk_drv-mm-cpu首先电影XXX.rmvb在你电脑的硬盘上存储当在播放器点击播放这个电影的时候由于硬盘的速度比较慢不能把数据直接给CPU所以内核的块驱动程序先将电影读入内存播放器程序会把rmvb格式的数据计算成屏幕上显示的点这就需要cpu然后给到屏幕显示。另外播放器程序原本也是在硬盘上存储的。代码目录如下linux-0.11/fs目录下放的文件系统相关代码例如open.c 文件的打开、关闭、创建 read_write.c 对文件的读写操作 linux-0.11/mm 目录下放的是内存管理程序 memory.c 建立内存中地址程序使用也叫虚拟地址和键盘中地址物理地址的映射。 linux-0.11/kernel/blk_drv 含有硬盘和软盘的驱动程序负责对盘上的数据进行读写 ll_rw_blk.c 块设备的读写操作 hd.c 硬盘控制器程序2 使用printf打印字符串到屏幕经历了什么printf-write-int $0x80-system_call-sys_write-rw_char-rw_ttyx-rw_tty-tty_write-con_write-寄存器操作上一篇文章我们在linux-0.11/init/main.c中添加了一行代码printf(This my helloworld!\n\r);printf函数在mian.c中定义如下staticintprintf(constchar*fmt,...){va_listargs;inti;va_start(args,fmt);write(1,printbuf,ivsprintf(printbuf,fmt,args));va_end(args);returni;}vsprintf(printbuf, fmt, args)是字符串的格式化可以自己去研究下。这里write是一个系统调用下面看下这个wrire函数是怎么定义的/lib/write.c中_syscall3(int,write,int,fd,constchar*,buf,off_t,count)include/unistd.h中#define _syscall3(type,name,atype,a,btype,b,ctype,c) \typename(atypea,btype b,ctype c)\{\long __res;\__asm__ volatile(int$0x80\:a(__res)\:0(__NR_##name),b((long)(a)),c ((long)(b)),d ((long)(c))); \if(__res0)\return(type)__res;\errno-__res;\return-1;\}这里按照宏定义对write函数进行了定义翻译过来就是intwrite(intfd,constchar*buf,off_t,count){long__res;__asm{//... 参数传递mov eax,__NR_write//__NR_write的值定义为 4int0x80//这是重点32位陷阱门//... 返回值处理}return__res;}__NR_##name的定义为#define__NR_write 4int $0x80系统调用会执行kernel/system_call.ssystem_call: all sys_call_table(,%eax,4) # 间接调用指定功能C函数sys_call_table在include/linux/sys.h中定义fn_ptr sys_call_table[] { sys_setup,sys_exit, sys_fork, sys_read, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,。。。。。由上面的_NR_write 4找到函数sys_writefs/read_write.c中intsys_write(unsignedintfd,char*buf,intcount){if(fdNR_OPEN||count0||!(filecurrent-filp[fd]))return-EINVAL;inodefile-f_inode;if(S_ISCHR(inode-i_mode))returnrw_char(WRITE,inode-i_zone[0],buf,count,file-f_pos);printk((Write)inode-i_mode%06o\n\r,inode-i_mode);return-EINVAL;}fd的值是1这里牵扯到tty设备的初始化想了解了继续关注公众号讲到的时候说明tty是一个字符设备这里调用rw_char函数在fs/char_dev.c中if(!(call_addrcrw_table[MAJOR(dev)]))return-ENODEV;returncall_addr(rw,MINOR(dev),buf,count,pos);crw_table的定义为staticcrw_ptr crw_table[]{NULL,/* nodev */rw_memory,/* /dev/mem etc */NULL,/* /dev/fd */NULL,/* /dev/hd */rw_ttyx,/*/dev/ttyx */rw_tty,/* /dev/tty */NULL,/* /dev/lp */NULL};/* unnamed pipes */MAJOR(dev)了解驱动的同学都知道有设备的主从设备号通过命令查看如下主设备号是4这里对应rw_ttyx函数传入的minor为次设备号0tty_write(minor,buf,count));tty_write函数中下面三句话很重要tty channel tty_table PUTCH(c,tty-write_q); tty-write(tty);tty channel tty_table找到tty为0 tty_table就是tty_table结构体的第一个元素在kernel/chr_drv/tty_io.c中structtty_structtty_table[]{{{ICRNL,/* change incoming CR to NL */OPOST|ONLCR,/* change outgoing NL to CRNL */0,ISIG|ICANON|ECHO|ECHOCTL|ECHOKE,0,/* console termio */INIT_C_CC},0,/* initial pgrp */0,/* initial stopped */con_write,{0,0,0,0,},/* console read-queue */{0,0,0,0,},/* console write-queue */{0,0,0,0,}/* console secondary queue */PUTCH(c,tty-write_q);把要写的数据放入队列write_q中tty-write(tty);tty-write 由上面的tty_table找到对应这个con_write函数// 获取写队列的字符数量nrCHARS(tty-write_q);while(nr--){// 每次获取一个字符cGETCH(tty-write_q,c);//写操作的核心代码__asm__(movbattr,%%ah\n\tmovw%%ax,%1\n\t::a(c),m(*(short*)pos));这句嵌入汇编代码的意思是先把寄存器ax中存放字符c和其属性其中字符在低位。然后将ax中的数据存放在地址为pos的内存处。这样就完成了一个字符的printf后面的字符也是大同小异地写入到pos地址的内存处。具体汇编语言算是个拦路虎后续文章也会进行介绍。上面就是printf的流程是不是有点被这个分析吓到了但是这个过程从软件角度是不是很深入分析的很过瘾软件干到寄存器也算到头了不论啥时候回过来看这段分析都会回味无穷。后记文中的语言基本都是笔者参考了一堆的书和资料自己组织讲出来的费了挺多时间。书写的过程也是对知识的二次整理其实挺不容易鼓励大家也多写点什么。这一篇业余时间写了一个星期好像篇幅有点长下次会短点。linux0.11学习系列至少一周一更新纯干货分享无广告不打赏。欢迎转载欢迎评论交流往期链接os内核入门-linux0.11运行环境搭建“那路谈OS与SoC嵌入式软件”欢迎关注个人文章汇总https://thatway1989.github.io

更多文章