0%

一、闲谈

在我进入大学的新同学介绍会上,有个同学说她来自贵州,我想了想,贵州是广西的省会啊,原来是广西人啊!让我尝试为自己辩解一下,这种事情并不能全部怪我,贵州以“州”结尾,除了贵州以外,没有任何一个省份是以“州”结尾的,相反,“广州、潮州、雷州、惠州”都是以“州”结尾的城市。

我一个学过初中地理的人,居然还能把一个省份当成一个城市,多么愚蠢可乐的事情。在我的认知中,贵州是完全缺位的,我不是对它有一个好印象或者一个坏印象,我是完全没有印象。

image-20240124195100752

而实际上贵州是真实存在的,从某个我记不住名字的版块运动开始,随着喜马拉雅山破海而出,贵州就存在了。我在贵阳的博物馆里看到了保存完好的化石,看到了各个民族的文化,我看到的东西并不比我熟悉的东西少了分毫。这种真实的,冒着热气的,在我眼前的庞然大物,居然默许了一个仅有二十多年渺小灵长类的忽视。

Read more »

一、编译原理

在我一开始接触内联汇编的时候,我已经略懂编译的原理了,而这更让我困惑,比如说像这样的内联汇编:

asm volatile("lw a0, 0(%0)"
    :
    : "r"(addr));

会改写寄存器 a0 的值,那如果 a0 原先就被程序中的某个变量占用了呢?那岂不是会造成原来那个变量所参与的行为发生错误?同时 addr 需要被放到一个寄存器中(我们称之为 rx),而 rx 如果之前也被占用了呢?,为了把原来在内存中的变量搬运到 rx 寄存器中,是不是也会

其实内联汇编并不是生硬地将 lw a0, 0(rx) 直接插入到代码里,因为这样确实会因为上述的原因导致程序错误。在实际情况中,内联汇编在编译角度应该被理解成一个类似于函数调用的处理逻辑。也就是说,如果内联汇编中用到了 a0 ,那么在内联汇编前就会有一个机制保存 a0 ,而在内联汇编后则有一个机制恢复原本的 a0 。也就是和“调用者保存寄存器”的逻辑是一样的。

Read more »

一、总论

这篇博客会从一个初学者的视角去积累一些科研中的常见“名词”,希望可以借此达到一个科普和入门的目的。

事实上我也没法以不是“非初学者”的视角去写,因为事实上我也刚知道这些东西不到一个上午。所以可能会有一些错误或者偏颇的地方,还望大家见谅。

此外因为我本人是做系统的,所以可能 AI 等方向我并不清楚,在下面的文章中也不会涉及。

二、实体

Read more »

一、抽象层次

1.1 User Program 与 Operating System

一开始的用户程序 User Program 都是裸机程序,他们直接运行在硬件上。这种方式的缺点在于,任何程序都需要思考与其他程序的“共存方式”,内存空间的是具象的,所以就要思考自己要利用多少的内存,利用哪个部分的内存;CPU 是具象的,所以就要思考自己何时会被调度,以怎样的形式被调度;所有的硬件资源都是具象的,所以要思考的事情数不胜数。

正因如此,操作系统 Operating System 提供了一层抽象,OS 将原本的硬件资源全部进行了抽象表达,具象的硬件资源被操作系统接管,不再提供给用户程序具象的硬件资源,而是提供给用户抽象的“系统调用”,系统调用是操作系统提供的一种硬件资源的封装形式,用户程序使用系统调用来完成使用硬件资源的功能。

抽象的硬件资源相比于具象的硬件资源,其好处在于抽象资源要更加简单,内存空间变成了虚拟内存空间,不再有“有限”或者“非独占”的困扰;外存变成了文件,不再有复杂的驱动或者定位问题;CPU 的调度被简化成了线程的调度,由 OS 进行统一管理,再也不用思考与其他进程共享 CPU 的问题,所有的硬件资源都被抽象的十分简单,使得开发者不再需要考虑与设计本身无关的问题。

Read more »

一、循环依赖

在 C 和 CPP 这种有 include 机制的语言中,当项目复杂时,很容易出现一种头文件相互包含的错误,如下所示:

A.h 内容如下:

#ifndef _A_H_
#define _A_H_

#include "B.h"

class A
{
    B* pb;
    void doSomethingA() {
        pb->method();
    }
};

#endif // _A_H_

B.h 内容如下:

Read more »