手搓OS-day1

今天进入正式开搓的阶段(霉比 maybe),今天比较大的阻碍还是代码障碍比较大,需要回顾和总结大量的基础,所以会显得人比较菜(其实就是菜),还有一个比较好的调试方式。然后就是对老师口中的玩具的分析(==好难玩的玩具==),从中结合我们学过的基本的操作系统的知识进行结合,体会其中状态机和程序的概念。

Python部分

Generator(函数生成器)

其中的重要关键字yield(生产,生成的意思 考研词汇),代码运行到yield关键字后会自动保存

一个弯弯绕的小栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def number_generator():
for i in range(5):
a=i+10
yield a

def add_generator():
f=0
for i in range(5):
a=i+10+f
print(a)
f=yield a


if __name__=='__main__':
generator_1=number_generator() # 接收生成器对象
for i in range(5):
print(generator_1.__next__())

generator_2=add_generator()
# 直接调用next
next(generator_2)
# 采用send方式
generator_2.send(10) # 按道理这里应该是11,但通过send函数改变f的值后变为21

另外第一次启动生成器是不能使用send方法,会报错:

1
TypeError: can't send non-None value to a just-started generator

对此有两种解决方案: ① 第一次启动是使用next()函数

② 第一次传入send()的值为None

match函数

match语句是 Python 3.10 中引入的一种结构模式匹配的特性,允许在数据结构中匹配复杂的模式。基本形式如下(==这个真挺好用的==):

1
2
3
4
5
match a,args:
case "haha",xs:
print(xs)
case "lala",(f,args):
.....

有一些接受函数返回参数的技巧:

1
syscall,args,*_=self._func.send(self.retval)

*__可以有效的扔掉不想要的变量,保留有效变量

:= 运算符

:=运算符是Python3.10中的新特性,提供在赋值的同时并运算:

1
2
3
4
t:=1+2
# 等价于
t=1
t+2

exec 函数

exec函数是Python标准库中的函数:

1
exec(str,variables)

str是一段代码,exec执行该段代码,将运行后的函数接口传递到variable字典

一个小栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
code = '''
def greet(name):
print(f"Hello, {name}!")

greet("John")
'''

# 执行字符串中的代码
exec(code)

#创建一个全局字典,以方便调用
globals_dict = {}
exec(code, globals_dict)

# 从 globals_dict 中获取 greet 函数
greet_func = globals_dict['greet']

# 调用 greet 函数
greet_func("111")

SYS包

sys,就是system的简写,秉承着用多少学多少的理念我们先补一点,以后遇到了再补(懒狗

1
2
sys.avg #读取命令行中参数
#此外还有常用的path,先摆了

GDB

还是秉承用多少学多少,gdb是一种命令行调试工具,那就意味着没有IDE要用命令行打断点。

可以类比使用IDE的debug,程序在debug的模式下运行,同理在用gdb调试时也就要在gdb模式下调试,步骤如下:

  1. 编译要调试的代码:
1
gcc -g -o tst tst.c

这里要提的是,-g使得能够在栈帧中查看代码和对应行号,具体对于栈帧的描述可以去查一下内存的虚拟映射,

  1. 在gdb下运行:
1
gdb ./tst

运行结果

  1. 然后就可以用gdb指令进行调试了,下面罗列指令并且给出执行效果
1
2
3
4
# 查看代码
list
# 或者
l

ls查看代码

1
2
3
4
# 运行
run
# 或者
r
运行
1
2
3
4
5
6
7
8
9
# 打断点
break n # n为行号 或者用
b n
# 查看断点
info b
# 禁用断点
disable b
# 重新启用
enable b
1
2
3
4
5
# 执行下一条指令,但不进入函数体
next # 或者
n
# 进入函数体
step
1
2
3
# 监视变量值
print # 或者
p

剩下的功能用到再学(咕咕

VScode的一种调试方式

因为要运行一个类似这样的指令

1
python os-model.py hello.py

才能运行整个程序,所以这给调试带来了困扰,因为我并不知道如何在debug的同时输入命令行,这里我想到了两个解决方案:

① 通过再写一个Python文件,通过os包执行指令就可以打上断点(天才),结果就是路径始终对不上

② 如下:

添加配置

添加参数args

这个args就代表的是命令中的参数

1
python xx.py paramter

于是就可以顺利调试了。

OS玩具模型

这里还是简单画个图:

OS模型

简单解释一下,step提供了一个获取运行线程的下一步指令的功能,而run函数提供了一个将下一步指令转化为机器指令(可执行)的功能,而run中也就提供了各种系统调用的接口:比如随机切换线程,线程休眠,读写调用等等。

在实现中采用了一个很精妙的方法,通过对待运行文件的内容读取,并修改其中的系统调用为一个生成器函数,转入OS系统的栈中存储函数入口,然后通过OS运行就得到了运行结果(妙啊~),这里建议大家去看看代码。

Makefile先不写了,用到再写(咕咕

参考链接


今日无