我如朝露降人间,和风樱花随春谢。四十九年一朝梦,一期荣华一杯酒。 收藏本站
登陆 / 注册 搜索

阅读: 5.6K   回复: 5

一个键盘的自述

回复 发新帖
仗剑天涯 论坛大牛 2017-6-25 13:31 |显示全部楼层

今生相逢便是缘分,何苦去怨恨,何苦去仇视。

主题破百
十万人都在学习的网络安全知识
        我是一个键盘,和我的兄弟鼠标一样,是个典型的输入设备,像我这样的I/O设备多如牛毛,比如显卡,声卡,网卡,打印机,扫描仪,CD-ROM等等。
  n" d1 A7 h- p0 S+ f% i) _3 b/ [8 ]
        CPU和内存很明显是第一等公民,这一对好基友占据着二环内最核心、最金贵的土地,居高临下对外发号施令,从各处“抢劫”二进制数据到自己的地界来。其他的都被归类到二等公民,居住在5环以外,统称为输入输出(I/O)设备。' X* w  q; k6 J

( ]/ j0 i+ i& p. x, e; S        这个世界存在阶级歧视的,我确信。#381:
6 q. q( @' ]6 K4 X8 R& p% l
, V, N, u/ ]" m+ m$ D2 v  k        有些设备居无定所,通过USB临时接入到计算机,待个三五天就走,典型的“北漂”。5 U9 R9 j: p' h0 K

, k) M1 M" V; Z+ l# ~# g; @        哦对了,我必须得说明,硬盘的地位有点特殊,虽然它也是个I/O设备,但是它存储着所有的程序和数据,包括操作系统老大!
: x3 k2 p$ _8 r
; O, }5 ^$ |7 b0 O- t1 X        虽然经常被CPU和内存嘲笑,但硬盘应该属于1.5等子民,住在三环以里。操作系统老大把我们这些二等公民笼统的划分为两类:块设备字符设备
; ]9 y, q, ^5 \; ?, F! q/ T( N. q& y% @- E& U/ j
        硬盘,CD-ROM,U盘是典型的块设备,数据存储在固定大小的块中,每个块都有一个地址,就样门牌号那样。像我,鼠标,打印机很明显就是字符设备,哪有什么块结构? 就是用一个个字符组成的流而已,也没有什么地址。
5 }  W$ P5 ^6 t- l/ \: G( P; V6 o9 D7 Q6 P/ t! J
        还有一种分法是存储设备(硬盘),传输设备(网卡,调制解调器)、人机交互设备(我和鼠标,显示器也算),不管怎么划分,我们二等公民的身份都无法更改,也住不到二环去,那里房价实在太贵了。& q% {4 H; j1 `2 b2 T. X
8 R( ^2 ?# C4 Z0 C; m
        夜深人静的时候,我和二等公民朋友们经常探讨这个经久不衰的问题:咱都是人,为啥就住不到二环去?
. N  V0 Q( Q; S! T2 E/ {7 ^1 a: G

8 a1 O- [  {7 }; e" `
一个键盘的自述 crop.jpg

2 R+ F$ M+ Y5 {" n% u        鼠标说:这都是命啊,计算机刚发明的时候,只有最基本的计算功能和存储功能,哪有什么显卡,声卡,网卡?CPU和内存的祖先占据了二环,并且一直在那里经营至今,现在都不知道是多少代了。
& j! [( i6 y; O; p, d5 i
5 B& B/ K0 d* e' T  N) S" T        我说:唉,也是,我们的祖先还是出现晚了,没有占据好地界儿。/ e4 h6 l. L7 b/ y# V" u0 z
( A; T2 u- Q0 S; q9 U  N
        网卡说:这个不对的,关键是我们没本事,干不了CPU的活啊。
8 o  S! l( {* S/ D" r% g+ b( `7 s
4 L! r/ }- W" G5 b2 K1 P        “那算啥,我的GPU运算速度已经很厉害了,很多超级计算机还用我做运算部件呢,知道不?”显卡说。8 I  ~) l. i8 u* R
/ _. f" W% e; |% w. n: T
        鼠标说:别想那么多,其实二环生活也不轻松,你看看一开机,CPU阿甘和内存就忙的不可开交,累得要死。像我和键盘,尤其是你键盘,除了码农写程序,半天都不用一下,还是知足吧。/ u4 [" ?( L3 g& x$ I6 M3 K
        : I- b: a. C) O7 [! d/ P
总 线 和 端 口
        . c: G, c/ Y) O5 m
        虽然我们是住在五环外的二等公民,但是CPU还得和我们打交道,那CPU是怎么和我们联系的?
/ k# L  ~5 j- ~% n+ N! v4 q; A, H- g7 @! }3 ?. ]( M: E! k
一个键盘的自述 总线.png
# Y5 e* C$ r! {! O: V8 ?: ^
        一种办法就是CPU和每个I/O设备之间都扯一根线,有多少个设备就扯多少根,组成了一个以CPU为中心的星型布局,很明显这样太麻烦了,尤其是来了新设备怎么办?
4 j8 e1 q; m9 h; p% f1 n( n
- y! X2 n( b/ V. D- P  K        后来我们采用了“总线”这个概念,大家都挂到这一条“总线”上,CPU想找谁了,就在上面吼一声。8 E# P7 L* g. r. |! ~

  j9 T  Z( M6 V+ M        当然这种方式也有缺点,当一个人在总线上吼叫的时候会霸占总线,其他人都得等待。还有这么多设备,CPU怎么知道谁是谁?
2 N- b) L* }) \; [
7 M/ |* T6 `' z) e- j$ E& J' E        首先肯定得给每个设备编号,比方说硬盘(更准确一点是,硬盘控制器)的编号是320,图形控制器的编号是3D0,这个编号就被称为IO端口。有时候CPU会更懒,他和内存商量好,把我们这些IO端口映射到内存中去,这样CPU访问我们的时候,就像访问内存地址一样了。称为内存映射I/O
4 j/ B0 E3 ?& B6 ?& e% r/ N
* [2 @% u6 }- b9 t) Q9 Y
一个键盘的自述 内存映射io.png

' g8 P# F7 X/ o# o, a$ L) g
轮 询(程序式I/O)
       
        现在CPU知道了我们在哪儿,还知道我们的编号,接下来就可以和我们通信了。这时候我们又遇到了那个老问题:CPU太快,而我们I/O设备太慢,毕竟机械设备的速度是无法和电子设备相媲美的。#365:
9 S8 \! g$ N& x6 v+ F& h  g/ g. b/ E+ x
        比如说有个进程要读取硬盘上的文件,CPU代表该进程向磁盘控制器发出指令:3 `: k9 B3 R# a5 U; F

9 J* h  ]3 T) g" R3 d' F! k2 p) t! z$ m        CPU:硬盘硬盘,把你第1023689号磁盘块的内容给我拿过来0 K2 z: ~/ y  H2 h# F- b5 ~: l
5 G* |9 d6 u; P$ V
        硬盘:好的。: c% G# O( g0 N6 J
+ }+ v* u+ Q5 T
        CPU:弄好了没有?
3 u+ e7 m6 i- z* g# k0 I- }* h7 ?4 l
        硬盘:还没有。5 x  Z3 J; ?0 P

8 P3 e' l/ @/ L8 G        CPU:弄好了没有??
. F. Y: K# ?6 }# h! A( C' x5 ?, Q2 J; n
        硬盘:还没有还没有。。& h+ ^# X" I) Q7 I

; P  e7 W" m# P3 `6 V        CPU:到底弄好没有?快点!
7 ?: t; H, `& t3 c& P, O# q+ s' {- I
        硬盘:都说过没弄好了!!!# \5 k, G+ ^  a. F2 {: d8 D( ~
! O' V2 I( T, }9 u
        CPU:弄好了没有?!: V! C% j5 E1 s& z, f, G

% {4 z. J1 _9 x        硬盘:@#¥%……&&#j332:
+ ~* q/ M  s$ a7 ?
+ r( F/ S/ v9 P, P        CPU一直霸占着总线,不厌其烦的问硬盘弄好了没有,别的啥事也不做,这叫做轮询,或者叫做程序控制的I/O
8 `, y& N3 [" t6 u8 S( s" \$ }  Y& w$ U; e9 R, G* {
        由于CPU比硬盘快百万倍,很明显CPU被浪费了。
) w( R' U' p7 \! x
' K, y: v& |& l/ u5 w
中 断
       
3 N9 `8 [8 ]8 C, y8 B5 X        大家都觉得这样不合适,因为CPU忙着和硬盘“卿卿我我”,把别的I/O都抛弃了,像我,鼠标即使有什么数据等着CPU读取,他也不搭理我们。- {! L* i# C; X1 ~# s, ?

' u) S6 E- G0 r' j) {8 \        后来就改成了这种方式:
3 d  E! T5 D# G) V: p5 D8 W, A# l; W6 V
        CPU:硬盘硬盘,把你第1023689号磁盘块的内容给我拿过来,你弄好了以后告儿我一声。# A2 z4 d& P3 Q) s: q: |. r& s9 D  U

) x4 }3 y: [5 f        硬盘:我怎么告诉你啊?# U# r% Q- P4 u2 ~1 X1 j! b

* A1 `$ t) B3 R  E+ P$ o5 F6 p        CPU:我有一个中断请求线,你弄完了可以往这个地方发信号,我每次执行完一个指令都会检查。
$ C; \; b9 K; ?1 n: o7 Z* @0 o
; _7 d2 q% m3 D9 `) U2 f! D: z9 M        硬盘:好的(CPU干别的事儿去了,当前进程A阻塞,另外一个就绪的进程B开始执行)2 ^4 H! _& ?- W. f
) X- T3 f+ e) H) [9 [& R
        过了不知道多少纳秒。。。。。: g1 |9 \8 b- w" S/ C

  Q) s5 F' j+ Y        硬盘:CPU,数据好了,赶紧过来取走。
5 u# ?% {* _5 h( T7 \0 ]8 J
; P* T" i2 u0 d8 X        CPU:稍等,我把当前的进程B给保存了,然后就去处理。(CPU执行中断处理程序,读取数据.....)
" M4 B+ t0 n% Z: M4 O. v7 A
! M) Q6 K7 R0 y9 d% X+ y* m/ {- G        这就是“中断”方式,有了中断以后,这些平时都不怎么露面的I/O设备都跳出了抢着发中断,“调戏”CPU,CPU乱成了一团,系统也乱成了一团。CPU不胜其烦,后来专门找了一个叫中断控制器的家伙专门负责协调,这家伙确实厉害,一上场就说:
4 I; T% l6 a2 k+ ]/ u3 U        ' u! B% m# l' m5 ]/ W/ I& ~! A* C) K
        只有我才能给CPU发中断,你们的中断请求统统发给我啊,我来裁决谁的优先级高,谁能“调戏”CPU。4 g5 B4 |: U, E: [  h8 y; a' d

& k1 k' [2 A* s1 r# L        这样一来系统清净了。#j337:$ a( j1 n- S7 {( f+ T# }

" ?5 ], E2 h1 j7 d        注:这种“中断”的方式,其实就是一种异步的、事件驱动的处理思想,在计算机软硬件上应用非常广泛,例如Node.js,AJAX等等
  h4 o/ o' Q; J) W( f7 o        6 |4 O* N8 D: v( S/ j' k
D M A
       
6 l+ K3 K/ h3 Z' ~) s! G6 }, I) [        但是我知道,CPU和内存才是系统的核心,CPU运算时候只认内存这个好基友,所以所有的数据不管是谁产生的,不管是1.5等公民硬盘,还是2等公民键盘,鼠标等,数据统统都得搬到内存去。
. O1 d+ U- S) P& e3 x; W  _7 B
/ i8 X# y0 J$ ~8 W5 s5 ~( l- g3 F        这就给我们带来了一个挑战:数据的搬运  a+ {' t4 x+ s; j7 v

8 Y) R& o" X# i4 H3 @  M- o* A        中断的方式对于小数据量传输是有效的,像我是一个键盘,每次你按下一个键以后,我就会发出一个中断告诉CPU,CPU就能发出指令,把这个一个键对应的字符搬到内存。! M0 V- O+ Y/ m- {' P- s% o
$ Y# J8 q; M+ {9 j
        但是对于大数据量传输尤其是像硬盘这样的,CPU还得花费大量的时间和精力不断的发出指令,让磁盘控制器把数据从硬盘搬到内存去,这相当于又陷入了程序式I/O的陷阱。对于类似这样的情况,我们也有办法处理,就是用一个DMA控制器,使用这个专用的处理器进行I/O设备和内存之间直接的数据传输,脏活累活都被这个DMA给处理了。6 Y, X- i, h& e  ^& b
, l0 V  N% r+ ~6 y. j0 a" r
        CPU:硬盘硬盘,把你第2333333号磁盘块的内容发送到内存的xxx地址去,弄完了告诉我,我去干别的事儿去了。) W& x' M  s/ @* l. e; N

+ _# w& v* M1 Q" w, D) {: L3 _        硬盘:好咧,DMA,我这儿有数据要传输,数据一共有4096个字节,要传输到内存的xxx地址去。
2 e& n# J# u2 t& N7 m7 D3 c% ]- C) {5 B' e
        DMA:没问题!(DMA控制器开始哼哧哼哧的干活,把这4096个字节复制到xxx地址)
! B, j' K- ]5 D, R) Y9 y' R. @' g0 K7 a: y- t% w
        DMA:CPU,数据已经在内存中了,可以用了啊。: `& q, b  C* N

& V, G! B% Y( e7 j$ U3 e        CPU:怪不得刚才有时候我没法使用总线,是不是你小子霸占着啊?
' D4 y. y5 {) F( v
( F+ t+ g, ?2 W6 D* `& T7 R        DMA:我不用总线怎么搬运数据到内存?我也没有挪用几个时钟周期啊,再说了你还能使用你的一级缓存和二级缓存不是?
: d0 P* ?1 s+ g4 s. W
9 ~9 s7 A6 B; t        CPU:好吧,看在你帮我干了这么多苦活累活,就算了吧。#j335:$ \# V9 y* X0 q. O8 L; u7 _3 u
       
+ z* o$ F4 B4 S, T7 V5 ^; s  E. d
键 盘 的 工 作 原 理
       
        说了这么多别人的事儿,也该说说我自己了。我和鼠标一样,是个非常简单的I/O设备,每次你按下和释放键盘上某个键的时候,我就会产生一个扫描码,例如你按下A,扫描码是"1E",释放A,扫描码是"9E"
. v& G# g: _6 m$ g; @: W" w% k
  o% F" \, A& }- q) H        我把这个扫描码放到0x60端口,然后向CPU发中断,当然得通过中断控制器了。CPU会调用中断处理程序,读这个0x60端口,取到扫描码,翻译成ASCII码就可以使用了。2 h: G& h  q  C: N

5 ~/ i6 P5 o  U; {- W- Y3 g/ C7 h7 t        那么问题来了,假设系统中有好几个进程都在等待键盘的输入,这个中断处理程序获得ASCII码发给谁呢?怎么发过去呢?这个问题留给聪明的小伙伴们~. U( t3 e% `. L# s& y) u9 x" k

2 @1 w7 u5 X5 V9 C- u


流星☆坠落「出类拔萃」 2018-1-25 15:13 来自手机 |显示全部楼层

这个用户很懒,还没有填写自我介绍呢~

锄禾日当午,发帖真辛苦。谁知坛中餐,帖帖皆辛苦!
柔光的暖阳「出类拔萃」 2018-1-20 23:15 来自手机 |显示全部楼层

这个用户很懒,还没有填写自我介绍呢~

回个帖子,下班咯~
站在你身边的人「出类拔萃」 2017-6-26 18:30 |显示全部楼层

这个用户很懒,还没有填写自我介绍呢~

学到了#j335:
清风徐来龙战于野 2017-6-26 20:23 |显示全部楼层

这个用户很懒,还没有填写自我介绍呢~

记得作文也是这么写的* v$ h. o5 ^2 ^- Y+ O
小河的自述# a( ~) i/ D# A+ Y
地球的自述
7 U5 \7 I# M2 S& B1 \  |# o森林的自述: W0 \% K7 U8 d  x- |) |2 B7 R8 O
海洋的自述) G3 R0 E2 h" c) k0 p" n# r
..................
雾月「出类拔萃」 2017-9-4 10:27 |显示全部楼层

这个用户很懒,还没有填写自我介绍呢~

你们那些十五字神马的完全弱爆了0 j( G& A6 {/ y% n$ N
您需要登录后才可以回帖 登录 | 注册账号  

本版积分规则

关于本站|大事记|小黑屋|古黑论 网站统计

GMT+8, 2020-6-4 16:24 , Processed in 0.043597 second(s), 25 queries , Redis On.

© 2015-2020 GuHei.Net

Powered by Discuz! X3.4

快速回复 返回列表