
计算机科学
文章平均质量分 76
小白起步
每天都要学到新东西
展开
-
程序与CPU
CPU程序是什么程序 = 指令 + 数据 程序: 将一些数据和指令由上而下进行排列,有某种规律的执行,这个过程叫做程序。CPU的组成寄存器: 寄存器是用来存储数据的 相当于CPU中的内存 控制器: 将内存或者寄存器的数据进行读取,写入的操作 运算器: 逻辑运算单元 时钟: 运算频率寄存器累加 ==> 做运算的标志 ==> 存储状态,进行逻辑判断程序计数 ==> 存储下一条指令地址基址 ==原创 2017-08-03 09:41:33 · 517 阅读 · 0 评论 -
filesystem2
在前面一节中介绍了文件系统的基本概念,接下来就要准备开始实现我们的文件系统,下面是为管理文件系统提供的几个基础数据结构。超级块的结构/* 超级块 */struct super_block{ uint32_t magic; // 用来标识文件系统类型,支持多文件系统的操作系统通过此标志来识别文件系统类型 uint32_t sec_cnt; ...原创 2018-05-19 17:35:20 · 236 阅读 · 0 评论 -
filesystem3
文件描述符在之前介绍的概念中,inode是用来表示一个文件的,用于描述文件的存储信息,文件的权限等。但这个inode结构是操作系统为自己的文件系统准备的数据结构,仅供其内部使用,与用户的关系不大,接下来要介绍的文件描述符才是用户能够使用的结构。在linux系统中,读写文件的本质是先通过文件的inode找到文件数据块的扇区地址,随后对这些扇区的数据进行读写,从而实现了文件的读写。对用户进...原创 2018-05-19 17:35:57 · 337 阅读 · 0 评论 -
十八. 文件系统四(文件的读写与删除)
写入文件文件的数据都是记录在inode中的文件块中,在该文件系统的设计中,只用了12个直接块和一个间接块来存储文件,所以一个文件最大可以存放 140 * 512字节的数据。写文件的过程对文件块和扇区的分配过程,根据当前要写入的数据量大小,来判断是否需要分配新的数据块。如果12个直接块不够存储该数据,就分配间接块来存储,当所需的数据块分配好了之后,就会逐块的往硬盘上写入数据,知道所有的数据被...原创 2018-05-19 17:36:33 · 1051 阅读 · 2 评论 -
shell
fork的原理先通过下面这段代码简单的介绍一下fork这个函数,了解一下它的功能#include <unistd.h>#include <stdio.h>int main(){ int pid = fork(); if (pid == -1) return -1; if (pid) { ...原创 2018-05-19 17:37:46 · 197 阅读 · 0 评论 -
shell1
路径解析转换路径有绝对路径和相对路径之分,在平常使用linux的过程中,我们在输入命令和参数的时候,往往使用的都是相对路径。相对路径是基于当前的工作路径的出的。当前工作路径 + 相对路径 = 绝对路径比如说当前工作路径为 /home/work 此时输入 ls file,那么file所在的绝对路径就是 /home/work/file 了。因为这个kernel比较简单,如果路径以根目录...原创 2018-05-19 17:38:28 · 249 阅读 · 0 评论 -
二十一. elf文件格式解析
elf文件格式我们的程序是通过gcc编译的,在linux下,gcc编译出来的可执行文件是elf格式的二进制文件。那么肯定要elf文件进行解析才能正确的得到进程可执行数据的位置。下面介绍一下elf格式的几个基本概念一个程序中最重要的部分是段和节,他们是真正的程序体,存储程序执行所需要的数据,程序中有很多段,常见的有代码段和数据段,段是由节组成的。多个节经过链接之后被合并成一个段。段和...原创 2018-05-19 17:39:27 · 1621 阅读 · 0 评论 -
pipe
进程同步看一下上一节写的调用外部shell的方法。memset(final_path, 0, sizeof(final_path));int32_t pid = fork();if (pid){ while(1);}else{ make_clear_abs_path(argv[0], final_path); argv[0] = final_pa...原创 2018-05-19 17:41:51 · 566 阅读 · 0 评论 -
十一. 线程同步
乱序输出前面完成了多线程之后,那么肯定会涉及到线程的同步问题。因为线程的执行是随机的,乱序的。虽然我们这个小kernel实现的调度器算法比较简陋,它的随机性没那么强,但是每次进行线程切换的时候,还是有可能产生问题。并且问题已经产生了。int main(void){ put_str("I am kernel\n"); init_all(); thread_start("thr原创 2018-05-07 06:13:28 · 227 阅读 · 0 评论 -
十三. 实现系统调用
系统调用简介关于系统调用前面有过简单的介绍,这里将真正实现系统调用现代的操作系统中,用户的权限是有限的,它不能随意的访问系统中的资源。操作系统屏蔽了用户直接访问硬件的能力,这样做的原因主要是为了安全考虑。但是如果我们想控制显卡打印字符怎么呢,那就需要通过操作系统提供的接口来完成了,我们调用操作系统提供的接口,然后操作系统去操控硬件,比如说这里的显卡,打印出字符来。我们使用的c语言里面的printf函原创 2018-05-07 06:14:20 · 355 阅读 · 0 评论 -
十二. 实现用户进程
TSS单核CPU想要实现多任务,唯一的方案就是多个任务共享同一个CPU,也就是让CPU在多个任务间轮转。CPU执行任务时,需要把任务运行所需要的数据加载到寄存器、栈和内存中,因为CPU只能直接处理这些数据,这是CPU在设计上就直接决定的。任务的数据和指令是CPU的处理对象,任务的执行会占用寄存器和内存。内存相对于CPU来说是低速设备,里面的数据往往被加载到高速寄存器之后被CPU处理,再将结果写到内存原创 2018-05-07 06:15:40 · 459 阅读 · 0 评论 -
filesystem
磁盘的基础概念扇区:它是磁盘读写的基本单位。在我们个人的pc上,他的大小通常为512byte块:在windows中,称为簇。一个块由多个扇区组成,磁盘在进行读写数据的时候,不可能有一扇区的数据就读或写一次,而是等数据累计到一定量后,在统一进行读写,而这个数据量就叫块。在对磁盘进行格式化分区的时候可以选择块的大小,默认的是4kb。因为每次进行读写的数据量都是一块为单位,所以在磁盘上数据的存储...原创 2018-05-19 17:34:40 · 6728 阅读 · 0 评论 -
malloc&free
之前的内容中已经实现过内存分配的功能,但之前的内存管理模块中只是实现了内核空间的内存分配,而且每次分配的空间都是已页为单位,也就是只能分配页的整数倍的空间。已页为单位的内存确实是最利于操作系统管理的,但是当只需要小块内存区域的时候,之前的内存管理模块就无法完成了。所以在这里要完善之前的内存管理模块,使其能够支持小块内存的分配。有了底层的内存管理模块的支撑之后,malloc和free的实现就非常容易...原创 2018-05-19 17:33:58 · 361 阅读 · 0 评论 -
八. 内存池规划
bitmap简介计算机中一些资源的数量非常庞大,比如内存容量和硬盘容量。为了使用这些资源,必须涉及到一套管理这些资源的方法,而方法中必须要构建数据结构来存储管理数据,这些数据本身也是需要占用内存的计算机中最小的单位是位,那么用一组二进制位串来管理其他单位大小的资源是很自然的,这组二进制位中的每一位与其他资源的数据单位是一一对应的关系,这实际是一种映射关系,于是这组二进制位便有了一个名字—-位图位图与原创 2018-04-27 19:34:15 · 305 阅读 · 0 评论 -
内存
内存内存的分类ROM: 只读 RAM: 可读写内存RAM分两种: DRAM 动态RAM(Dynamic RAM) 动态随机存取存储器,需要不断的刷新,才能保存数据.而且是行列地址复用的,许多都有页模式SRAM 静态RAM(Static RAM) 静态的随机存取存储器,加电情况下,不需要刷新,数据不会丢失,而且,一般不是行列地址复用的内存中的数据断电即消内存的物理模型内存的逻辑模原创 2017-08-03 10:59:34 · 264 阅读 · 0 评论 -
磁盘
目前硬盘的运行速度还是以MB在进行运算,它的速度远远低于CPU和内存硬盘的物理结构硬盘是以扇区的方式进行管理的. 以簇为单位进行读写 簇不是固定的大小 一般的, 1簇就是1扇区 1扇区是512字节 如果一个文件是2byte, 那么这个文件存储后是512byte 因为最小单位就是1簇 1簇不能存储2个不同的文件, 否则会导致一个文件不能正确读取.磁盘缓存磁盘缓存是为了减原创 2017-08-03 12:24:22 · 268 阅读 · 0 评论 -
操作系统
操作系统在操作系统没有出来之前,我们写的程序只能在一种或者一类电脑中运行.因为那个时候不同电脑之前的硬件是不一样的.1. 克服硬件的差异让我们能更好的驾驭我们的软件,我们只需要关注与操作系统的通信不用再分别对不同硬件进行处理.2. 提供统一的应用程序接口提供了一套标准化的东西, 也就是API.软件最终是通过操作硬件来达到功能的.通过操作系统提供的接口, 我们不在需要了解各种硬件参数和品牌原创 2017-08-07 09:35:22 · 416 阅读 · 0 评论 -
二. 编写mbr,让机器启动起来
mbr简介大家都知道,在我们按下电脑电源的时候,首先启动的BIOS(基本输入输出系统),那么BIOS又是如何被启动的呢,谁来唤醒他呢,它又在何处运行呢。要了解这些的话,首先得介绍一下我们实模式的内存布局实模式的内存布局图中的内容我们现在只需要关注红色框出来的地方,可以看到BIOS的入口地址处只有16BYTE的空间,很显然,这一小块空间肯定存放的不是数据,只能是指令了,图中也写的很明显了jmp f0原创 2018-04-23 15:36:48 · 2172 阅读 · 0 评论 -
三. 保护模式
实模式与保护模式下的分段机制程序想要在计算机上运行,就必须将源代码编译链接成二进制的可执行文件之后才可能被操作系统加载执行。如果在加载的过程中,程序的地址都是绝对的物理地址,那么程序就必须放在一个固定的地方,那么拥有两个相同地址的程序就只能运行一个了。于是,分段机制就产生了。让CPU通过 段基址:段内偏移 来访问任意内存,这样程序就可以实现重定位。也就是说,段内偏移相对于段基址是不变的。无论段基址是原创 2018-04-23 15:38:54 · 1055 阅读 · 0 评论 -
四. 获取内存容量
前言在前面一篇文章中介绍了进入保护模式的方法: 1. 打开A20 2. 加载gdt 3. 将控制寄存器cr0的pe位置1 通过这三步成功的进入到保护模式下,但是在进入保护模式之前,还需要对进行内存的检测工作,启动分页机制等等,最后还要将内核加载到内存当中。这些是之前没有完成的,接下来就要完成这些进入到保护模式之前的准备工作获取物理内存大小在linux中,获取内存容量的方法有很多种,比如det原创 2018-04-23 15:40:13 · 773 阅读 · 0 评论 -
五. 开启分页机制
为什么有进行内存分页目前我们的小kernel还一直在分段机制下工作,因为还只有一个loader在内存中跑,所以不会出现内存不足的问题。假如说此时未开启分页功能,而物理内存空间又不足了,如下图此时进程C想要执行,但是内存空间已经不足。要么就等待进程A或者进程B执行完成,这样就有连续的内存空间了。要么就讲进程A的A3段或者进程B的B1段换到硬盘上,腾出一部分空间,同样可以容纳进程C执行等待是极其不好的用原创 2018-04-23 15:49:40 · 528 阅读 · 0 评论 -
七. 中断
简介中断是指CPU获知了计算机中发生的某些事,CPU暂停正在执行的程序,转而去执行处理该事件的程序,当这段程序执行完了之后,CPU继续执行刚才的程序。通过中断可以极大的提高CPU的执行效率,如果没有中断,在处理器与外部设备通信时,他必须在向该设备发送指令后进入忙等待,反复轮询该设备是否就绪,这样就浪费了大量处理器的执行周期。引入中断之后,当处理器发出设备请求后就可以立即返回处理其他任务,而当设备动作原创 2018-04-23 15:50:53 · 435 阅读 · 0 评论 -
六. 函数调用约定与系统调用
函数调用约定调用约定从字面上理解,他是调用函数的一套约定。主要体现在一下三个方面 1. 参数的传递方式,参数是存放在寄存器中还是栈中 2. 参数的传递顺序,是从左到右传递还是从右到左传递 3. 是调用者保存寄存器环境还是被调用者保存在进行函数调用的时候,函数所需要传递的参数往往是不固定的。在计算机中并没有专门储存参数的硬件,因为参数的不确定性,该硬件的容量并不好确定,而且如果传递参数的过程中,原创 2018-04-23 15:52:14 · 475 阅读 · 0 评论 -
九. 内核的内存分配
前面已经准备好了内存池,这里就要正式实现内存的分配了。因为到目前为止,还没有用户进程,所以这里只实现内核中的动态内存分配。内存分配的过程如下: 1. 在虚拟内存池中申请n个虚拟页 2. 在物理内存池中分配物理页 3. 在页表中添加虚拟地址与物理地址的映射关系接下来就是一步步完成这三步申请虚拟页// 在虚拟内存池中申请pg_cnt个虚拟页static void *vaddr_get(enum原创 2018-04-27 19:33:05 · 421 阅读 · 0 评论 -
十. 内核线程
实现线程函数观察一下这段c语言代码void threadFunc(void *arg){ printf("thread function\n");}int main(){ printf("main function\n"); _beginthread(threadFunc, 0, NULL); return 0;}这里只是举个简单的例子,没有考虑错误处理和资源回收。在原创 2018-04-30 00:00:58 · 300 阅读 · 0 评论