babyos2
文章平均质量分 69
从0实现一个简单的类linux操作系统,包括:引导,中断异常及系统调用,内存管理,进程管理及调度,文件系统(inode, 基本文件操作), IPC(pipe,socket,signal),shell,multi-processor,network。
孤舟钓客
人生如梦,梦何曾醒?不过旧愁新怨。但无他。回首向来萧瑟处,也无风雨也无晴。夜阑风静彀纹平,小舟从此逝,江海寄馀生。
展开
-
babyos2(43) network(9) -- tcp, sock_stream
前面给babyos实现了简单的UDP,这次准备实现一个非常简单的TCP协议。TCP提供一种面向连接的、可靠的字节流服务。在一个TCP连接中,仅有两方进行彼此通信。 TCP通过下列方式来提供可靠性: • 应用数据被分割成 TCP认为最适合发送的数据块。这和 UDP完全不同,应用程序产生的数据报长度将保持不变。由 TCP传递给IP的信息单位称为报文段或段( segment); • 当TCP发...原创 2018-05-06 23:27:34 · 488 阅读 · 2 评论 -
babyos2(42) network(8) -- udp, SOCK_DGRAM, gethostbyname
前面为babyos2实现了发简单的UDP包,以及解析DNS,但通常DNS解析是用户态通过socket发DNS请求并解析结果,UNIX一般会使用gethostbyname。这次准备实现SOCK_DGRAM,以及用户态发dns请求及解析,并实现一个简单的DNS echo 服务器和客户端验证。1. SOCK_DGRAM这里实现一个简单的SOCK_DGRAM,类似于前面实现的socket_local_t和...原创 2018-04-26 19:20:25 · 342 阅读 · 0 评论 -
babyos2(41) network(7) -- udp, dns resolve
前面为babyos2实现了简单的raw socket及从用户态ping指定IP地址。而通常意义的ping不但可以ping某个具体的地址,还可以ping baidu.com这种域名。而从内核角度看,要发送IP包,必须知道目的IP地址。所以需要经过域名转换,将给定的域名转换成IP地址,这就是常说的DNS(Domain Name System)的主要功能。反映到用户态就算常用的gethostbyname...原创 2018-04-26 19:20:19 · 524 阅读 · 0 评论 -
babyos2(40) network(6) -- sock_raw, ping
前面babyos2实现了从内核中构建icmp echo包,并发送出去,以及icmp答复、及收到回复时显示相关信息,但这些都是在内核中处理的。而通常的网络应用都是从用户态发送并接受信息的。很久前实现了通过socket进行进程间通信,现在是时候实现通过socket进行网络通信了。而一个最常用、最简单的网络应用就算ping。ping是使用type=SOCK_RAW类型的socket,所以首先要让baby...原创 2018-04-26 19:20:13 · 340 阅读 · 0 评论 -
babyos2(39) network(5) -- icmp echo request, reply, receive
前面为babyos2 实现了发送IP数据报,但只测试了同一个局域网内发送,而当目的IP跟发送发自己的IP不在同一局域网内时,babyos2会把IP数据报发往网关。而如何测试是否发送成功,首先想到的是ping。ping使用ICMP(Internet控制报文协议)。ICMP经常被认为是 IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被 IP层或更高层协议( TCP或UDP...原创 2018-04-26 19:20:06 · 3890 阅读 · 0 评论 -
babyos2(38) network(4) -- ipv4, transmit, receive, checksum, arp retry
IP:网际协议,I是TCP/IP协议族中最为核心的协议。所有的 TCP、UDP、ICMP及IGMP数据都以I P数据报格式传输。IP协议提供不可靠、无连接的数据报传送服务。1.IP首部最高位在左边,记为 0 bit ;最低位在右边,记为 31 bit。4个字节的32 bit值以下面的次序传输:首先是 0~7 bit,其次8~15 bit,然后1 6~23 bit,最后是24~31 bit。这种传输...原创 2018-04-26 19:20:00 · 500 阅读 · 0 评论 -
babyos2(37) network(3) -- arp, request and reply
一台主机要将一个帧发送到另一台主机,仅知道这台主机的IP地址是不够的,还需要知道主机在网络中的有效硬件地址。对于TCP/IP网络,地址解析协议(ARP) 提供了一种在IPv4地址和各种网络技术使用的硬件地址之间的映射。前面babyos2实现了向特定ethernet addr发送帧,实现ARP协议的条件已经成熟。ARP协议相对功能比较简单,准备只实现基本功能:1)广播ARP request2)收到A...原创 2018-04-26 19:19:54 · 907 阅读 · 0 评论 -
babyos2(36) network(2) -- ethernet layer, send, receive
前面为babyos2支持了简单的网卡驱动RTL8139,这次准备实现往特定的mac地址发包。1.bufferTCP/IP 详解 卷2,一开始就讲述了mbuf结构及其用法,整个BSD的网络部分大量使用了该结构。babyos2不准备实现功能如此强大、复杂的buffer,但准备实现一个简化版,然后逐步完善增加功能。typedef struct net_buf_s { uint32 m_data...原创 2018-04-26 19:19:47 · 404 阅读 · 0 评论 -
babyos2(35) network(1) -- simple RTL8139 nic driver
要为babyos2实现网络,首先要支持网卡,之前选了RTL8139,为此前面做了PCI相关的一些东西,这次要实现简单的网卡驱动。1.从PCI获取设备信息uint32 rtl8139_t::get_info_from_pci(){ /* get pci device */ pci_device_t* device = os()->get_arch()->ge...原创 2018-04-26 19:19:38 · 733 阅读 · 0 评论 -
babyos2(34) PCI Config space and Enumerating PCI buses
想为babyos2实现网络功能,第一步就是得驱动网卡。选了个比较古老但general的网卡RTL8139,看了一些介绍,发现得先搞PCI。1.Enumerating PCI Buses 类定义:/* * guzhoudiaoke@126.com * 2018-03-01 */#include "types.h"class pci_device_bar_t {publi...原创 2018-04-26 19:19:30 · 689 阅读 · 0 评论 -
babyos2(33) bug fix 2 - bug on mp
前面为babyos2实现了多核的启动及调度,但测试过程中发现当使用多个核启动时会随机性存在segment fault。因为bug出现机率较小,在shell.cc中写了如下测试程序:static void test_fork_wait_exit(const char* times){ int t = 0; while (*times != '\0') { ...原创 2018-02-24 23:48:47 · 327 阅读 · 0 评论 -
babyos2(32)multi-processor,startup APs, mp schedule
前面解析了MP config, 这次准备为babyos2实现启动其他processor。 解析config的时候可以看到,其中一个processor被指定为bootstrap processor(BSP),其他的称为application processor(AP)。AP 的启动有固定的流程,在Intel MP spec中有描述。 为了简化cpu_t类,把一些代码挪到了新的类,在此不再描述。然...原创 2018-04-26 19:19:15 · 1003 阅读 · 0 评论 -
babyos2(31)multi-processor configuration
要为babyos2实现MP(multi-processor),首先得解析MP configuration。找到mp configuration的一种方法是通过mp floating pointer.1.mp floating pointerIntel MP Spcification 中对floating pointer 描述如下: The MP Floating Pointer Stru...原创 2018-04-26 19:19:08 · 904 阅读 · 0 评论 -
babyos2(30) APIC, local APIC, I/O APIC
Intel从Pentium开始引入APIC(Advanced Programmable Interrupt Controller),以适应MP(Multiple processor)环境。 Local APIC,在处理器内部 I/O APIC 在PCI-to-ISA bridge(PCI-to-LPC bridge)的LPC控制器内每个逻辑处理器(logical processor)有自己...原创 2018-04-26 19:18:51 · 2481 阅读 · 0 评论 -
babyos2(29) socket(AF_LOCAL), IPC
这几天为babyos2实现了通过socket进行进程间通信,即AF_LOCAL相关功能,主要参考linux 1.2。 socket常翻译为套接字,也有些地方翻译成插口,挺形象。把socket想象成类似网线插口的东西,则通过一根网线(连接),把两个socket连接起来,就可以进行通信。 AF_LOCAL域的socket比较简单,因为在同一个系统中,就可以通过addr(path)查找要连接的soc...原创 2018-04-26 19:18:44 · 1079 阅读 · 0 评论 -
babyos2(28) strange problem, strange solve
这两天看socket AF_UNIX(AF_LOCAL) 相关的代码,准备为babyos2实现socket 进程间通信。linux 内核代码虽然是C写的,但很多地方用了面向对象的思想,socket代码中,为了接口一致,各种域类型的socket都用socket结构做接口,但里面op结构不同,操作各不相同。 babyos2是C++写的,但从来没用过继承,这次感觉机会来了,可以用继承来实现这种关系。于...原创 2018-01-21 18:27:20 · 389 阅读 · 0 评论 -
babyos2(27) pipe
为babyos2实现pipe进程间通信方式。一个pipe表现为两个文件描述符fd[2],对应两个打开的文件,一个只读,一个只写。当通过fork创建子进程的时候,会拷贝父进程打开的文件,所以也持有这两个打开的文件。 使用的时候,一个关闭读端,一个关闭写端。即父子进程各自只剩下一个打开的文件,例如父进程关闭写端,子进程关闭读端: parent: fd[0] <-> file {...原创 2018-04-26 19:18:30 · 423 阅读 · 0 评论 -
babyos2(26)fs(4), lock
之前为了简化问题,兼之之前没有实现semaphore,文件系统的操作未加锁。上次为了实现读取硬盘时睡眠等待,实现了一个sem类,所以为babyos2文件系统加锁的时机已经成熟。主要用类三个锁: 1.inode table的锁 2.file table的锁 3.inode的锁。 前面两个比较简单,占用锁时间不会太长,用的自选锁,inode可能持有锁时间比较长,所以用的semaphore。...原创 2018-04-26 19:18:23 · 313 阅读 · 0 评论 -
babyos2(25) block dev, semaphore,sleep when wait for hard disk
babyos2前面实现的读取ide硬盘虽然靠中断来通知读取/写入完成,但等待过程中采用的是循环等待,尽管能工作,但不合理,所以准备实现睡眠等待的方式。增加下面几个类/结构: hard_disk_t类,实现对硬盘的操作, block_dev_t类表示一个块设备, io_buffer_t类表示一个块缓冲区,也用作缓存,一个block_dev_t类会预分配若干个io_buffer_t。当要读取...原创 2018-04-26 19:18:16 · 329 阅读 · 0 评论 -
babyos2(24) simple shell (3),printf, cd, mkdir, ln, rm, cp, mv, cat
前面实现了基本的shell执行命令,并实现了ls,这次准备为babyos2实现几个基本的命令。当然为了打印更简单,先实现一个printf。1.printfint userlib_t::sprint_int(char* buffer, int n, int width, int base, bool sign){ char buf[16] = {0}; uint32 ...原创 2018-04-26 19:18:09 · 345 阅读 · 0 评论 -
babyos2(23) simple shell (2),load elf from file, args for exec, ls
babyos2前面实现了从键盘中断读取数据并回显,下一步准备实现: 1)通过读取的命令创建新进程 2)exec时传递参数给新进程 3)ls之前因为没有文件的概念,exec时传入的时可执行文件在磁盘上的lba和size,然后通过读取数据加载elf,为了能实现简单的shell,需要能从文件系统中读取elf文件。static int32 read_file_from(int fd, v...原创 2018-04-26 19:18:01 · 357 阅读 · 0 评论 -
babyos2(22) simple shell (1),mknod, console read, write
到此,babyos2已经有了基本的中断、异常、系统调用,基本的物理、虚拟内存管理,基本的进程创建、fork、exec、调度,一个简单的文件系统,是时候实现一个简单的shell了。首先要让现在的console能够以设备文件的方式读取、写入。 简单的想法是,维护一个缓冲区,当键盘中断发生时,往缓冲区写入数据,当read时,从里面读取数据,当然要维护读、写指针。 另外就是增加设备类型的inode...原创 2018-04-26 19:17:54 · 334 阅读 · 0 评论 -
babyos2(21)mkdir, link, unlink
前面babyos2实现了create, open, close, read, write 文件,接下来实现一个简单的创建目录mkdir, 及link和unlink。还是暂时不考虑锁,后面再添加。1.mkdirint file_system_t::do_mkdir(const char* path){ if (create(path, inode_t::I_TYPE_DIR, ...原创 2018-04-26 19:17:47 · 417 阅读 · 0 评论 -
babyos2(20) fs (2), file, open, close, read, write
前面已经探究了super block, inode, bitmap等基本的结构、读写,以及实现了一个简单的namei实现从path找到inode。现在准备为babyos2实现基本的文件操作,打开,创建、读写等。为简单起见,还是先不考虑多进程访问需要的锁,等功能完成后再增加锁。1.open, close, createint file_system_t::write_inode(inod...原创 2018-04-26 19:17:27 · 338 阅读 · 0 评论 -
babyos2(19) fs (1), fs struct, super block, inode, bitmap, namei
文件系统是操心系统必不可少的一部分,babyos2准备参考xv6实现一个简单的文件系统。 为了简单,暂时不考虑多进程之间的竞争,即暂时不考虑锁的问题,功能实现完后再增加锁。xv6文件系统,磁盘第一个扇区为引导扇区,第二个扇区是super block,后面是inode,再后面是bitmap,之后是data block,xv6后面还有log扇区,babyos2暂时不准备实现该功能,所以没有这部分...原创 2018-04-26 19:17:20 · 422 阅读 · 0 评论 -
babyos2(18)—— signal,kill,do_signal,sig_return
signal是一种IPC方式,babyos2准备实现一个比较简单的模型,只探究它的基本原理,不深究各个信号具体意义及相互关系等。基本思路: 1)每个进程有一个信号队列,存放已收到未处理的信号 2)一个进程要发送一个信号到另一个进程,通过系统调用sys_kill进入内核,通过pid找到接受信号的进程,并给它的信号队列新增加一个信号 3)每个进程中断返回之前,检查有没有未处理的信号,若有则去...原创 2018-04-26 19:17:13 · 523 阅读 · 0 评论 -
babyos2(17)—— exit, wait
babyos2一个进程跑起来之后一直无法退出,因为fork出一个新进程,并执行exec后,通过中断返回设置的frame->eip进入新进程main入口函数,栈上并无正确的返回地址,所以若进程所有代码执行完成,到末尾return时会发生错误,因为系统下一步不知道该执行哪了。 目前一方面为了测试,一方面为了进程不会挂,init和shell进程都会执行一个while(1)然后定时打印一个字母。如...原创 2018-04-26 19:17:07 · 387 阅读 · 0 评论 -
babyos2(16)—— sleep, wakeup
现在babyos2内核初始化完成后,会启动init进程,这是第一个用户态进程,init会启动shell,目前这些进程都啥事都不干,内核初始化完成后化身为idle进程,一直打印’P’, init进程一直打印’I’,shell一直打印’S’。但这中间的时间间隔都是靠一直死循环一阵子来实现延时的,所以先做了一个简单的sleep和wakeup。 1. list/* * guzhoudiaoke...原创 2018-04-26 19:17:00 · 396 阅读 · 0 评论 -
babyos2(15)—— bug fix 1
完成了基本的内存管理、进程调度之后,因为进程main函数执行完之后,return的时候,栈上没有正确的返回地址,main执行完后将会执行随机的指令导致进程崩溃,所以想先做一个简单的exit,但做完之后,遇到一些问题,比较诡异,甚至虽然现在暂时修改好了,还是不能给出一个确切的解释,在此罗列下:1.去掉一些打印信息后,init 进程fork子进程,子进程调用exec后,子进程又诡异的调用了一次fo...原创 2017-12-24 14:43:43 · 477 阅读 · 0 评论 -
babyos2(14)—— user stack, stack expand, load elf
到目前为止,babyos2用户态栈只分配并映射了一个页,所以当栈的内容超过这个界限时,就会PAGE_FAULT,并且无法处理导致进程halt。先简单验证下:int main(){ uint32 cs = 0xffffffff; __asm__ volatile("movl %%cs, %%eax" : "=a" (cs)); int i = 0; whi...原创 2018-04-26 19:16:40 · 466 阅读 · 0 评论 -
babyos2(13)—— process page table,fork, COW(copy on write)
尽管已经实现了分页,但目前babyos2各个进程使用的还是同一个页表,所以一旦一个进程mmap了一块虚拟地址空间,其他各个进程都是可以使用的,这是不合理的。我们先验证这个现象:unsigned *address;inline void visit_address(){ for (unsigned i = 0; i < 10; i++) { address[...原创 2018-04-26 19:16:33 · 531 阅读 · 0 评论 -
babyos2(12)——pagefault, vm_area, mmap
用户态程序经常需要动态分配一块内存,比如使用glibc的malloc。linux下malloc底层会调用操作系统提供的系统调用,如brk, mmap来跟操作系统动态申请内存。而brk, mmap只是获得了一块虚拟内存空间,当真正访问这些内存时,由于没有物理页,会发生缺页中断,此时操作系统负责寻找一个空闲的物理页面,并跟虚拟地址建立映射关系。 babyos2目前已经拥有了物理内存管理系统(budd...原创 2018-04-26 19:16:27 · 621 阅读 · 0 评论 -
babyos2(11)—— physical memory manage, buddy system
由于babyos2采用了类似于linux的获取current进程指针的方法,这要求process_t的内存按8K对齐,继续采用boot阶段m_start_mem递增的方式就很笨拙了,而要实现后续的vma,虚拟内存管理等功能,一个好用的物理页分配函数是必须的,所以实现了一个buddy system来管理物理内存。#define MAX_ORDER 6#define ...原创 2018-04-26 19:16:20 · 616 阅读 · 0 评论 -
babyos2(10)—— process,schedule,fork,exec,user mode
此前babyos2一直运行在内核态,ring0,使用的是内核代码段、内核数据段。如何能创建用户态进程,进入用户态执行呢?需要从中断说起。中断处理及中断返回如图所示为中断执行流程,首先会判断当前CPU工作模式,我们只关注32位保护模式。首先会检查是否超过IDT表长度限制,或者选中的中断描述符不是中断门、陷阱门、任务门之一,若满足之一,则报一般保护错误#GP。 如果是INT指...原创 2018-04-26 19:16:02 · 718 阅读 · 0 评论 -
babyos2(9)—— system call
如果说外部中断是CPU被动地、异步地进入系统空间的一种手段,那么系统调用就是CPU主动地、同步地进入系统空间的手段。 babyos2通过0x80号中断实现系统调用。void cpu_t::do_common_isr(trap_frame_t* frame){ uint32 trapno = frame->trapno; if (trapno < IRQ_0)...原创 2018-04-26 19:15:55 · 476 阅读 · 0 评论 -
babyos2(8)——IDE hard disk, interrupt
/* * guzhoudiaoke@126.com * 2017-10-29 */#ifndef _HARDDISK_H_#define _HARDDISK_H_#include "types.h"#include "spinlock.h"#include "kernel.h"#define HD_STATE_READY 0x40#define HD_STATE_BUS...原创 2018-04-26 19:15:49 · 921 阅读 · 0 评论 -
babyos2(7)——keyboard interrupt、clock interrupt、real time
babyos2暂时还是使用8259a作为中断控制器,后续可能会尝试使用APIC。/* * guzhoudiaoke@126.com * 2017-11-7 */#ifndef _I8259A_H_#define _I8259A_H_#include "types.h"#define IRQ_0 (0x20)#define IRQ_NUM ...原创 2018-04-26 19:15:41 · 697 阅读 · 0 评论 -
babyos2(6)——IDT,interrupt,exception
babyos2内核开始执行后,会重新设置GDT到一个更安全的位置。同时,为了能处理中断和异常,需要设置IDT。 IDT也是一个表,叫中断描述符表。每个项表示一个中断描述符。 Task Gate,Intel是想用于任务调度的,在此先不描述。 中断门和陷阱门的区别在于通过中断门进入中断服务程序时CPU自动关中断,即将CPU的EFLAGS中IF位清0,防止中断嵌套。而通过陷阱门进入则IF标志位...原创 2018-04-26 19:15:33 · 684 阅读 · 0 评论 -
babyos2(5)——分页
加载elf格式的内核完成后,babyos正式开始执行内核代码,首先要开启分页。 这张图表示了段页式内存管理的基本流程。要开启保护模式,一定会开启分段,而分页是可选的。但现代操作系统,分页也是最基本的功能。 如图所示,左半边展示了分段。进入保护模式之前,我们用lgdt指令加载了GDT,GDT名字叫全局描述符表,它是一张表。每一个表项是一个全局描述符: 它描述了一个段的基地址、限长及一些...原创 2018-04-26 19:15:24 · 572 阅读 · 0 评论 -
babyos2(4)——memory ranges by int 0x15, eax=0xe820
要做内存管理,首先要知道物理内存数量。获取内存数方法有几种,如BIOS,CMOS,访问内存等。babyos2采用的是int 0x15, eax=0xe820的方式。 1.在boot阶段通过BIOS中断获取内存信息:# finnction to get memory info by 0xe820get_memory_info: movw $(BOOT_INFO_SEG), ...原创 2018-04-26 19:15:16 · 619 阅读 · 0 评论