只有破碎的心才有伤人的棱角。 收藏本站
登陆 / 注册 搜索

阅读: 6.3K   回复: 5

一个键盘的自述

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

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

主题破百
        我是一个键盘,和我的兄弟鼠标一样,是个典型的输入设备,像我这样的I/O设备多如牛毛,比如显卡,声卡,网卡,打印机,扫描仪,CD-ROM等等。
% R* Y' R  ?( x, v) j9 B
5 O% ?0 x7 \; R  T        CPU和内存很明显是第一等公民,这一对好基友占据着二环内最核心、最金贵的土地,居高临下对外发号施令,从各处“抢劫”二进制数据到自己的地界来。其他的都被归类到二等公民,居住在5环以外,统称为输入输出(I/O)设备。
6 g/ l$ R4 G* B- W" V
3 [/ R2 s6 Q4 v+ }8 b' e$ B* {        这个世界存在阶级歧视的,我确信。#381:
& c2 R. g# C! e. ?" \, _; n8 N" U3 }, f; T& k' T
        有些设备居无定所,通过USB临时接入到计算机,待个三五天就走,典型的“北漂”。
5 f; l# F. T. J. m! i6 E! ]) N: o# c( s
        哦对了,我必须得说明,硬盘的地位有点特殊,虽然它也是个I/O设备,但是它存储着所有的程序和数据,包括操作系统老大!) c* [' u+ `) m4 N+ T& t4 Z/ @; f3 o

  L4 Q, L, d! O( S        虽然经常被CPU和内存嘲笑,但硬盘应该属于1.5等子民,住在三环以里。操作系统老大把我们这些二等公民笼统的划分为两类:块设备字符设备% u! o, W5 J; h% d2 d$ g

+ W  @( ^) s9 G. b$ O        硬盘,CD-ROM,U盘是典型的块设备,数据存储在固定大小的块中,每个块都有一个地址,就样门牌号那样。像我,鼠标,打印机很明显就是字符设备,哪有什么块结构? 就是用一个个字符组成的流而已,也没有什么地址。5 h3 P! X* @. l
0 _9 D. C6 L" A4 b
        还有一种分法是存储设备(硬盘),传输设备(网卡,调制解调器)、人机交互设备(我和鼠标,显示器也算),不管怎么划分,我们二等公民的身份都无法更改,也住不到二环去,那里房价实在太贵了。" _! ~9 z& u" `4 @/ r& G2 x
6 U! C3 y% r: z" v8 b$ f6 N# d
        夜深人静的时候,我和二等公民朋友们经常探讨这个经久不衰的问题:咱都是人,为啥就住不到二环去?" Z& T) J& L- }* R7 H& Y4 v+ t5 @$ F
% N" W7 k0 b$ R

/ \. p' o; z) e. v
一个键盘的自述 crop.jpg

7 ], a. W0 C: @" g        鼠标说:这都是命啊,计算机刚发明的时候,只有最基本的计算功能和存储功能,哪有什么显卡,声卡,网卡?CPU和内存的祖先占据了二环,并且一直在那里经营至今,现在都不知道是多少代了。
' ?; F! ~& e3 x3 B# I! Q7 ]) ]) P  |3 f/ r/ p. ]& G
        我说:唉,也是,我们的祖先还是出现晚了,没有占据好地界儿。
$ _1 a. S" H. T/ a4 \2 g$ N! ^
. W' V% R; O0 e/ d$ Z( g4 X7 D        网卡说:这个不对的,关键是我们没本事,干不了CPU的活啊。* @" b" b) H) L# @$ q

3 X7 ^4 {! p  }1 {+ T& L2 S/ S        “那算啥,我的GPU运算速度已经很厉害了,很多超级计算机还用我做运算部件呢,知道不?”显卡说。
3 F( _- k, P' @0 Y% l* g+ H5 ]' M: h' d. i( V2 s' h
        鼠标说:别想那么多,其实二环生活也不轻松,你看看一开机,CPU阿甘和内存就忙的不可开交,累得要死。像我和键盘,尤其是你键盘,除了码农写程序,半天都不用一下,还是知足吧。8 r- A" N5 e8 ~2 I% J
       
2 U4 n) |( m7 I, J
总 线 和 端 口
        + H) H, }8 G6 ^+ r" c, N
        虽然我们是住在五环外的二等公民,但是CPU还得和我们打交道,那CPU是怎么和我们联系的?& M$ D5 q/ w* b5 p* u' E
3 R! g8 V0 F* W: P
一个键盘的自述 总线.png
& X9 @8 d3 [2 @# e' i+ h
        一种办法就是CPU和每个I/O设备之间都扯一根线,有多少个设备就扯多少根,组成了一个以CPU为中心的星型布局,很明显这样太麻烦了,尤其是来了新设备怎么办?- |. f7 i' g& k% U1 q
$ f2 @, C% I/ q% H
        后来我们采用了“总线”这个概念,大家都挂到这一条“总线”上,CPU想找谁了,就在上面吼一声。6 I% Q" Q$ F7 w8 T: D' `+ v
+ k' Z% `0 S; u8 F( m
        当然这种方式也有缺点,当一个人在总线上吼叫的时候会霸占总线,其他人都得等待。还有这么多设备,CPU怎么知道谁是谁?# }- N/ U7 r! @) \

+ Y5 [$ U" C8 J* ?2 ^7 t$ `( r# x; J        首先肯定得给每个设备编号,比方说硬盘(更准确一点是,硬盘控制器)的编号是320,图形控制器的编号是3D0,这个编号就被称为IO端口。有时候CPU会更懒,他和内存商量好,把我们这些IO端口映射到内存中去,这样CPU访问我们的时候,就像访问内存地址一样了。称为内存映射I/O! L& Q# G1 `8 F; y9 C2 q! g
4 D" o1 w# X/ b1 o, _! a. D" X. W1 x
一个键盘的自述 内存映射io.png
5 e% o* X! _2 l0 n- A& o
轮 询(程序式I/O)
       
        现在CPU知道了我们在哪儿,还知道我们的编号,接下来就可以和我们通信了。这时候我们又遇到了那个老问题:CPU太快,而我们I/O设备太慢,毕竟机械设备的速度是无法和电子设备相媲美的。#365:
1 `  `4 Y+ E- @7 d* o, W7 y- v  f2 s0 d, ~! H) {
        比如说有个进程要读取硬盘上的文件,CPU代表该进程向磁盘控制器发出指令:, I7 A- R4 a3 w6 }. n: n

& g+ P7 q; w2 r: O9 U; b( c8 w. i        CPU:硬盘硬盘,把你第1023689号磁盘块的内容给我拿过来3 O0 I. V) B" Y" Z9 c5 y: l6 n
& U% a% I- U, C3 k0 S4 Q
        硬盘:好的。
3 s* Y/ O3 s6 S3 [+ I8 O% n, A8 L" k! w& P! n9 j1 R8 I9 ]
        CPU:弄好了没有?# X$ x, q1 M" Q# W

  W: ]  {$ E* l. v        硬盘:还没有。. X9 Q6 Q0 S6 F# K6 m# v0 b
' f1 i6 \+ [0 _" G
        CPU:弄好了没有??% S% W& R- P* G$ x

2 b# B' X5 i; `! ]        硬盘:还没有还没有。。, y! m1 P2 ?( A: R" z

) ]! I* a: _$ j        CPU:到底弄好没有?快点!. e6 b8 }% U# R4 l  w, N7 P  a* t

% }' l5 }' m) G  t2 c1 a        硬盘:都说过没弄好了!!!
% I% q! t8 m- R& o4 V7 K2 t1 x/ c% y% w# p% @1 x. L
        CPU:弄好了没有?!
" a, L& z6 Z, G+ O3 d
" @% H5 s1 a& t& V5 u( C9 j        硬盘:@#¥%……&&#j332:* Y( y) g1 O, I; v% _; t4 r

3 b% c) T( e8 _) t- M        CPU一直霸占着总线,不厌其烦的问硬盘弄好了没有,别的啥事也不做,这叫做轮询,或者叫做程序控制的I/O/ A! w7 O: ~  M5 G8 m
+ q1 c* |8 N) Y3 r" \* l; @
        由于CPU比硬盘快百万倍,很明显CPU被浪费了。" b6 Y; G0 [" M9 i. @4 N) V9 g

, E& f' x6 L  @6 e
中 断
       
5 u" S1 G+ t- C/ t6 E        大家都觉得这样不合适,因为CPU忙着和硬盘“卿卿我我”,把别的I/O都抛弃了,像我,鼠标即使有什么数据等着CPU读取,他也不搭理我们。& x6 Q4 J( x& Q: d& R5 K3 d" c
! \3 S! E& Z! q, _6 N) q
        后来就改成了这种方式:
1 M! u9 z0 c9 C5 `  R9 y! f0 F- Z+ X1 W$ p6 I' r3 j
        CPU:硬盘硬盘,把你第1023689号磁盘块的内容给我拿过来,你弄好了以后告儿我一声。
* a; j+ t2 }  `; z3 ]6 I. x, B% D$ D& X, F1 C" ]
        硬盘:我怎么告诉你啊?8 T5 Y5 s7 Q  S) {" H
. S/ e' X! B; |- x9 y, `" ~! f( }
        CPU:我有一个中断请求线,你弄完了可以往这个地方发信号,我每次执行完一个指令都会检查。" P' n4 }7 n9 c, {
4 ?8 Z4 U2 g4 N& S- P1 y& V- M( s
        硬盘:好的(CPU干别的事儿去了,当前进程A阻塞,另外一个就绪的进程B开始执行)
2 p  N, v* y7 w/ t5 k6 N7 N( c: v) ~9 r
        过了不知道多少纳秒。。。。。
: p1 ?; y9 T) Y0 C9 V; _: x3 r0 {/ A  P7 C' b4 {
        硬盘:CPU,数据好了,赶紧过来取走。) V0 z+ c1 ]4 k
0 f  f: j; c: a  a& B! R! i: g/ A3 e
        CPU:稍等,我把当前的进程B给保存了,然后就去处理。(CPU执行中断处理程序,读取数据.....)
; s- `7 ]" G3 o1 T# R+ |$ L( i" _* c- `' o8 B- \) s5 |
        这就是“中断”方式,有了中断以后,这些平时都不怎么露面的I/O设备都跳出了抢着发中断,“调戏”CPU,CPU乱成了一团,系统也乱成了一团。CPU不胜其烦,后来专门找了一个叫中断控制器的家伙专门负责协调,这家伙确实厉害,一上场就说:
+ q' G* V; l' S8 a0 S4 A        ' H6 {' Z" D4 ^6 w( {
        只有我才能给CPU发中断,你们的中断请求统统发给我啊,我来裁决谁的优先级高,谁能“调戏”CPU。
# }4 C4 Z4 g. P2 o, S" V/ u) a" d" q" f: p: X/ Y" K
        这样一来系统清净了。#j337:
5 X# B# }7 K2 P! K
, S0 m7 W- ?% y7 @' d1 q! `' y        注:这种“中断”的方式,其实就是一种异步的、事件驱动的处理思想,在计算机软硬件上应用非常广泛,例如Node.js,AJAX等等
5 I& |- ~; k, M        * v  O7 J4 R4 `3 F7 I1 S
D M A
       
1 i3 C+ {' C3 @) u% ], U& U4 R        但是我知道,CPU和内存才是系统的核心,CPU运算时候只认内存这个好基友,所以所有的数据不管是谁产生的,不管是1.5等公民硬盘,还是2等公民键盘,鼠标等,数据统统都得搬到内存去。" ^6 [! L7 Y# Q4 y- v8 p

; l3 i7 C& a; O+ r+ M3 A3 i        这就给我们带来了一个挑战:数据的搬运: x+ X9 @4 t* y. {) ]$ f
0 I* W! C5 P! E  P) q! ], T8 c
        中断的方式对于小数据量传输是有效的,像我是一个键盘,每次你按下一个键以后,我就会发出一个中断告诉CPU,CPU就能发出指令,把这个一个键对应的字符搬到内存。
: @/ s5 }1 ?1 b
' M% _$ B. C" Q" ~) O* A: H        但是对于大数据量传输尤其是像硬盘这样的,CPU还得花费大量的时间和精力不断的发出指令,让磁盘控制器把数据从硬盘搬到内存去,这相当于又陷入了程序式I/O的陷阱。对于类似这样的情况,我们也有办法处理,就是用一个DMA控制器,使用这个专用的处理器进行I/O设备和内存之间直接的数据传输,脏活累活都被这个DMA给处理了。0 Y; J6 i' w5 c
: }8 l3 T1 I2 o2 m+ m; ]
        CPU:硬盘硬盘,把你第2333333号磁盘块的内容发送到内存的xxx地址去,弄完了告诉我,我去干别的事儿去了。* a- [! u8 X" k2 o8 z' u( W

3 I$ l' Z: ?1 ^6 n        硬盘:好咧,DMA,我这儿有数据要传输,数据一共有4096个字节,要传输到内存的xxx地址去。( l) V' n' R1 p: }6 ~; [' N) [  Y! `

" M3 F/ @% A, E- P        DMA:没问题!(DMA控制器开始哼哧哼哧的干活,把这4096个字节复制到xxx地址)
* k: }( N5 d) y5 E+ i9 C) q3 f2 Q3 L5 V+ f; x5 d/ j: X
        DMA:CPU,数据已经在内存中了,可以用了啊。! a3 }7 O& \* E7 T' k1 c$ j
+ d: U4 \+ @6 V8 E
        CPU:怪不得刚才有时候我没法使用总线,是不是你小子霸占着啊?6 }1 c8 Q9 S  n( `* {8 C
0 t3 b# I- p/ O2 e% A- H! j6 R
        DMA:我不用总线怎么搬运数据到内存?我也没有挪用几个时钟周期啊,再说了你还能使用你的一级缓存和二级缓存不是?) U+ B7 c, y% ]" K& l

. [. H2 \1 S$ V        CPU:好吧,看在你帮我干了这么多苦活累活,就算了吧。#j335:
' ^! }+ n# l4 i) x0 @$ `        : Y! p3 [  y, g/ [
键 盘 的 工 作 原 理
       
        说了这么多别人的事儿,也该说说我自己了。我和鼠标一样,是个非常简单的I/O设备,每次你按下和释放键盘上某个键的时候,我就会产生一个扫描码,例如你按下A,扫描码是"1E",释放A,扫描码是"9E"
1 p4 Z: d7 M7 ~9 e/ e' I# b8 Q
! d! t& K: b) h        我把这个扫描码放到0x60端口,然后向CPU发中断,当然得通过中断控制器了。CPU会调用中断处理程序,读这个0x60端口,取到扫描码,翻译成ASCII码就可以使用了。9 ?1 H% c/ s2 z& v
+ M4 l. d' V  ?) p# [
        那么问题来了,假设系统中有好几个进程都在等待键盘的输入,这个中断处理程序获得ASCII码发给谁呢?怎么发过去呢?这个问题留给聪明的小伙伴们~
9 C4 Y* M7 I6 J$ d1 E; I8 I/ e
; a4 U, y5 y3 z, a4 x( J6 E
上一篇
下一篇


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

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

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

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

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

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

学到了#j335:
一个袋子砸在了站在你身边的人头上,站在你身边的人赚了 2 个 金币.
清风徐来 「龙战于野」 2017-6-26 20:23 |显示全部楼层

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

记得作文也是这么写的
5 V, G, d- `, n' u小河的自述
: J; g; X; Y3 J' n7 h) t地球的自述/ j6 B0 |" g+ {* F  x
森林的自述) F/ P* U1 A0 D1 K1 J" ?
海洋的自述! S% N+ @& u( F; m6 J1 u
..................
清风徐来被钱袋砸中进医院,看病花了 1 个 金币.
雾月 「出类拔萃」 2017-9-4 10:27 |显示全部楼层

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

你们那些十五字神马的完全弱爆了1 j7 a) r) Y& e
您需要登录后才可以回帖 登录 | 免费注册  

本版积分规则

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

GMT+8, 2021-5-9 00:55 , Processed in 0.026101 second(s), 20 queries , Redis On.

© 2015-2021 GuHei.Net

Powered by Discuz! X3.4

快速回复 返回列表