计算机学科中有很多概念, 例如编码(原码,补码,反码), 虚拟内存, 文件, IO, 编译,链接,分组交换,关系, 事务,范式, Hash, 加密。。。等等,本文试图讲一下最重要的核心集合,从这个集合当中就可以变换出计算机编程的各种魔法。) s! H* o; R( ` G! L0 \
/ J$ P' `: Q, I% A 一、冯·诺依曼结构计算机的原理
; \3 O$ K' A" P, P( U# c; ?
: w- x+ R0 W( Y6 ? 所有的计算机语言,不管是Java, Python, Go, C, C++, PHP...... , 无论你在TIOBE上是排行第一还是排行第100, 无论看起来多么花哨,功能多么强大,用起来多么舒服, 最终都要变成基本的二进制指令,老老实实地在冯·诺依曼结构计算机上按规矩执行。
5 s! U8 i/ z4 e% k- I9 b T R4 p$ W: o: j) F( D' Z4 a; ?8 d' M
这里是根, 我们看到的、用到的都是这棵树上的花和枝叶。+ u2 v6 {5 k! h
# {! I) a# S) y0 T5 e
作为志向远大的、有着强烈好奇心的年轻人, 难道你不想到根部来看一看?#j324:, P1 [2 I7 f6 n# c- Z; x" w
- i+ C2 ^' \, b. v8 T2 D 作为最基本的要求, 必须要了解CPU和内存这俩哥们是怎么亲密无间工作的: CPU从内存取出指令,进行译码和执行,执行时从内存中取出数据放到寄存器中, 进行计算, 然后把结果写回到内存。如果是跳转指令, CPU则取出跳转目的地的指令继续执行。& k8 s. U$ h9 T2 s7 b" h/ t7 {6 ]$ v
! f# J/ B1 U8 g 如此简单的过程,竟然组成了多姿多彩的电脑世界: 你可以听音乐,玩游戏、上网聊天、用Word来写文档..... 当然看起来微不足道的一个操作,进入到CPU和内存中都可能需要成千上万条指令来完成。. Z, u# J1 { E6 J8 a- @
' `$ Q% y* t0 G. u9 j 这些基本的指令组成了顺序、循环、分支等基本的程序结构,形成了更为强大的编程语言的基础。! m; J4 ]. F' ~" Z
8 f: A; K2 J1 @ CPU和内存、硬盘等设备的速度不匹配,是冯·诺依曼结构计算机的一个核心问题,为了解决这个问题,科学家们绞尽脑汁,想尽了办法, 又引出了一堆概念: 缓存,DMA, 同步,异步,阻塞....
, \8 e2 t* {# p8 @9 z4 r3 ~/ ~
1 ~) U& q/ |1 A; c- ^9 i3 r 书籍:《编码》 《穿越计算机的迷雾》! a! i0 e8 P( S" L
: t1 `, W0 t1 z4 a6 Y
二、进程和线程( m" @, K# s3 [" H& q
; m6 a! S) g: `; m" X) x- d& C' b 这俩家伙的重要性不言而喻,因为你写的所有的程序要么会成为一个独立的进程去执行,要么是被一个进程中的线程收编,没有例外 。
7 u! h9 O$ C8 T K7 z u- m
6 }7 n6 s# a$ a+ J4 r6 \% `+ z% d 几乎所有的编程语言都会涉及到对多进程或者多线程编程的支持, 特别是多线程的并发编程, 所以你必须得搞明白它的本质是什么。3 o) L2 _: ]3 ^8 N% U
0 g) z8 ]6 x* b9 s3 w8 l+ Y+ S 进程是对一个运行中的程序的抽象,没有这个概念,我们是无法实现一边听歌、一边上网的惬意生活。
& `0 `+ C9 u( C0 S# B) d2 _8 I" z' Q4 U: q. q2 t# Y$ X# f
对于CPU来讲, 它只是“浑浑噩噩”地从某个地方取指令,译码执行,但是它不会意识到在某一刻整个世界已经变了天, 它执行的程序已经发生了切换,另外一个程序(准确地讲叫进程)已经成功地抢班夺权。3 Z' X0 ?$ ~: P Y
* F# R7 J+ Y" |1 Y; G
每个进程都有一个被操作系统老大维护的进程控制块, 里边保存了这个进程在运行时的重要信息,是进程能来回切换的重要保证。
' H2 M( K3 q8 q& H( \( j! s% Z, {2 z/ `" m, d( h e
而线程则寄居于进程之内 , 共享进程提供福利(代码和数据)的同时, 还拥有自己的一亩三分地。) D+ Z) K5 w, `) ]1 p3 t& L
" y* f5 [! e" ]8 z9 V
* w/ d) o. {% A6 V& K4 A 线程的出现,提升了系统的性能、吞吐量和响应性。 但是多进程/多线程编程也带来了一系列问题: 同步,通信,锁, 死锁。。。
4 G' Y3 b( g$ |* q) g
/ @8 ~$ c- w' ~* i9 {5 i% I# W) ~ 扩展阅读:( z+ O% _- q! S$ o6 i. n
《我是一个进程》2 a& W2 C8 x: Y7 m9 f( A' K" |
《我是一个线程》
. U% M- F, O" ]; Q# @5 n& ? 书籍:《操作系统概念》
* D j: G3 {2 y2 W& @" Q. v6 U
. a* I/ C( c' j 三、虚拟内存
( a1 V8 D) L! Y, }
: k6 \6 R( J# t+ w4 L 有了物理内存, 为啥还有虚拟内存?一个重要的原因就是给各位进程先生提供一个由虚拟地址组成的独立王国,给他们造成一种假象:我最重要,我是独占内存的!
, T' T; s+ f* S% _- n
) r! Q4 ^ N. h# ]( n' r 每个人在自己的独立王国里闹腾,就不会互相打架, 治安也就有了保证。
; d! `' U& O% |& f- r/ O a9 H
. o! a* }% D9 p( L: K" Q 但是在虚拟地址王国里做不了什么事情,指令必须在物理内存中才能被执行,操作系统老大用尽浑身解数,把每个进程的虚拟地址映射到实际地址上去,表面上不动声色,背后绝对惊心动魄,分段,分页,页表,还要动用CPU的TLB来加速。. ^- J5 c2 y/ t- K- T$ h
) t3 u' h' U. [- R3 Z. d. `4 { 程序并不是像你想象的那样,一下子全部装载到内存的, 而是慢慢地, 用到的时候才进行装载。
4 R( l' _( ]7 p! R* M; F
0 h: |9 k- o% j! J, E, r 进程一条普通指令的执行, 其实有一大家子在鞍前马后地忙碌着, 而进程几乎浑然不觉,真是太幸福了。1 A' C/ a, ]4 L$ t3 q* K5 m
& i( S1 y2 U6 g. ]; [- ~3 o
扩展阅读:
9 f1 Q/ f" { _0 v 书籍《深入理解计算机系统》, 《操作系统概念》
1 b" i+ p# l4 D9 q& r: H# R% n; T" {$ g1 l
四、网络的核心概念
7 p7 `2 O! N" v; R+ T: n) j0 o3 X4 z! H/ b1 P
上面所说的都局限于一台计算机, 然而一张大网早已经把这些孤岛联系在一起。这张大网就你我的周围, 我们都变成了它的一个节点。
$ A3 ~+ v; k& L: B X& m
2 {; u% H+ ~$ j$ ~5 B/ _ 大网的设计非常有趣,没有一个中心的节点,某几个甚至某一片节点阵亡都没有关系,大网继续生存,提供服务。作为码农我们要理解的核心概念是: 分组交换, TCP/IP参考模型, socket , http(s)。- h* ]# Z7 U8 K4 d) U$ b8 j/ G- H
8 W; R0 z: @9 H _! _
你也许没有想到,你上网玩游戏,听音乐,看这篇文章,其中的数据并不是一下子全发给你的, 而是被切分成适合网络传输的小块,给每个小块编上号, 每个小块都独立地走相同甚至不同的网络路径, 到达你这里,重新排序,组合,然后才展示给你, 这就是分组交换。
, U1 G3 N r/ F5 l+ { t
6 K# k$ ]9 J8 B) W; V' S. M 使用分组交换可以充分的利用网络带宽: 在你不使用的间隙,别人也可以利用。
3 x+ W& L s6 X* j3 O
" M9 X/ ?$ D4 I- V$ B 但是一个很明显的问题就是分组数据丢失了怎么办? 如何检测, 怎么重发,如何缓存已经收到分组数据等一系列烦人的问题接踵而来。 这就是TCP要干的事情。
/ R q% D: h4 w' K7 g3 R. r }) n+ [) ^# M
如果你能体会到TCP是在端系统实现的,中间节点一无所知,我想你就Get到了分组交换和分层的真谛。. p1 {1 t" f, Y1 c: y2 {
" T( g9 H, N. }/ G TCP/IP参考模型定义了5层: 应用层,传输层,网络层,链路层,物理层。你一定得理解所谓的分层只不过是把你的数据层层包装而已,在传输的过程层中每到一个节点都会拆开某一层的包装,查看一下数据, 然后再次包装,转发出去,直到终点。+ b K) L8 C+ [ W7 [% b- A7 l
* E3 a& C# e% @' {( }% K 也许你不愿意了解底层烦人的细节, 但是一定要理解socket和http(s) , 这哥俩最贴近我们码农的日常生活,我们经常直接和他们对话,利用他们收发数据, 所以花点经历好好学学吧。
. w2 v* `/ ?' g) E. N: f7 X% ^5 y! ~
图书:
8 ^! l2 G; j7 w4 r5 J 《图解HTTP》
! U' K5 }% k" P! w: {5 j7 x 《计算机网络:自定向下的方法》/ N2 s3 v( i2 @, J/ H; q
" R/ M: R. D$ L1 {: S 五、Hash 和 RSA9 P3 s& I# D' N( M/ ^2 U3 |8 M0 @0 R
% F/ H) r9 P0 S; t) i, R2 Q" k
如果说Https是网络安全通信的一大基石, 那Hash和RSA 则是基石的基石。为了保证消息在传输过程中的私密性, 完整性,不可伪造性,这哥俩可以说是功不可没。) Y6 u2 n. ]1 {( {6 g& b5 C
5 R: v v: @/ ? 其实不仅仅是Https , 在各种软硬件平台上都能看到他们勤奋的身影, 例如SSO, SSH, JWT ..... 所以非常值得你投入精力去学习。
& r. y' v' {- M& [' }8 ]8 M; a# ^! z# {: [
RSA最为美妙之处就是有一对儿钥匙, 一个是私有的、保密的, 另外一个是公有的, 谁都可以知道, 这对于之前的对称密钥是个极大的颠覆, 谁能想到原先需要保密的密钥竟然可以公开呢!* |# j d$ v+ o9 V9 G$ e1 B
1 [( y- P* d1 s" \) t 更有意思的是私钥加密的数据只有相应的公钥才能解开, 反之亦然,这确实是很漂亮的概念。
% I0 e- P! F, X" g( r8 h9 ~% q$ M4 C' A) L1 Q r( t0 ]+ f
RSA的概念很简单, 但是为了实现真正的安全消息传输,作为第一步必须得有数据签名做保证, 你需要理解如何对消息用Hash形成摘要,然后用私钥签名,又是如何验证这个签名的, 理解了这一点,很多东西都迎刃而解。1 M( t5 M: X5 `5 v3 b/ [! m/ X# f
- V9 H* d5 p9 A1 q, s
|