FunCoder

FunCoder

PyOS - 一个Python写的OS(1)

引用自David Beazley的视频PPT

PyOS 这个系列,我们进一步利用协程的特性,一步一步的构建一个多任务操作系统。系列的最后,我们会在我们自己写的PyOS上实现一个 Web Client/Server。

当然,这不是真正的操作系统,而是一个操作系统上的操作系统。。哈哈。完成这个系列可以对并发编程、协程、操作系统多任务管理、IO有更深刻的认识。当然,你还会收货成就感。

对协程不太了解的同学请看:https://zhuanlan.zhihu.com/p/354982602

Read more »

PyOS - 一个Python写的OS(2)

上文我们的PyOS已经可以处理多任务了,而且加入了第一个 OS call:GetTid 来获取任务ID。今天,我们继续开发我们的OS,增加更多的 OS call。

更多 OS call

我们需要增加两个基本的系统函数:NewTaskKillTask 让操作系统进行基本的任务管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class SystemCall(object):
task: Task
sched: Scheduler

def handle(self):
...

# Create a new task
class NewTask(SystemCall):
def __init__(self,target):
self.target = target

def handle(self):
tid = self.sched.new(self.target)
self.task.sendval = tid
self.sched.schedule(self.task)


# Kill a task
class KillTask(SystemCall):
def __init__(self,tid):
self.tid = tid

def handle(self):
task = self.sched.taskmap.get(self.tid,None)
if task:
task.target.close()
self.task.sendval = True
else:
self.task.sendval = False
self.sched.schedule(self.task)
Read more »

重新认识 Python(4)并发模型

并发是什么?

并发一般是指多个计算在时间上无固定先后顺序的执行。并发程序不一定存在并行。举个例子reference:

并发实例

上面的例子中我们有三个任务,T1~3,这三个任务就属于并发执行,而且因为有两个CPU,所以存在一定的并行。左图是每一个任务在CPU核心的执行情况,而右图是从任务自身的时间线角度表达任务的执行情况。可以看到任务通常不是连续执行,而是根据调度情况间断执行。

Read more »

类型系统是什么

类型系统是一个有多个规则组成的逻辑系统,系统内的规则会给程序中的每一个组成部分,包括变量、表达式、函数、甚至模块等等,制定一个 类型 属性。

通俗的讲,类型系统是为了赋予程序或者数据意义。因为任何值或者一个函数,在内存里面都只是一串bits,而类型就是要给这串bits意义。例如,10 是的类型是一个奇怪的 int 类型,这个int只有两位。类型系统会给你加额外的信息让他变成一个 int,01|10,这里我们假设类型占两位,01就是int的bit表达,| 用来区分类型和值。这是,10就有了意义,而且程序在编译阶段或者运行时就可以通过这个类型标识确保采用合法的操作来操作这个值。

换句话说,类型系统形成了一个除了语法(syntax)和语义(semantic)以外的另一套可以用来分析代码的系统。刚才我们也提到了,类型系统属于逻辑系统,就是通过规则(rule)可以进行推到和证明。所以我们可以肯定的说,好的类型系统可以帮助我们从逻辑角度分析程序,减少bug。因为语法和语义其实并没有办法从逻辑层面表达任何关于程序本身要做的事情。而类型系统可以发现一些逻辑错误,至少在他的rule可以推导的范围内。

有些语言只会给变量制定类型,而表达式、函数则没有类型。比如 Python 中,if a == 1: 1 else: 2 这个表达式是没有类型的概念的。而在 Ocaml 中,if a=1 then 1 else 2 这个表达式有类型 int。事实上一般函数式语言的类型覆盖会更加广泛,而过程式语言覆盖则低很多,比如表达式基本都是没有类型的。显然,类型覆盖约广泛,这个逻辑系统能提供的帮助就越多。

Read more »

重新认识Python(3):GIL,Global Interpreter Lock

之前的两个文章主要简述了Python的内存管理模型和对应的GC模型。今天我们来看看Python的另一个“著名”特征:GIL,全局解释器锁。GIL长久以来被各种内行、外行诟病,可是很多人并不清楚GIL究竟是什么?为什么当初要设计GIL?GIL的优势在哪里?

Python 是如何工作的?

要理解 GIL 需要知道一些Python解释器的运行原理。Python的解释器其实一个循环,循环里是一系列的cases,逐行读取编译后的Opcode进行计算,每一个线程都有独立的这么一个循环。这里插一嘴,其实Python不是解释型语言,起码不是纯粹的解释型,Python源代码会被编译成Python自己的byte code,就是上面循环中的那些opcode。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
for (;;) {
assert(stack_pointer >= f->f_valuestack); /* else underflow */
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
assert(!PyErr_Occurred());
// 这部分省略的代码就是后面GIL的关键。。我们先来看看解释器的循环
// ....
/* Extract opcode and argument */

NEXTOPARG();
dispatch_opcode:
switch (opcode) {

/* BEWARE!
It is essential that any operation that fails sets either
x to NULL, err to nonzero, or why to anything but WHY_NOT,
and that no operation that succeeds does this! */

TARGET(NOP)
FAST_DISPATCH();

TARGET(LOAD_FAST) {
PyObject *value = GETLOCAL(oparg);
if (value == NULL) {
format_exc_check_arg(PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg));
goto error;
}
Py_INCREF(value);
PUSH(value);
FAST_DISPATCH();
}

PREDICTED(LOAD_CONST);
TARGET(LOAD_CONST) {
PyObject *value = GETITEM(consts, oparg);
Py_INCREF(value);
PUSH(value);
FAST_DISPATCH();
}
...
Read more »

重新认识 Python(2):内存管理

理解内存管理需要知道通常内存使用的基本规则。一般来说,一个进程的内存会被划分成两个部分,堆(heap)和栈(stack)。栈的结构相对简单,本质上就是一个先进后出队列,所有被分配在栈上的值必须是确定大小的、静态的。栈的功能主要是临时存储函数运行时的参数、临时变量和结果。显然,在程序运行的时候,我们需要产生许多大小不固定且动态的值,比如对象、列表、字典等等,这些数据结构不能直接分配到栈上,因此我们需要堆来存放这些值。相应的,堆的内存空间往往比栈大的多。

而我们通常将的内存管理,本质上是堆管理,不是栈管理。

对象,Object

Python的内存管理主要是针对“一切皆对象”这个设计理念设计的(这里我们仅针对CPython实现展开说明。)。什么是对象,Object?在Python的世界里对象就是任何分配在堆中的值。

Read more »

重新认识 Python(1):GC,垃圾回收

Python是目前受众最为广泛的计算机语言之一,涉足的领域包罗万象:Web,机器学习,数据处理,爬虫等等。使用Python的人群也非常多样, 从专业的程序员到数据科学家。这种现状也导致了一个现象:大家对Python存在很多道听途说来的误解。比如,Python是解释型语言(其实python 还真不是,Python是编译型的,只不过他通过解释器执行编译后的代码,其实跟Java一样的,只不过java用虚拟机执行、解释代码),Python非常慢(讲快慢不讲场景都是耍流氓),GIL是垃圾设计(很多人其实不清楚GIL到底是什么?其设计初衷是什么?), Python的GC很垃圾等等。这些误解通常是因为 Python过于火热,以至于内行、外行都可以随意评论一番,一些误解也就慢慢蔓延开来。我写这个系列的目的就是帮助大家重新认识Python,把 Python当成一个计算机语言,而不是一个工具来认识它。这样不仅会增加对语言本身的理解,也可以提高编写Python代码的质量。

今天我们先来聊一聊Python的GC。(CPython)

Python的内存管理

说GC之前,我们先来看看Python的内存管理。与许多其他语言不同,由于Python中的所有值都是一个对象,object,所以Python程序运行的时候会产生数量众多但是体积很小的对象。因此,Python通常不会把已经申请的内存交还给操作系统,他会为每一个小于512byte的对象分配一个专门的allocator并且不会释放这些内存,方便以后继续使用。Python的很多内存直到进程结束才会释放给系统。

Read more »

SICP quick overview

Building Abstraction with Procedures

The Elements of Programming

Three machanisms of powerful language:

  • primitive expression, the simplest entities the language is concerned with
  • means of combination, compound elements are built from simpler ones
  • means of abstraction, compound elements can be named and manipulated as units
Read more »

2020 年总结

世界

今年对世界很独特。2020年1月,新冠(COVID-19)在武汉首先爆发,3月疫情拓展至美国、英国、欧洲等世界各地。在我写下这篇博客的时候,中国的疫情已经得到了完全控制,而欧洲、美国正处在新兴变种病毒的第三波高峰期。

日新增病例

在新冠疫情的影响下,美股出现了前所未有的崩盘运动。2020年2月到3月之间,标普500期货连熔断三次,跌幅高达40%。

Read more »
0%