CyberRt源码剖析-线程等待策略
1.线程等待策略在base/wait_strategy.h这个头文件中定义了线程切换的策略类:
class WaitStrategy { public: virtual void NotifyOne() {} virtual void BreakAllWait() {} virtual bool EmptyWait() = 0; virtual ~WaitStrategy() {}};class BlockWaitStrategy : public WaitStrategy { public: BlockWaitStrategy() {} void NotifyOne() override { cv_.notify_one(); } bool EmptyWait() override { std::unique_lock<std::mutex> lock(mutex_); cv_.wait(lock); ...
CyberRt源码剖析-常用宏分析
从这篇blog开始,我们来分析百度CyberRt这个高性能的分布式通信中间件
CyberRt的源码组成如下:
base文件夹是Apollo开发的高性能基础库,我们先从这个文件夹里的代码看起:
从文件命名中可以看见实现了与线程相关的如线程池、锁、无锁队列、哈希表等等基础组件,我们就开始从零造轮子吧
1.c++前置知识std::nothrow(std::nothrow) 是在C++中用于进行内存分配时的一种选项。通常,当你使用 new 运算符创建对象时,如果内存分配失败,new 会抛出 std::bad_alloc 异常。但是,当你希望在分配失败时不抛出异常,而是返回一个空指针,你可以使用 (std::nothrow) 作为参数传递给 new。
具体来说,使用 (std::nothrow) 会使得 new 在分配失败时返回一个空指针而不是抛出异常。这样,你可以在分配失败时通过检查返回的指针是否为空来处理错误,而不必使用异常处理机制。
以下是一个示例:
#include <iostream>int main() { // 尝试分配一个非常大的数组,可能导致 ...
riscv编译工具链构建说明
riscv编译工具链构建说明构建riscv-gnu-toolchain有几种方式:
第一种是直接下载源码然后本地编译,然后 make install
第二种如果使用的是ubuntu20,可以直接使用 apt 安装
第三种就是下载别人已经编译好的文件,然后解压,配置一下工具链路径
编译器有这几种类型,以64位的编译器为例子,三种不同类型编译器的区别后面会说明
riscv64-linux-gnu-gcc
riscv64-unknown-elf-gcc
riscv64-unknown-linux-gnu-gcc
源码构建riscv-gnu-toolchain的官方仓库在:riscv-collab/riscv-gnu-toolchain: GNU toolchain for RISC-V, including GCC (github.com),下载上面的源码,然后按照官方提供的编译命令进行编译安装,但是绝大多数时候是编译不过的,因为官方的源码依赖种的第三方文件我们下载不下来,有一个解决办法就是去gittee镜像上去把对应的包下载然后放进源码种,这样编译是能成功。关于如何在gi ...
手写STL之List
代码仓库:yanglianoo/My_STL at timer (github.com)
1.List概述C++标准模板库(STL)中的list是一个双向链表容器,提供了在链表中高效存储和访问数据的功能。它是一个模板类具有以下特性:
链表结构:list是由节点组成的链表,每个节点包含数据以及指向前一个节点和后一个节点的指针。这种结构使得在list中插入、删除和移动元素非常高效,因为不需要像动态数组那样进行内存的移动和重分配。
双向访问:list支持双向访问,可以从链表的开头或末尾快速访问元素。你可以使用迭代器进行正向或反向遍历,也可以使用front()和back()函数访问第一个和最后一个元素。
动态大小:list的大小可以动态增长或缩小,无需预先分配固定大小的内存。
插入和删除:在list中插入和删除元素非常高效。通过使用迭代器,可以在常数时间内在任意位置插入或删除元素。
不支持随机访问:list不支持通过索引进行随机访问,这意味着不能像数组那样使用索引来访问元素。如果需要随机访问,vector可能更适合。
没有连续存储:由于list是一个链表,它的元素在内存中不是连 ...
计算机系统基础-存储访问
1.存储器使用场景先来看如下这一张图,CPU运行程序的流程如下:
1:假设我现在在电脑上编译了一个hello.c的程序,编译完成后为hello.bin的一个二进制文件,此时这个程序还存储在我们电脑的硬盘上,这个硬盘可能是机械硬盘也可能是固态硬盘,这些都是外存储器。
2:将hello.bin装载进内存,这里的内存就是插在电脑上的内存条,hello.bin包含了cpu要执行的指令和运行所需要的数据。
3:CPU从内存中逐条读取指令及相关指令,然后依次执行完成对数据的处理。
4:将处理结果送回内存保存,然后再将处理结果送到外存储器。
所以其实在CPU运行的过程中主要是分为两类存储器:
内存储器
存取速度快
成本高、容量相对较小
直接与CPU连接,CPU对内存 中可直接进行读、写操作
属于易失性存储器(volatile), 用于临时存放正在运行的程序和数据,掉电就没了数据。
外存储器(简称外存或辅存)
– 存取速度慢 – 成本低、容量很大
– 不与CPU直接连接,先传送到内 存,然后才能被CPU使用。
– 属于非易失性存储器,用于长久存放系统中几乎所有的信息
这里可能会有 ...
设备树详解
1.设备树简介传统上,操作系统内核会直接编译进所有支持的硬件设备的驱动程序。但是,随着硬件设备的不断增多和变化,这种方法变得不够灵活。设备树的引入解决了这个问题。设备树将硬件的描述信息以一种结构化的方式存储在单独的文件中,然后在引导过程中由操作系统内核加载和解析。
设备树文件使用一种称为”Device Tree Source”(DTS)的语言编写,它是一种人类可读的文本格式。该文件描述了硬件设备的层次结构、寄存器地址、中断线路、DMA通道和其他相关属性。这些信息对于内核来说非常重要,因为它们允许内核正确地初始化和配置硬件设备。
设备树文件经过DTC编译后会生成一种称为”Device Tree Blob”(DTB)的二进制格式。DTB文件在引导过程中由引导加载程序(Bootloader)提供给内核。内核会解析DTB文件,根据其中的描述信息初始化硬件设备,并加载相应的驱动程序。
设备树的作用在于用来描述一个具体的硬件平台的硬件资源,如果没有设备树,当我有一个新的硬件平台时,在移植操作系统时需要去修改源码去适配这个具体的硬件平台。有了设备树之后,bootloader就能直接从设备树中获取硬件 ...
从源码构建Qemu
1.Qemu介绍QEMU(Quick Emulator)是一个开源的虚拟化软件,它可以模拟多个硬件平台,包括处理器和外设,从而允许在一个平台上运行多个不同的操作系统。QEMU可以运行在多个主机平台上,包括Linux、Windows、macOS等。
QEMU的主要功能是模拟一个完整的计算机系统,包括处理器、内存、存储器、网络接口等,它可以将客户操作系统(例如Linux、Windows等)当作应用程序运行在主机操作系统之上,从而实现虚拟化。QEMU还支持通过二进制代码转换的方式实现虚拟化加速,例如使用KVM(Kernel-based Virtual Machine)模块加速虚拟机的运行。
QEMU可以用于多种用途,包括:
系统仿真:可以模拟不同的处理器架构(如x86、ARM等)来运行和测试操作系统和应用程序,方便开发人员进行交叉平台开发和调试。
虚拟机:可以在一个物理机上运行多个虚拟机实例,每个虚拟机可以运行不同的操作系统,实现资源的隔离和共享,提供虚拟化环境。
可移植性:QEMU可以将一个操作系统或应用程序打包成一个虚拟机镜像,这个镜像可以在不同的平台上运行,提供了一种便携式的软件分发 ...
操作系统-3.实模式
1. X86cpu工作原理
程序计数器PC存储了下一条要运行的指定的地址,在x86cpu上,PC就是:cs:ip,控制单元读取ip寄存器中的地址后,将此地址送上地址总线,cpu由此得到了要执行的指令,然后将指令存入指令寄存器IR中。下一步指令译码器将此指令解码,解码后得到了操作数和操作码,于是操作控制器OC就给运算单元下令,运算单元就开始执行指令。ip寄存器的值被加上当前指令的大小,由此循环。
IA32的指令格式如下:
2. 实模式的寻址8086的地址总线是20位宽,意味着寻址范围为:2^20=1MB,但内部寄存器都是16位的,若采用单一寄存器来寻址只能访问:2^16=64KB空间。
为了解决16位寄存器不能寻址20位的问题,因此通过先把16位的段基址左移四位变成20位后,在加上段内偏移地址,这样就形成了20位地址,只要保证了段基址是20位的,偏移地址是多少位就不用关心了。
下面列举一下寻址实例:所有的利用寄存器寻址的方式,每个寄存器都有对应的段基址,寄存器的默认段基址见上一章
直接寻址(Direct addressing):
MOV AX, [0x1234]mov ax, [ ...
操作系统-2.X86寄存器详解
1.什么是寄存器寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果以及一些CPU运行需要的信息
x86架构CPU走的是复杂指令集(CISC) 路线,提供了丰富的指令来实现强大的功能,与此同时也提供了大量寄存器来辅助功能实现。寄存器分为两类,一类对程序员不可见,这一类寄存器用于支撑CPU内部运行,程序员无法操作。一类对程序员可见,在进行汇编编写程序时,能够直接操作。
通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
标志寄存器:EFLAGS
指令寄存器:EIP
段寄存器:CS、DS、ES、FS、GS、SS
控制寄存器:CR0、CR1、CR2、CR3、CR4
调试寄存器:DR0、DR1、DR2、DR3、DR4、DR5、DR6、DR7
描述符寄存器:GDTR、IDTR、LDTR、TR
2.实模式下寄存器(16bit)在x86架构下,实模式可以使用的通用寄存器有 AX、BX、CX、DX、SI、DI、BP 和 SP。这些寄存器都是16位的,可以分为两个8位的寄存器来使用。
此外,还有一些特殊用途的寄存器,包括:
IP(指令指针寄 ...
操作系统-1.概述
1.环境配置
开发环境:
ubuntu20.04.5 WSL
sudo apt install nasm: 安装汇编编译器 nasm
sudo apt install bochs-x: 安装虚拟机 bochs
sudo apt-get install qemu-system :下载安装可以模拟全部硬件的qemu
sudo apt install gdb :安装gdb调试器
sudo apt-get install gcc-multilib&&sudo apt-get install g++-multilib: 安装在64位的机器上产生32位的程序
参考书籍:
操作系统真相还原
30天自制操作系统
Orange’S:一个操作系统的实现
源码地址:yanglianoo/Onix: 基于X86的操作系统,C语言 (github.com)
2.操作系统大纲
系统引导
自写bootloader
grub 引导
硬件及驱动
CPU : 32位X86架构
显示器:VGA
中断控制器:8259A
键盘
硬盘
时钟:内部时钟,外部时钟
网卡
任务调度: ...