momo zone

调核人的blog

Monthly Archives: 八月 2011

fujitsu MO驱动器 解剖

MCP3130AP 仕様

OEM製品
  • 1.3GB
  • ATAPI
  • GIGAMO規格準拠
  • メディアID機能搭載
  • セキュリティ機能搭載

GIGAMOロゴメディアIDロゴセキュリティMOロゴ

MCR3230AP
製品名 MCP3130AP
3.5型光ディスク媒体 (注1) 1.3GB媒体、640MB媒体、 540MB媒体、230MB媒体、128MB媒体
セクタ容量 1.3GB媒体 2,048Byte
640MB媒体 2,048Byte
540MB媒体 512Byte
230MB媒体 512Byte
128MB媒体 512Byte
情報転送速度 Max 1.3GB媒体 3.92~6.70MB/s
640MB媒体 3.52~5.87MB/s
540MB媒体 3.54~5.94MB/s
230MB媒体 2.00~3.16MB/s
128MB媒体 1.65MB/s
連続ライト (実効) 1.3GB媒体 0.99~1.70MB/s
640MB媒体 0.93~1.55MB/s
540MB媒体 0.78~1.30MB/s
230MB媒体 0.47~0.75MB/s
128MB媒体 0.39MB/s
連続リード (実効) 1.3GB媒体 2.98~5.09MB/s
640MB媒体 2.79~4.66MB/s
540MB媒体 2.33~3.91MB/s
230MB媒体 1.40~2.23MB/s
128MB媒体 1.16MB/s
インターフェース 16.6MB/s (PIOモード4、マルチワードDMAモード2)、 33.3MB/s (ウルトラDMAモード2)
平均シークタイム(typical) 23ms
平均回転待ち時間 1.3GB媒体 8.2ms
640MB媒体 5.5ms
540MB媒体 5.5ms
230MB媒体 5.5ms
128MB媒体 5.5ms
回転数(typical) (注2) 1.3GB媒体 3,637min-1
640MB媒体 5,455min-1
540MB媒体 5,455min-1
230MB媒体 5,455min-1
128MB媒体 5,455min-1
ロード時間 12s(1.3GB媒体) 8s(640MB媒体、540MB媒体、230MB媒体、128MB媒体)
アンロード時間 4s
インターフェース ATAPI (ATA[ATAPI-5規格準拠])
データバッファ(注3) 1,844KB
電源条件 +5VDC±5% 1.2A(最大 2.7A)
ヘッド ポジショナ + 分離光学系
外形寸法(注4) 101.6mm
長さ 150.0mm
高さ 25.4mm
重量(注4) 410g
消費電力 平均値 (typical) Ready時 3.9W
W/R時 5.8W
パワーセーブ時 (最小) 1.2W
温湿度 動作時 5~45℃ (勾配 15℃/h以下)、10~85%
振動(注5) 動作時 3.9m/s2 (5~500Hzサインスイープ)
非動作時 9.8m/s2 (5~500Hzサインスイープ)
衝撃(注5) 動作時 19.6m/s2 (10msハーフサインパルス)
非動作時 49m/s2 (10msハーフサインパルス)

注1  :
1GBは1,000,000,000バイト、1MBは1,000,000バイトです。 使用できる記憶容量は本表記の数値より少なくなります。 実際に使用できる記憶容量はお客様の使用環境やフォーマッティングにより変化します。
注2  :
1min-1=1rpm
注3  :
1KBは 1,024バイトです。データバッファの一部はファームウェア制御に使用されます。
注4  :
外形寸法及び重量については、前面パネルありの場合です。
注5  :
9.8m/s2=1G

拿在手上非常有量,全钢机心,基本看不到塑料。完全不是现在刻录机那种轻飘飘的感觉,毕竟一个是7000多RMB ,一个100多RMB ……

REV.NO 很喜感 ~

2002 年的东西,那个时候我还在用CD ROM 光驱。 距今已经9年了!!!!

比较精密的机械,所有螺丝都可以拆卸,绝对看不到刻录机中的各种胶水。这里可以看到MO光驱最大的特色:光头在轨道上以音圈电机驱动而不是步进电机!!!!另一特点是光头与主光学系统分离!!!

为什么呢 ?  后面再解释

主轴电机特写,有螺丝 ,很容易拆卸

主光学系统特写1:

主光学系统特写2:

主光学系统特写3:

工作状态中:

光头部分的进光口:  还能看到光头下方的写入磁线圈。

由于主光学系统和光头分离,工作时激光发射之后要经过很长一段距离进入光头上的入射孔,然后再经过里面的反光镜和物镜 聚焦在盘片上。

棱镜上方的一面应该涂有特殊涂层,起到1/4波长片的作用。下方的是激光器(LD)和可调准直透镜(CP镜),左边的是光敏管,右边的是可调聚焦透镜以及OEIC( 用于聚焦伺服)。很多CD/DVD光头直接把LD和OEIC 合在一起,叫全息单元。光栅(GR) 应该是在光头里面,而不是在LD前面。

集成度相对比较低,主控MCU 是fujitsu 自己的,但依据型号查不出什么资料。音圈电机驱动IC 是日立的。

MO 整个机构都在防震钢架上,而刻录机或光驱则只有光头部分在防震钢架上。

开始测试,因为MO 不属于光驱类设备,而是属于可移动磁盘设备,所以不能用Nero cd speed 测了。

前面说了,这个是2002年制造的,已经有9年了,但读状态依然正常,老化不严重,平均1.5MB 读速度。

读取时间中包含寻道时间 ,平均是33毫秒。 除去实际的读取时间,那么寻道时间也就最多30毫秒。硬盘的寻道时间也就这样吧~~

为什么会这么快? 因为光头和主光学系统分离,光头很轻,所以就可以用音圈电机就能驱动光头的移动了,和硬盘的磁头差不多了(当然还是慢了点)

Advertisements

疑为微软火中取栗 SCO曾震撼Linux阵营

“SCO在言语上变得越来越好斗,还拒绝展示有关诉讼的任何证据,一切都似乎在表明,SCO只不 过是在拉虎皮做大旗地狂言乱语。但是,微软决不会轻易放弃这么一个利用这些狂言乱语的好机会。”2003年,《向Linux发起“恐惧战”?》的作者布鲁 斯·佩伦斯(Bruce Perens)这样评价SCO。

2003年3月,自称Unix操作系统的拥有者SCO向IBM提出了赔偿金为10亿美元的起诉,因为SCO认为IBM在开放源代码的Linux中泄露了其商业秘密。

2003年5月15日,SCO发信给全球约1500家大型企业,警告这些企业如果再使用Linux,他们将承担法律责任。

那么,Unix与Linux,SCO与IBM、微软,到底是怎样纠结在一起的呢?

风起Unix

“你写的系统太差劲,干脆就叫Unics算了。”上个世纪60年代末的一天,贝尔实验室的布赖恩·柯尼翰(Brian Kernighan)对同事肯·汤普生这样说。

在英文里,Unics发音与Eunuchs(太监)一样。肯·汤普生接受同事的嘲弄,并在稍作修改后,把自己研发的系统叫做Unix。

上个世纪60年代的计算机虽然已不再是庞然大物了,但体积仍然不小,操作这些又慢、又笨的家伙需 要专业的计算机程序员。为了提高效率,用户急需新系统。在这种背景下,贝尔实验室的肯·汤普生和丹尼斯·利奇研发了Unix操作系统。此时,乔布斯和盖茨 还在中学里搞恶作剧,PC和它配套的微软操作系统在10年后才初露端倪。

Unix的两位创始人和贝尔实验室都没把Unix太当回事,起初只是在内部使用,没有积 极推销。后来大学、研究机构可以免费使用Unix,而且还可以得到源代码,因此Unix源代码被广为扩散。这段时间它没有像后来的商业软件那样急功近利, 并留下一堆窟窿和补丁。Unix在诞生后的10年里“养在深闺人未识”,在实验室被充分使用和论证,这也是后来它一度在对稳定性、安全性要求较高的企业级 客户中得到推崇的主要原因。

到了1980年,Unix开始走出实验室,蔓延到大学与研究机构,还有数以千计的技术高手想把Unix装在家里的机器上。

此时,后知后觉的贝尔实验室开始认识到Unix的价值,但由于源代码早已外散,贝尔实验 室无法将其归集起来进行精细的商业开发,于是干脆采取对外授权的模式,研究机构可以免费使用,企业要使用则需交授权费。当时有多家大学、研究机构和公司获 得了授权,并开始了各自不同的版本演进之路。

贝尔的一位高级主管曾说:“Unix是继晶体管以后的第二个最重要的发明。”

1993年,拥有贝尔实验室的AT&T将其拥有的Unix资产卖给Novell。此时的IBM、DEC、HP和Sun因为早年得到授权,继续进行着各自的Unix版本研发。

1995年,Novell将Unix资产卖给SCO。和两年前AT&T把 Unix卖给Novell时Novell一次付清购买资金的情况有所不同,SCO当时没有足够的现金一次付清,因此Novell初期只是把Unix的源代 码及其他数据交给SCO,而在协议中对Unix著作权的归属存在语焉不详和模棱两可的地方。在那个时代的许多软件合作协议在今天看来都是含混不清的。

花了钱的SCO认为自己是Unix的正宗传人,而Novell当时已视Unix为鸡肋,并没有异议。而且此时SCO的声音不大,SCO也没有对别的获得过Unix授权厂商置喙,于是大家进入了一个相安无事的阶段。

微软的进进出出

微软与Unix的关系源远流长,并对SCO的演变起了重要的催化作用。

1979年,微软也从AT&T获得授权,为英特尔处理器开发一种Unix操作系统。由于微软购买的授权无法直接让该操作系统以“Unix”为名,于是命名该系统为Xenix。Xenix可用在个人电脑及微型计算机上。

微软并不直接把Xenix销售给终端客户,而是以OEM的形式授权给英特尔、Tandy、施乐及SCO。

由于微软需要从AT&T获得授权,因而对微软来说Xenix是一个自己难以把握 其未来发展命运的操作系统,而且竞争对手拥有众多版本不同的相关软件在搅乱这个市场。因此,盖茨在寻找机会退出这个领域。当微软和IBM达成开发OS/2 操作系统的协议后,盖茨便失去了推广Xenix的兴趣。史料揭示,微软当时脚踩两条船,除和IBM联手开发OS/2操作系统外,微软还在紧锣密鼓地进行着 Windows3.0系统的研发。微软不可能在三条线上同时投入精力,断然舍弃了Xenix操作系统。

1987年,微软与SCO达成了一项协议,前者以持有后者股票25%的条件转让了Xenix的所有权。有趣的是,微软内部依旧在使用Xenix。有资料显示,他们一直用到1992年。

从微软接盘Xenix的SCO,将这种操作系统以最快速度移植到386电脑。Xenix成为首款支持英特尔386芯片的操作系统,占领了市场的先机。

当时小型机加五花八门的Unix操作系统主导着高端的企业级用户市场,其中的代表厂商是 IBM、DEC、惠普、Sun、SGI等;英特尔芯片加微软操作系统,正在全面控制个人电脑市场,其中的代表厂商包括康柏、AST、佰德等。小型机加 Unix操作系统的阵营鄙视英特尔芯片加微软操作系统形成的Wintel联盟,认为它们简陋;而后者则认为前者老化、顽固。

SCO此时扮演的角色有点像蝙蝠,非鸟非兽,其运营模式是英特尔芯片加Unix操作系统,在两大阵营间徘徊。随着装有英特尔芯片电脑的攻城略地,SCO也跟着分得了一杯羹。

在上个世纪80年代末,有媒体称Xenix“可能是传播最广的Unix操作系统”。

SCO进入了其发展史上最辉煌的时期。当然在这段时间,Unix的发展也进入了黄金期。1984年9月,《财富》杂志称,全球范围内750所大学80%的计算机领域教授都是Unix的用户,因此当时计算机专业毕业的学生都接触过Unix,而他们毕业后成为IT骨干。

而,Unix有个致命的缺陷:从来就没有通用版存在。由于早期混乱的授权,五花八门、不 同版本的Unix遍地开花,所以为其中一个版本写的应用程序,常常要修改后才能运用到另一个上。这对于专业的程序员来说也许不是太大问题,但对技术实力较 弱的用户来说,则平添了许多困难。

从Unix脱身而出的盖茨深知其支离破碎所带来的问题。他抛弃了Unix,但他可没打算抛弃这块广阔的市场,而且SCO的成功也给他带来了不小的刺激。

于是盖茨下令打造一款“可移植的”的操作系统——“Unix杀手”。这就是微软的Windows NT,包括SCO在内的Unix阵营将感受到它带来的巨大压力。

强悍对手逆袭

定下“Unix杀手”计划后,盖茨准备组织一个团队来完成这项计划。“我太想要一个可移植的操作系统了。”盖茨说,“问题不在于我们是否应该组成团队,而在于何时能组成团队去开发它。”

机会来了,DEC的天才工程师大卫·卡特勒因在公司坐冷板凳而萌生去意。盖茨亲自拜会卡 特勒。初次见面,卡特勒就给盖茨一个下马威。他直言不讳地称微软的代码“写得很烂”,当时微软深以为傲并捧在手心的DOS在卡特勒的眼里只是一个玩具。卡 特勒说,只有自己才有能力开发出一个面向未来的、能进行网络管理的、具有高可靠性的、强大的操作系统。

此时的盖茨早已走过创业期,拥有海量的财富与强大的权利,耳边响起的都是“软件神童”的悦耳之音。不过,卡特勒的刺耳之音和轻蔑态度反而坚定了盖茨聘请卡特勒的决心。

盖茨尽可能地满足卡特勒的要求,有些要求甚至已经打破微软的惯例。譬如卡特勒不要微软原来的工程师加入他的团队,他把自己在DEC工作时的团队带了过来,团队中有些成员是硬件工程师。

盖茨识才的眼光和用人不疑的态度,最终得到了丰厚的回报。1993年,Windows NT完美亮相,成为微软撬动Unix市场的一把利器。

在包括SCO在内的Unix阵营开足马力贬低Windows NT的同时,Windows NT在高端市场上大步前进。SCO公司则开始走下坡路。

在微软与Unix阵营的对手进行车轮战的同时,一股新的力量在生成并强大起来,左右了战局的发展方向。这就是Linux。

起初盖茨认为Linux无足轻重。但大量用户不那么认为,他们向Linux投去青睐的目光。Linux公开授权,允许用户销售、拷贝并且改动程序,但要求修改后的代码也免费公开。这些举措成了Linux蔓延的强大推力,并给微软带来了强烈的冲击。

Linux与微软相比似乎微不足道,但它的存在使用户在与微软谈判时有了选择的余地和讨 价还价的筹码。有媒体报道,2003年初英国政府的Windows许可证协议须续约时,他们告诉微软,其服务器操作系统正准备改用Linux,不再采用 Windows。微软在听到这些话后,不得不做出妥协,降低合同价格。大量大型用户纷纷效尤。

Linux的存在还给了对微软一直心存敌意的对手们一把雪耻的利刃,其中包括IBM、Oracle和Sun等业界大鳄,它们纷纷表示扶持Linux,向陷住微软战靴的Linux泥潭灌进去更多的水。

微软一度陷入了被动的局面。但随着Linux的发展,战局发生了微妙的变化。

“受到Linux蚕食的是Unix,而不是Windows。”盖茨在一个公开场合表示,“我们确实在与Linux竞争,但转换到Linux的Unix市场是相当可观的。Windows和Linux将共同主导市场。”

市场分析机构Gartner也宣称,Linux和开放源代码会继续发展,但它们所掠夺的是Unix而不是微软的领地。

Unix操作系统的价格比微软产品的更高,市场份额更少,受到Linux的冲击更大,靠Unix吃饭的SCO对此感同身受。一位Linux厂商技术总监曾放话:“SCO Unix的生命周期已结束,系统移植是必然的。”

与其坐以待毙,不如奋力一击。进入21世纪后,日渐式微的SCO开始策划一出震惊IT业界的大戏。

旷日持久的车轮诉讼大战

“在过去的18个月内,我们发现IBM把一些极其高端的企业运算技术的源代码公开了。其 中部分看上去与我们拥有知识产权的技术非常相似,违反了我们与IBM之间的协议。他们单方面公开了源代码。他们的行为破坏了我们之间不公开这部分技术的协 议。我们有证据表明部分代码是逐字的抄袭。”2003年5月21日,SCO CEO达尔·麦克布莱德(Darl McBride)这样说。

2003年3月,SCO向IBM提出诉讼,控告IBM的Linux破坏了双方之前签订的软件代码授权协议,声称IBM免费散发了共有知识产权的代码,把一些Unix的代码改头换面后加入Linux产品中,要求IBM向SCO赔偿10亿美元。

这在Linux阵营炸开了锅。他们认为SCO此举是“项庄舞剑,意在沛公”,最终目标是 Linux阵营。起初,SCO CEO麦克布莱德说SCO的矛头只指向IBM,因为IBM和SCO还在合作时,“IBM的一位经理带头站出来支持Linux,并说‘我们正在将AIX技术 移植到Linux,而且我们将消灭Unix。’”作为Unix的“正宗传人”,SCO只能反击。

然而,微软的参与让这个局面变得混乱起来。5月20日,在起诉IBM后,SCO集团宣 布,向微软公司发放Unix技术许可,其中包括专利权和源代码。此项交易确保微软的知识产权遵从Microsoft解决方案,并更好地确保微软与Unix 和Unix服务的兼容性。就是说,微软花钱购买了SCO的Unix技术许可权,并承认了SCO的Unix合法传人的地位。

Bruce Perens称:“对于微软来说,购买SCO的源代码授权几乎没有任何意义。花钱购买SCO公司的授权,只不过是对一种‘行贿’行为的粉饰,顺便还对 Linux未来的用户进行恫吓。可谓一石双鸟!很难想象微软的前对手SCO能为比尔·盖茨冲锋陷阵,但是微软的钱改变了一切。”

Linux阵营担心的就是这一点。微软此举强化了SCO的Unix“权威地位”,增强了 SCO挑战IBM的决心。一旦拿下IBM,SCO就打开了一个收钱的口袋,其他推行Linux的厂商只有乖乖纳贡。而且使用Linux的商业用户也面临着 SCO追索授权费的危机,更多潜在用户会对Linux望而生畏。这非常符合一直以来微软针对Linux用户实施的心理战战术,让用户在恐惧、不确定、怀疑 的状态下对Linux敬而远之。

2004年初,麦克布莱德警告说,一些大公司可能由于使用Linux计算机操作系统而面临诉讼,它们的行为已受到调查,其中包括英国石油、西门子和富士通。在评论英国石油使用该软件的情况时,他说“这些人显然逃不脱干系”。

SCO的诉讼风暴席卷全球,Linux阵营的厂商和大型用户人人自危。Linux阵营开始对SCO进行了口诛笔伐。与此同时,SCO对IBM的诉讼却慢慢占了上风。

借着SCO对Linux阵营的压力,2004年11月,微软CEO斯蒂夫·鲍尔默在新加 坡举行的一个高级别政府论坛上表示,Linux侵犯了至少228项专利,不过他并没有明确表示侵犯了哪些专利。他说:“对于那些已经加入世界贸易组织的国 家而言,使用Linux就意味着有一天有人过来向你收取专利费。”

2005年1月,美国法院判决IBM交出20亿行的程序代码给SCO,SCO股价在判决确立后,暴涨20%。

这时SCO似乎可以动手打开巨大的钱袋子了,然而风云又变,半路杀出一个程咬金。 Novell站了出来,称自己才是Unix版权的合法拥有者,因为Novell当年没有把Unix版权卖给SCO,SCO也只是个授权使用者,并且要 SCO把从微软和Sun公司收到的授权许可费给吐出来。

于是,SCO又和Novell公司干上了,开始了在法庭上互有胜负的对峙。

树敌过多引起的破产

“SCO公司在诉讼过程中树敌过多。”就职于嵌入式Linux厂商MontaVista的温伯格(Weinberg)这样表示。

连年诉讼耗尽了SCO的人力、物力和财力,SCO也没有把重心放在业务上。不过话又说回来,其Unix业务已日薄西山,没什么好继续开展的了。

2007年12月27日,财力耗尽的SCO正式被纳斯达克摘牌。此前SCO已经依据美国 《破产法》第11章提交了破产保护申请。2007年8月,美国犹他州地方法院一名法官裁定,Unix操作系统的版权归属于Novell,而不是SCO。这 意味着SCO需要向Novell支付数百万美元的赔偿,因此它在与IBM进行的法律大战中将失去胜算。

随后几年,处于破产保护状态中的SCO挣扎着继续与Novell在法庭对峙,但两家没落公司间的较量渐渐淡出主流媒体的视野。

记者手记

投掷“博浪椎”的阳谋

“君不闻秦庭匕首博浪椎,报燕报韩知是谁?”语出周亮才《侠士行》。其中的博浪椎典故讲的是:秦朝一个力士做出一个120斤重的铁椎,趁秦始皇东游,狙击秦始皇于博浪沙,成为惊天一击。

2003年3月,SCO公司对IBM提出10亿美元赔偿的诉讼,也震惊天下,被世人视为SCO对IBM及Linux的狙杀。

当年SCO因Unix市场的衰落而举步维艰,审视家底后发现多年前留下的这份Unix衣钵继承书。Sun比较痛快地支付了授权费,这在一定程度上证明SCO当年从Novell购得这份遗产的合法性。

底气充盈的SCO开始通过起诉在IT业界举足轻重的IBM进行战术突破。这很鲁莽吗?有一些,但不尽然。SCO应该明白挑战IBM的艰难,懂得其诉讼成本之高昂,但对于SCO来说,拿下IBM,就完成了毕其功于一役的博浪之击。

SCO开价10亿美元,与之前从微软、Sun获得的数千万美元授权费相比,无疑为“张开 了血盆大口”。这可以看作是一只秋膘不足的熊向大象发起的撕咬。如果SCO再低调一点,向IBM索要数额较少的授权费用,很有可能达到自己的目标,成为一 家靠专利遗产活着的小型公司,然后在缺钱时再向财富500强之类的公司收点授权费用,SCO还是可以过下去的。

SCO与IBM的这场战役规模太大,引起了世人的广泛关注,暴露了SCO下一步图谋把控Linux市场的战略构想。

让人不解的是,SCO在与IBM苦战的同时,发信给全球约1500家大型企业,警告这些 企业如果他们使用Linux将承担法律责任。SCO这就把自己的战略意图彻底昭告天下了,结果除了义愤填膺的Linux非营利性组织奋力反击 外,Linux获利集团也开始加入了对SCO的围剿。

按说,SCO手上还是有筹码的,不然它也不会数度从法庭上得到有利于自己的判决,不仅是对IBM的诉讼,还包括对Novell的诉讼。

至于说当年SCO的“Unix遗产”继承合同有缺陷,那实在不是此次车轮诉讼成败的关键。纵观软件史,几份影响产业格局的软件合作合同,都留下了不同解读的空间。即使在今天,由庞大的律师团坐镇,要签订一个滴水不漏的软件合作合同也是一件十分困难的任务。

SCO最后功亏一篑,是因为它要挑战的利益集团强悍而又广泛,其资源无法支撑这样庞大的战役,而且其战术动作丝毫不讲隐蔽性,无任何技巧可言,基本上属于蛮干。

《中国计算机报》

试玩GIT

前两天搞git版的mplayer ,所以把git的一些概念和操作都总结了一下。

1.获取别人的代码,进行项目编译。

首先建立一个新的目录,这个目录将作为git的工作目录:

$mkdir github

工作目录github 是个不错的名字,但其实后面会提到那个真正的github ,这里用这个名字意味着后来我会把他作为github 中众多项目的总目录。

$cd github

$git clone git://git.mplayerhq.hu/mplayer
耐心等待一下,像mplayer这样的大项目会有上万个object(一般都是源码)

clone完毕后,这里会自动生成mplayer 目录作为git的工作目录(repo) ,里面包含.git 目录。里面存放了内容如下:

FETCH_HEAD  ORIG_HEAD  config       gitk.cache  index  logs     packed-refs
HEAD        branches   description  hooks       info   objects  refs

.git的存在就说明这不是一个普通目录,而是git工作目录。

github------------------
                         |
                   mplayer-----------|
                                       .git
                                        |
                                       other object
在git 目录下可以用一下命令:
git show: 显示最后一次commit 的内容:
commit dbdd0a2dcdaafbb382a460558cb1e11fc55f0e1b
Author: reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>
Date:   Mon Aug 15 21:28:19 2011 +0000
    Forgotten commit of subreader.h adding SUB_GOOGLE define.
    git-svn-id: svn://git.mplayerhq.hu/mplayer/trunk@33996 b3059339-0415-0410-9bf9-f77b7e298cf2
diff --git a/sub/subreader.h b/sub/subreader.h
index 470167e..35725f7 100644
--- a/sub/subreader.h
+++ b/sub/subreader.h
@@ -50,6 +50,7 @@ extern char *sub_cp;
 #define SUB_SUBRIP09 11
 #define SUB_JACOSUB  12
 #define SUB_MPL2     13
+#define SUB_GOOGLE   14
 #define MAX_SUBTITLE_FILES 128
git log: 显示所有commit,从该项目创立到最近的commit
git pull: 从远端同步代码到本地,也可以用git pull git://git.mplayerhq.hu/mplayer 指定远端。 不写的话就从.git 目录里的config 获得远端。这里先不讨论本地代码和远端不同的情况。
需要留意的是所有git 子命令必须切换到对应的repo 目录才可以用

2. 利用GITHUB建立自己的GIT repo,用于维护代码

先去https://github.com 注册github 帐号。然后去Account Settings -> SSH Public Keys 去把自己的 host/user 的ssh公钥(public key)输入到这里。目的是为了允许github可以访问本机。git的分布式文件操作依赖ssh 。关于ssh key 的相关内容可以点击这里。

然后测试一下连接是否可用:

$ssh -T git@github.com

Hi username! You’ve successfully authenticated, but GitHub does not provide shell access.

然后设定git 的一些变量:

$ git config –global user.name “Firstname Lastname

$ git config –global user.email “your_email@youremail.com

尽量设置成和github上注册的一致吧。

https://github.com/dashboard/yours 点击New Repository 建立新的repo。

现在可以在本地创建repo:

$cd github

$mkdir helloWorld

$cd helloWorld

$git init

然后开始创建object ,也就是源码文件。 不过这里可以写一个README 用来测试。README 在git里面是个特殊文件,它总是在github的repo首页中显示,自动充当项目的自述。

书写完毕后将README 加入repo的stage状态:

$git add README 或者 $git add .  (把当前目录的所有文件加入stage 状态)

然后生成一个提交记录:

$ git commit -m ‘first commit’

一个提交记录就相当于给整个repo记录一个save 档,或者说是一个快照,下次提交时同样再生成一个。两个步骤也可以合并成一个

$git commit -a -m ‘first commit’

接下来就要让远程的repo和本地连接:

$git remote add origin git@github.com:lainredsonic/helloWorld.git

origin 就是remote git repo的别名。

最后将本地的repo同步到远程:

$git push origin master  

如果要将远程同步到本地:

$git pull origin master 

其实git pull 相当于依次执行了git fetch 和git merge。

每当在repo中新增文件到stage 时,都要用git add <filename> or git add . 然后用git status 可以看到当前的repo的变化:

$git add .

$git status

#On branch master
#Changes to be committed:
#       (use “git reset HEAD <file> …” to unstage)
#
#             new file: helloworld.c
#

然后新建一个提交:

$git commit -m ‘new file created’

$git push origin master

如果要从repo 删除一个文件,可以分为两种情况:只从repo中把stage状态改为unstage 状态,另一种是不仅repo中更改为unstage 状态,而且文件本身将被物理删除。无论何种删除,一旦同步到远程,则远程的文件肯定会消失。

$git  rm –cached <filename>    #仅更改为unstage 状态,文件本身还存在

$git rm <filename>  #真正删除文件

$git commit -m ‘del file from repo’

$git push origin master

下面试一下git的高级功能,主要是分支操作,和回退(撤销)操作

先说一下分支, 具体含义就不多说了。

$git branch   #查看当前仓库的所有分支,前面有星号的说明是正处于的分支。一般都是master吧。

$git branch <branch_name> [<source_branch>] #从source_branch建立branch_name的分支。如果source_branch不写的话默认就是master分支了。 注意一个分支是另外一个分支的完整克隆,包括log 。

$git checkout <branch_name> #切换至branch_name分支

$git push origin <branch_name> #提交分支到远程。 branch_name 必须写上,否则将默认push master 分支。

对分支修改完毕后可以合并至另外一个分支(包括master):

$git checkout master

$git merge <branch_name> <branch_name>  #一次可以合并多个branch

$git pull origin <branch_name> #直接将远程的分支合并到本地的当前分支。

这里一般都会遇到冲突提示,比如branch 1 里的一个文件包含和branch 2 同文件的相同部分的内容。通常解决冲突的方法就是vi 那么个有冲突的文件,然后新建一个commit即可。然后再push 这个branch到远程。注意:merge不但合并实际内容,也会合并log。

merge完毕后可以删除这个branch:

$git branch -d <branch_name>

如果没有merge 却要删除的话就要这样:

$git branch -D <branch_name>

这里有个疑问,本地branch 已经删除了,那么如果才能同步删除远程的呢 ? 按照下面来做:

$git push origin  :<branch_name>

最后再说一下回滚

如果要把git里面的内容回滚到之前的某个版本(以commit 为标识),有两张做法:

$git revert -n <commit msg>  #将内容会回到commit msg所指版本 ,而不回滚repo 状态信息

$git reset <commit msg> #回滚整个repo状态到 commit msg 版本。 意味着有可能丢失历史记录和branch 信息。

Nivida tegra2的一幅图

Nvidia  tegra2 架构。从它直接输出HDMI 说明内含GPU 了

2011081204590718.png (1200×925)

[转]市值只是表象 苹果企业价值仍远低于埃克森美孚

国外媒体今天撰文称,虽然苹果市值超过了埃克森美孚,但其企业价值仍然远低于埃克森美孚。而且由于埃克森美孚所处的是石油行业,对全球经济的影响也远胜于苹果。以下为文章全文:尽管外表冷酷,但华尔街却非常热衷于一些很表象的东西。苹果取代埃克森美孚成为全球市值最大企业就充分体现出这一点。

新闻标题给出的数字或许有些误导。市值本身既不代表债务,也不代表现金。不仅如此,埃克森美孚截至周三收盘的企业价值仍然高达3370亿美元,依旧远高于苹果的2610亿美元。所以,埃克森美孚的实际业务仍然更有价值。

有人认为,市值排名的变化从一定程度上预示着人们不可避免地会在沙发上使用iPad。但这种想法同样言过其实。无论你相信与否,没有了iPad,全球经济都可以照常运转。但没有能源却不行。如果没有能源,iPad不过是一款外表光鲜的镇纸而已。

而且,尽管苹果已经成为移动领域的埃克森美孚,但与沙特阿拉伯国有石油公司沙特阿美公司(Saudi Aramco)相比,埃克森美孚的石油产量和储备仍然相形见绌。美国外交关系委员会的迈克尔·莱维(Michael Levi)指出,如果以埃克森美孚的每桶石油价格和石油储备指标来计算沙特阿美的市值,后者将达到约4万亿美元。与整个能源市场相比,埃克森美孚只是一个小个子。

将苹果的成就放在整个行业背景中并不会有损它的价值。与埃克森美孚的前身标准石油(Standard Oil)在几十年前面临的情况一样,苹果也在创建新的市场。优秀的增长前景和高额利润,加上庞大的现金储备,使得苹果在这样一个困境重重的时刻格外具有吸引力。

十年前的微软也享受着同样的推崇,市值也曾经超过埃克森美孚。但时过境迁,微软如今的市值比苹果低了40%。这是对当前趋势的一个警醒。但同样也带来了一个并未被广泛提及的积极信号:美国经济拥有自我修复的能力

文/新浪科技

其实这篇文章的点睛之笔是最后一句话。这差不多也是美国敢随便印钞票,随便发国债的原因吧。机遇和风险并存这句话大家都知道。假如美国遇到了机遇,那么自己可赚到10美元,那么为之拼命打工的中国可能只能获得1美元的好处费。这其实也就是所谓的美国模式吧。

mplayer与H.264,VC-1 那点事

1.mplayer解某些TS的文件会发现没有声音 ,看log的意思是直接找不到音频流。 怀疑是分离器的问题,TS格式会优先使用MPEG-TS解封。

将demuxer 更换为lavf 后解决:
mplayer -demuxer +44

demuxer 的定义可以在 libdemuxer/demuxer.h 中找到。

2.播放某些高码率的H264或WMV封装的VC-1 会提示:

************************************************
**** Your system is too SLOW to play this! ****
************************************************

Possible reasons, problems, workarounds:
– Most common: broken/buggy _audio_ driver
– Try -ao sdl or use the OSS emulation of ALSA.
– Experiment with different values for -autosync, 30 is a good start.
– Slow video output
– Try a different -vo driver (-vo help for a list) or try -framedrop!
– Slow CPU
– Don’t try to play a big DVD/DivX on a slow CPU! Try some of the lavdopts,
e.g. -vfm ffmpeg -lavdopts lowres=1:fast:skiploopfilter=all.
– Broken file
– Try various combinations of -nobps -ni -forceidx -mc 0.
– Slow media (NFS/SMB mounts, DVD, VCD etc)
– Try -cache 8192.
– Are you using -cache to play a non-interleaved AVI file?
– Try -nocache.
Read DOCS/HTML/en/video.html for tuning/speedup tips.
If none of this helps you, read DOCS/HTML/en/bugreports.html.

当然,上面说的都是废话。最有效的方法还是换cpu 或显卡(硬解)。不过事实的真相是FFMPEG的效率还是不高,同样的配置在win 下用coreavc 解码无问题。

即使我用了下面的参数做了我认为最大程度的优化依然没有什么改观:

gmplayer -cache 8042 -demuxer +44 -lavdopts fast:threads=2 -ao sdl -vo gl_nosw -noskip -mc 0

也许是时候考虑HD6XXX ,vaapi(libva) , libxv ,xvba , fglrx 这套玩意了

3.遇到有问题的H264或VC1 视频可以尝试更换解码器,当然其他编码遇到问题也可以尝试更换 。方法是用mediainfo 找fourcc ,然后参照这个表(很全,很强大)去找解码器:http://www.mplayerhq.hu/DOCS/codecs-status.html

ARM9(v4) MMU分析

MMU听起来熟悉又陌生的,熟悉是因为他就是和X86的内存页机制差不多的一个东西。陌生是因为嵌入式ARM中这个MMU是可选的,也就是可以用MMU 也可以不用,不用的话整个内存就是平坦的,而且在管理细节上和X86不同。

 

一、MMU是什么?
    MMU,英文名称为Memory Manage Unit, 中文可以为“内存管理单元”,或者“存储器管理单元”。MMU是硬件设备,它与virtual memory是紧密联系在一起的。
    看一下s3c2410 datasheet Appendix 1中关于ARM920T的介绍(因为s3c2410采用的是ARM920T的处理器)。对ARM9系列处理器有如下几种:
    --ARM9TDMI(ARM9TDMI Core)
--ARM940T(ARM9TDMI core plus cache and protection unit)
--ARM920T(ARM9TDMI core plus cache and MMU)
    可见ARM920T具备了MMU功能部件。而且还有cache。它采用了一种变形的Harvard架构,拥有16KB的Instruction cache和16KB的Data cache,MMU和cache有密切的联系,后面会谈到。
    总之,由于s3c2410这款SoC采用了ARM920T的处理器(处理器内核为ARM9TDMI,关于这些命名的区分在前面已经讨论过了),所以拥有了MMU和cache。有了这个硬件基础,软件上才可能使用这个功能。那么,现在的问题是,s3c2410拥有MMU,那么MMU到底有什么用呢?还是从历史发展的角度看一下。
二、从历史发展的角度看MMU的作用
    这一部分可结合蔡于清的讲解【网址:http://www.another-prj.com/viewthread.php?tid=28&extra=page%3D1】来看,下面的大部分内容转载此处,针对自己的理解做了一些扩充性说明。只是需要注意的是,在蔡于清此部分的讲解中,有几处小的错误,完成此部分的讲解后可以进行更正。
    MMU功能部件是与虚拟内存技术(virtual memory)紧密联系在一起的。
    第一阶段:最初,计算机内存很小,而且非常昂贵,大多数都是以KB为单位的。相应的,当时程序规模很小,不复杂,所以内存还是能够满足需求的。在看《Linkers and Loaders》的时候,也是从这个阶段讲解,不过此书的核心视角是从Linkers和Loaders的发展来看的。也就是,计算机刚刚出现时,还是比较简陋的,各种复杂的技术是伴随着人们需求的提高而出现的。把握住这一点,就可以从需求的角度入手探讨技术,可以分析它如何满足了这样的需求。通过这种分析,理解上就比较简单一些了。
    第二阶段:程序规模扩大,考虑到成本问题,出现了overlay技术,也就是内存覆盖策略。基本的原理就是把程序分割成许多称为“覆盖块”的片断。覆盖块0首先加载运行,结束时调用另一个覆盖块。覆盖块的调度是由OS来完成的,但是事先需要分割,这部分工作是程序员借助Linkers来完成的。但是毕竟枯燥,由此带来的开销也比较大。于是进入第三个阶段。
    第三阶段:出现virtual memory。虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上。比如对一个16MB的程序和一个内存只有4MB的机器,OS通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由程序员进行分割。
伴随着这种技术的出现,“virtual address,即VA”和“physical address, 即PA”也就出现了。一般来说,CPU看到的地址是VA,VA是有地址线来决定的。比如,s3c2410是32位的SoC,那么它的寻址空间为2^32=4GB,那么VA空间也就是4GB。但是在嵌入式系统中,物理存储器是不会有这么大的。现在这块s3c2410的实际内存SDRAM也就64MB,远远小于4GB。也就是说,VA是4GB,PA是64MB,PA的地址空间是VA地址空间的子集。既然PA没有VA那么大,而且CPU只能看到VA,那么CPU如何找到PA呢?这也正是MMU的基本作用之一,就是提供VA到PA的转换机制,除了硬件的支持外,软件上实际就是维护一张表,表中的内容是VA到PA的转换法则。由于有了MMU,那么就可以实现利用VA找到实际物理内存区域。
    现在讨论为什么要实现VA到PA的映射。就ARM而言,系统上电后,CPU的PC指向0x00000000或者0xffff0000,这是由CPU的设计者决定的。在这个位置,一般安排非易失性存储器地址空间,比如rom,flash等。但是flash等响应速度慢,这就称为提高系统性能的一个瓶颈。而sdram则具有很高的响应速度,为了提高系统运行速度,可以把flash中的应用程序下载到sdram中执行,也就是一个简单的loader的功能实现。这样就出现一个问题,ARM响应exception时,程序指针指向固定的VA,比如,假设发生了IRQ中断,那么PC执行0x00000018(如果是高端启动,则指向0xffff0018处。)但是此处仍然为非易失性存储器,也就是说,程序的一部分仍然在flash或者rom中执行。这时可以利用MMU,把sdram的地址映射到0x00000000起始的一片连续地址空间,而把原来flash映射到其他不相冲突的存储空间位置。例如,flash的地址范围0x00000000-0x00ffffff,sdram的地址范围0x30000000-0x31ffffff。那么可以把sdram映射到0x00000000-0x1fffffff(此处地址空间未被占用)。映射完成后,如果处理器异常,假设依然为IRQ中断,pc指向0x00000018,但是pc实际上是从物理地址0x30000018处读取指令。通过mmu的映射,可以实现系统运行的加速。这个地方也可以说明bootloader中常见的中断向量表的设置,为什么有些使用b,有些使用ldr了。【b的跳转空间只能是+-32M,而ldr可以大的多了。】
    在实际的应用过程中,还可能会把两片不连续的物理地址空间分配给sdram,而在os中,习惯上把sdram的空间连续起来,方便实现动态内存管理。通过mmu可以实现不连续的物理地址空间映射为虚拟地址空间。
    另外一个需求就是,实现不同的运行级别,那么一些关键的代码可以设定不被普通应用程序访问。这也是通过mmu控制访问权限来实现的。
    综上三个阶段所述,可见MMU的作用主要就是两个:
    · 实现VA到PA的映射(可以因此实现方便的动态内存管理)
    · 实现不同的访问权限。
三、结合s3c2410来分析MMU的几处硬件特点
    首先看看ARM920T的框图:
    可以验证前面的几个概念:
    ·位于中心的ARM9TDMI Processor Core发出的地址有两种,IVA和DVA,都是VA。其中I代表Instruction, D代表Data。也就是说,CPU核心看到的都是32bits的VA。
    ·Dcache、Icache、Dmmu、Immu看到的都是对应的MVA(modified virtual address),这个是比较复杂的地方,下面专门拿出这个来讲解。
    ·MMU处理后的输出地址都是对应的PA,通过AMBA Bus Interface连接到ASB总线上面。
    这样,从硬件上对地址的概念就比较清晰了。也可以很明显的看出MMU的功能:将VA转换成PA。但是现在存在的一个问题是,MVA是什么,为什么要用到MVA?
    可以看CP15协处理器的register 13。这个寄存器是进程识别寄存器,主要的操作如下:
Reading from CP15 register 13 returns the value of the process identifier. Writing CP15register 13 updates the process identifier to the value in bits [31:25]. Bits [24:0]should be zero.
    寄存器的字格式为:
    很清晰,ProcID为7bits,剩下的25bits should be zero,也就是可以实现2^25=32M的地址对齐。从这个道理上讲,每个进程拥有32M的MVA地址空间,而最多支持的进程数为2^7=128个。这样,128*32M=4GB,正是全部的虚拟地址空间。但是,英文的datasheet上却并非如此,写的记录数字为64个进程,同样每个进程32M,怎么可能达到4GB?参看下图:
    我觉得上图中的63应该改为127。因为这个63处不可能对应4GB,而应该对应2GB。判断此处属于datasheet的错误。
    还有,这个procID是何时,有谁写入的?有谁来维护?根据推断,在bootloader阶段,只需要一个进程就可以了,所以,procID一直都是复位后默认的0,不需要改变。但是后面有了OS后,要想实现多进程,那么就需要对此维护了。所以procID的维护者是系统软件OS。在创建一个新进程的时候,要把进程号写入procID。
    另外,关于MVA部分的转换公式,实际上还是有疑问的。
Addresses issued by the ARM9TDMI core in the range 0 to 32MB are translated by CP15register 13, the ProcID register. Address A becomes A + (ProcID x 32MB). It is thistranslated address that is seen by both the Caches and MMU. Addresses above 32MB undergo no translation.
    写成伪代码,可以参考《s3c2410完全开发》。
if VA < 32M then
MVA = VA | (ProcID << 25)
else
MVA = VA
    thisway.diy说利用PID来生成MVA的目的是为了减少切换进程时的代价:如果两个进程占用的VA有重叠,不进行上述处理的话,当进行进程切换时必须进行VA到PA的重新映射,这就需要重新建立页表,使无效cache和TLB等等,代价很大。但是如果进行上述处理的话,进程切换就省事多了:假设两个进程1、2运行时的VA都是0-32M,则它们的MVA分别是(0x02000000-0x03ffffff)、(0x04000000-0x05ffffff),前面看到的MMU、cache使用MVA而不是使用VA,这样就不必进行重建页表等工作了。
    但是这里带来的一个问题是,如果进程运行时的VA小于32M,那么根据PID的不同,可以达到4GB空间的任意部分,也就是,虽然可以避免运行VA小于32M时的不同进程的“撞车”,但是同时带来的是VA小于32M可能与VA大于32M的进程产生了“撞车”。这样不是更为普遍吗?现在从原理上还不能理解。翻看《ARM Architecture Reference Manual》,发现对于ARM核,如果采用MVA,那么进程切换实际上对应着Fast context switch extension,不知道原理是什么。对于研究bootloader来说,现在不设计到多进程,整个系统就是一个独立的单进程,PID就是默认的0x0。这个问题可能要后推了。
四、提出几个问题
    1、为什么在启动阶段使用了MMU?是否可以不用?
    这个问题已经解决。实际上,在nand flash启动的情况下,可以不使用MMU。因为一是中断向量表是放在sram里,响应速度比sdram还要快。另外,在bootloader阶段,只有一个进程,不存在多进程的内存空间重叠的问题。也因为一个进程,所以单纯的PA就满足需求,没有必要用VA。开始时,也不需要区分访问权限。大量的工作,比如进程切换、权限访问等等,都是在EOS中处理的。所以,这种情况下,可以不使用MMU。
    那么,为什么、、在启动时开启MMU呢?原因也是比较简单的,就是追求系统运行的高效。因为s3c2410的Icache不受MMU的影响,而Dcache和write buffer则必须开启了MMU功能之后,才能使用。而使用Dcache和write buffer后,对系统运行速度的提高是非常明显的,后面还将通过实验来验证这一点。也就是说,在nand flash启动时,使用了MMU,主要是为了获得Dcache和write buffer的使用权,借此提高系统运行的性能。
    2、使用了MMU,那么软硬件是如何分工协作的?
    这个基本搞清楚了,但是还有一个遗留问题。针对于s3c2410,可以分为如下几个阶段:
    · 第一阶段  软件准备
    MMU在软件上的实现过程,实际上就是一个查表映射的过程。建立页表(translation table)是MMU功能的重要的一步。页表就是内存的一块区域,由一个个固定格式的entry组成。其中每个entry对应一个VA到PA的转换,每一项的长度是一个word,还可以完成访问权限和缓冲特性的限定。在软件上,就是要把这个表填好。重映射就是修改相应的entry,改变了原来的映射规则,很简单。
    这步工作是要软件提前准备的。需要注意的是,明确如何找到这个页表。对于表的查找,需要知道表的基地址和偏移地址,在cp15的register 2用于保存页表的基地址,这样就可以查找到相应的PA了。
    · 第二阶段 硬件完成VA-MVA
    硬件根据ARM9TDMI发出的VA和CP15的register 13来自动生成MVA。
    · 第三个阶段
    硬件自动实现cache查询,如果没有,则根据cp15的register 2和MVA找到translation table中的entry,实现相应的PA转换,读取内存,然后根据cache算法更新cache。也就是说,这个阶段也是硬件实现的。不过软件上对cache要进行相应的管理,这个地方的算法相对还是比较复杂的。
    综上,对单进程而言,软件操作上就是维护translation table,并且处理好cache相关操作。

linux kernel 面试题

1) Linux中主要有哪几种内核锁?

2) Linux中的用户模式和内核模式是什么含意?

3) 怎样申请大块内核内存?

4) 用户进程间通信主要哪几种方式?

5) 通过伙伴系统申请内核内存的函数有哪些?

6) 通过slab分配器申请内核内存的函数有?

7) Linux的内核空间和用户空间是如何划分的(以32位系统为例)?

8) vmalloc()申请的内存有什么特点?

9) 用户程序使用malloc()申请到的内存空间在什么范围?

10) 在支持并使能MMU的系统中,Linux内核和用户程序分别运行在物理地址模式还是虚拟地址模式?

11) ARM处理器是通过几级也表进行存储空间映射的?

12) Linux是通过什么组件来实现支持多种文件系通的?

13) Linux虚拟文件系统的关键数据结构有哪些?(至少写出四个)

14) 对文件或设备的操作函数保存在那个数据结构中?

15) Linux中的文件包括哪些?

16) 创建进程的系统调用有那些?

17) 调用schedule()进行进程切换的方式有几种?

18) Linux调度程序是根据进程的动态优先级还是静态优先级来调度进程的?

19) 进程调度的核心数据结构是哪个?

20) 如何加载、卸载一个模块?

21) 模块和应用程序分别运行在什么空间?

22) Linux中的浮点运算由应用程序实现还是内核实现?

23) 模块程序能否使用可链接的库函数?

24) TLB中缓存的是什么内容?

25) Linux中有哪几种设备?

26) 字符设备驱动程序的关键数据结构是哪个?

27) 设备驱动程序包括哪些功能函数?

28) 如何唯一标识一个设备?

29) Linux通过什么方式实现系统调用?

30) Linux软中断和工作队列的作用是什么?

1. Linux中主要有哪几种内核锁?

Linux的同步机制从2.0到2.6以来不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随Linux从单处理器到对称多处理器的过渡;

伴随着从非抢占内核到抢占内核的过度。Linux的锁机制越来越有效,也越来越复杂。

Linux的内核锁主要是自旋锁和信号量。

自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图请求一个已被争用(已经被持有)的自旋锁,那么这个线程就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的执行线程便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的执行线程同时进入临界区。

Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。

信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。

Linux 内核中的同步机制:原子操作、信号量、读写信号量和自旋锁的API,另外一些同步机制,包括大内核锁、读写锁、大读者锁、RCU (Read-Copy Update,顾名思义就是读-拷贝修改),和顺序锁。

2. Linux中的用户模式和内核模式是什么含意?

MS-DOS等操作系统在单一的CPU模式下运行,但是一些类Unix的操作系统则使用了双模式,可以有效地实现时间共享。在Linux机器上,CPU要么处于受信任的内核模式,要么处于受限制的用户模式。除了内核本身处于内核模式以外,所有的用户进程都运行在用户模式之中。

内核模式的代码可以无限制地访问所有处理器指令集以及全部内存和I/O空间。如果用户模式的进程要享有此特权,它必须通过系统调用向设备驱动程序或其他内核模式的代码发出请求。另外,用户模式的代码允许发生缺页,而内核模式的代码则不允许。

在2.4和更早的内核中,仅仅用户模式的进程可以被上下文切换出局,由其他进程抢占。除非发生以下两种情况,否则内核模式代码可以一直独占CPU:

(1) 它自愿放弃CPU;

(2) 发生中断或异常。

2.6内核引入了内核抢占,大多数内核模式的代码也可以被抢占。

3. 怎样申请大块内核内存?

在Linux内核环境下,申请大块内存的成功率随着系统运行时间的增加而减少,虽然可以通过vmalloc系列调用申请物理不连续但虚拟地址连续的内存,但毕竟其使用效率不高且在32位系统上vmalloc的内存地址空间有限。所以,一般的建议是在系统启动阶段申请大块内存,但是其成功的概率也只是比较高而已,而不是100%。如果程序真的比较在意这个申请的成功与否,只能退用“启动内存”(Boot Memory)。下面就是申请并导出启动内存的一段示例代码:

void* x_bootmem = NULL;

EXPORT_SYMBOL(x_bootmem);

unsigned long x_bootmem_size = 0;

EXPORT_SYMBOL(x_bootmem_size);

static int __init x_bootmem_setup(char *str)

{

x_bootmem_size = memparse(str, &str);

x_bootmem = alloc_bootmem(x_bootmem_size);

printk(“Reserved %lu bytes from %p for x\n”, x_bootmem_size, x_bootmem);

return 1;

}

__setup(“x-bootmem=”, x_bootmem_setup);

可见其应用还是比较简单的,不过利弊总是共生的,它不可避免也有其自身的限制:

内存申请代码只能连接进内核,不能在模块中使用。

被申请的内存不会被页分配器和slab分配器所使用和统计,也就是说它处于系统的可见内存之外,即使在将来的某个地方你释放了它。

一般用户只会申请一大块内存,如果需要在其上实现复杂的内存管理则需要自己实现。

在不允许内存分配失败的场合,通过启动内存预留内存空间将是我们唯一的选择。

4. 用户进程间通信主要哪几种方式?

(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。

(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。

(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。

(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺

(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

(6)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

(7)套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

5. 通过伙伴系统申请内核内存的函数有哪些?

在物理页面管理上实现了基于区的伙伴系统(zone based buddy system)。对不同区的内存使用单独的伙伴系统(buddy system)管理,而且独立地监控空闲页。相应接口alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。

补充知识:

1.原理说明

Linux内核中采 用了一种同时适用于32位和64位系统的内 存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系 统中,用到了四级页表。

* 页全局目录(Page Global Directory)

* 页上级目录(Page Upper Directory)

* 页中间目录(Page Middle Directory)

* 页表(Page Table)

页全局目录包含若干页上级目录的地址,页上级目录又依次包含若干页中间目录的地址,而页中间目录又包含若干页表的地址,每一个页表项指 向一个页框。Linux中采用4KB大小的 页框作为标准的内存分配单元。

多级分页目录结构

1.1.伙伴系统算法

在实际应用中,经常需要分配一组连续的页框,而频繁地申请和释放不同大小的连续页框,必然导致在已分配页框的内存块中分散了许多小块的 空闲页框。这样,即使这些页框是空闲的,其他需要分配连续页框的应用也很难得到满足。

为了避免出现这种情况,Linux内核中引入了伙伴系统算法(buddy system)。把所有的空闲页框分组为11个 块链表,每个块链表分别包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续页框的页框块。最大可以申请1024个连 续页框,对应4MB大小的连续内存。每个页框块的第一个页框的物理地址是该块大小的整数倍。

假设要申请一个256个页框的块,先从256个页框的链表中查找空闲块,如果没有,就去512个 页框的链表中找,找到了则将页框块分为2个256个 页框的块,一个分配给应用,另外一个移到256个页框的链表中。如果512个页框的链表中仍没有空闲块,继续向1024个页 框的链表查找,如果仍然没有,则返回错误。

页框块在释放时,会主动将两个连续的页框块合并为一个较大的页框块。

1.2.slab分配器

slab分配器源于 Solaris 2.4 的 分配算法,工作于物理内存页框分配器之上,管理特定大小对象的缓存,进行快速而高效的内存分配。

slab分配器为每种使用的内核对象建立单独的缓冲区。Linux 内核已经采用了伙伴系统管理物理内存页框,因此 slab分配器直接工作于伙伴系 统之上。每种缓冲区由多个 slab 组成,每个 slab就是一组连续的物理内存页框,被划分成了固定数目的对象。根据对象大小的不同,缺省情况下一个 slab 最多可以由 1024个页框构成。出于对齐 等其它方面的要求,slab 中分配给对象的内存可能大于用户要求的对象实际大小,这会造成一定的 内存浪费。

2.常用内存分配函数

2.1.__get_free_pages

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

__get_free_pages函数是最原始的内存分配方式,直接从伙伴系统中获取原始页框,返回值为第一个页框的起始地址。__get_free_pages在实现上只是封装了alloc_pages函 数,从代码分析,alloc_pages函数会分配长度为1<

2.2.kmem_cache_alloc

struct kmem_cache *kmem_cache_create(const char *name, size_t size,

size_t align, unsigned long flags,

void (*ctor)(void*, struct kmem_cache *, unsigned long),

void (*dtor)(void*, struct kmem_cache *, unsigned long))

void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)

kmem_cache_create/ kmem_cache_alloc是基于slab分配器的一种内存分配方式,适用于反复分配释放同一大小内存块的场合。首先用kmem_cache_create创建一个高速缓存区域,然后用kmem_cache_alloc从 该高速缓存区域中获取新的内存块。 kmem_cache_alloc一次能分配的最大内存由mm/slab.c文件中的MAX_OBJ_ORDER宏 定义,在默认的2.6.18内核版本中,该宏定义为5, 于是一次最多能申请1<<5 * 4KB也就是128KB的 连续物理内存。分析内核源码发现,kmem_cache_create函数的size参数大于128KB时会调用BUG()。测试结果验证了分析结果,用kmem_cache_create分 配超过128KB的内存时使内核崩溃。

2.3.kmalloc

void *kmalloc(size_t size, gfp_t flags)

kmalloc是内核中最常用的一种内存分配方式,它通过调用kmem_cache_alloc函 数来实现。kmalloc一次最多能申请的内存大小由include/linux/Kmalloc_size.h的 内容来决定,在默认的2.6.18内核版本中,kmalloc一 次最多能申请大小为131702B也就是128KB字 节的连续物理内存。测试结果表明,如果试图用kmalloc函数分配大于128KB的内存,编译不能通过。

2.4.vmalloc

void *vmalloc(unsigned long size)

前面几种内存分配方式都是物理连续的,能保证较低的平均访问时间。但是在某些场合中,对内存区的请求不是很频繁,较高的内存访问时间也 可以接受,这是就可以分配一段线性连续,物理不连续的地址,带来的好处是一次可以分配较大块的内存。图3-1表 示的是vmalloc分配的内存使用的地址范围。vmalloc对 一次能分配的内存大小没有明确限制。出于性能考虑,应谨慎使用vmalloc函数。在测试过程中, 最大能一次分配1GB的空间。

Linux内核部分内存分布

2.5.dma_alloc_coherent

void *dma_alloc_coherent(struct device *dev, size_t size,

ma_addr_t *dma_handle, gfp_t gfp)

DMA是一种硬件机制,允许外围设备和主存之间直接传输IO数据,而不需要CPU的参与,使用DMA机制能大幅提高与设备通信的 吞吐量。DMA操作中,涉及到CPU高速缓 存和对应的内存数据一致性的问题,必须保证两者的数据一致,在x86_64体系结构中,硬件已经很 好的解决了这个问题, dma_alloc_coherent和__get_free_pages函数实现差别不大,前者实际是调用__alloc_pages函 数来分配内存,因此一次分配内存的大小限制和后者一样。__get_free_pages分配的内 存同样可以用于DMA操作。测试结果证明,dma_alloc_coherent函 数一次能分配的最大内存也为4M。

2.6.ioremap

void * ioremap (unsigned long offset, unsigned long size)

ioremap是一种更直接的内存“分配”方式,使用时直接指定物理起始地址和需要分配内存的大小,然后将该段 物理地址映射到内核地址空间。ioremap用到的物理地址空间都是事先确定的,和上面的几种内存 分配方式并不太一样,并不是分配一段新的物理内存。ioremap多用于设备驱动,可以让CPU直接访问外部设备的IO空间。ioremap能映射的内存由原有的物理内存空间决定,所以没有进行测试。

2.7.Boot Memory

如果要分配大量的连续物理内存,上述的分配函数都不能满足,就只能用比较特殊的方式,在Linux内 核引导阶段来预留部分内存。

2.7.1.在内核引导时分配内存

void* alloc_bootmem(unsigned long size)

可以在Linux内核引导过程中绕过伙伴系统来分配大块内存。使用方法是在Linux内核引导时,调用mem_init函数之前 用alloc_bootmem函数申请指定大小的内存。如果需要在其他地方调用这块内存,可以将alloc_bootmem返回的内存首地址通过EXPORT_SYMBOL导 出,然后就可以使用这块内存了。这种内存分配方式的缺点是,申请内存的代码必须在链接到内核中的代码里才能使用,因此必须重新编译内核,而且内存管理系统 看不到这部分内存,需要用户自行管理。测试结果表明,重新编译内核后重启,能够访问引导时分配的内存块。

2.7.2.通过内核引导参数预留顶部内存

在Linux内核引导时,传入参数“mem=size”保留顶部的内存区间。比如系统有256MB内 存,参数“mem=248M”会预留顶部的8MB内存,进入系统后可以调用ioremap(0xF800000,0x800000)来申请这段内存。

3.几种分配函数的比较

分配原理最大内存其他

__get_free_pages直接对页框进行操作4MB适用于分配较大量的连续物理内存

kmem_cache_alloc基于slab机制实现128KB适合需要频繁申请释放相同大小内存块时使用

kmalloc基于kmem_cache_alloc实现128KB最常见的分配方式,需要小于页框大小的内存时可以使用

vmalloc建立非连续物理内存到虚拟地址的映射物理不连续,适合需要大内存,但是对地址连续性没有要求的场合

dma_alloc_coherent基于__alloc_pages实现4MB适用于DMA操 作

ioremap实现已知物理地址到虚拟地址的映射适用于物理地址已知的场合,如设备驱动

alloc_bootmem在启动kernel时,预留一段内存,内核看不见小于物理内存大小,内存管理要求较高

超流水线,超标量和SIMD

继续回顾整理自己的己

流水线

流水线技术是一种将每条指令分解为多步,并让各步操作重叠,从而实现几条指令并行处理的技术。程序中的指令仍是一条条顺序执行,但可以预先取若干条指令,并在当前指令尚未执行完时,提前启动后续指令的另一些操作步骤。这样显然可加速一段程序的运行过程。
市场上推出的各种不同的1 6位/ 3 2位微处理器基本上都采用了流水线技术。如8 0 4 8 6和P e n t i u m均使用了6步流水线结构,流水线的6步为:
( 1 ) 取指令。C P U从高速缓存或内存中取一条指令。
( 2 ) 指令译码。分析指令性质。
( 3 ) 地址生成。很多指令要访问存储器中的操作数,操作数的地址也许在指令字中,也许要经过某些运算得到。
( 4 ) 取操作数。当指令需要操作数时,就需再访问存储器,对操作数寻址并读出。
( 5 ) 执行指令。由A L U执行指令规定的操作。
( 6 ) 存储或”写回”结果。最后运算结果存放至某一内存单元或写回累加器A。
在理想情况下,每步需要一个时钟周期。当流水线完全装满时,每个时钟周期平均有一条指令从流水线上执行完毕,输出结果,就像轿车从组装线上开出来一样。P e n t i u m、Pentium Pro和Pentium II处理器的超标量设计更是分别结合了两条和三条独立的指令流水线,每条流水线平均在一个时钟周期内执行一条指令,所以它们平均一个时钟周期分别可执行2条和3条指令。
流水线技术是通过增加计算机硬件来实现的。例如要能预取指令,就需要增加取指令的硬件电路,并把取来的指令存放到指令队列缓存器中,使M P U能同时进行取指令和分析、执行指令的操作。因此,在1 6位/3 2位微处理器中一般含有两个算术逻辑单元A L U,一个主A L U用于执行指令,另一个A L U专用于地址生成,这样才可使地址计算与其它操作重叠进行。

超流水线

超级流水线以增加流水线级数的方法来缩短机器周期,相同的时间内超级流水线执行了更多的机器指令。采用简单指令以加快执行速度是所有流水线的共同特点,但超级流水线配置了多个功能部件和指令译码电路,采用多条流水线并行处理,还有多个寄存器端口和总线,可以同时执行多个操作,因此比普通流水线执行的更快,在一个机器周期内可以流出多条指令。

一般而言,CPU执行一条指令需要经过以下阶段:取指->译码->地址生成->取操作数->执行->写回,每个阶段都要消耗一个时钟周期,同时每个阶段的计算结果在周期结束以前都要发送到阶段之间的锁存器上,以供下一个阶段使用。所以,每个时钟周期所消耗的时间就是由以上几个阶段中的耗时最长的那个决定的。假设耗时最长的阶段耗时为s秒,那么时钟频率就只能设计到1/s赫兹(这里不考虑阶段间信号传递的时间和锁存器的反应时间)。

那么,要提高时钟频率,一种可能的方法就是减小每个阶段的时间消耗。其中一种最简单的办法,就是将每个阶段再进行细分成更小的步骤,同样是细分后的每个阶 段,单个阶段的运算量小了,单位耗时s也就减少,这样实际上就是提高了时钟频率。这种将标准流水线细分的技术,就是超级流水线技术。当然,流水线和超级流 水线之间并没有很明显的区别。这样的技术,虽然提高了CPU的主频,但是也带来了很大的副作用:

首先,细分后的每一个阶段都要在其后使用锁存器锁存,因此将一个阶段细分为N的子阶段并不能让单位时间减少到s/N, 而是s/N + d, 其中d为锁存器的反应时间。这实际上就是增加了多余的时间消耗。

其次,随着流水线级数的加深,一旦分支预测出现错误,会导致CPU中大量的指令作废,这样的消耗是十分巨大的。

以上原因,也就是什么Pentium IV具有31级的流水线,指令的执行效率却赶不上只有14级流水线的Pentium M。

流水线技术针对的都是一条指令所做的优化,如果要进行多指令优化则需要下面的超标量技术

超标量
  超标量(superscalar)是指在CPU中有一条以上的流水线,并且每时钟周期内可以完成一条以上的指令,这种设计就叫超标量技术。 其实质是以空间换取时间。而超流水线是通过细化流水、提高主频,使得在一个机器周期内完成一个甚至多个操作,其实质是以时间换取空间。

SIMD

SIMD是Single Instruction Multiple Data(单指令流多数据流),由名称我们就能猜到SIMD技术的真正含义,以及该技术促进处理器性能提高的原因。事实上,SIMD回答了与时钟速度提高 比较而言,如何导致了处理时间的非比例的减少。原理很简单,就让我们看一下奇迹是怎么发生的吧。
通常,汇编程序的处理数据及指令依次在处理器 中处理执行,一个接一个,每个CPU的周期可以执行一个操作或者一个复杂操作的一部分。因此,要提高处理速度可以提高处理器的应答频率或时钟速率,因而提 高连续工作量的处理速度。但还存在另一种完全不同的办法,也即改进逐个处理数据的方式。试想一下,基于不同的数据集,实现相同操作的并行处理该多好啊。这 恰恰是SIMD技术要做的。SIMD实现了一个单独的指令,它可以实现同时在多个数据包上的运算。
SIMD汇编程序实现了同一指令同时在多个 寄存器上的执行。相比之下,旧有的普通汇编程序在每个所要进行数据处理的寄存器上,都要调用完全相同的指令。从技术角度讲,这不完全正确,但对于我们来 说,这种理解已经足够。实际上,SIMD指令也会一个指令对应一个寄存器,其中的诀窍是寄存器中并非仅仅包含一个数据包,而应该是多个。可以说,SIMD 指令使用的寄存器比旧有的32位寄存器要大一些。SIMD寄存器或多或少有点象你可以同时操作的一个数组内的变量,在同一CPU周期内并行执行。
或许举个应用的例子更容易理解。比如一个三维向量,需要用3个32位大小的浮点数来描述。不使用SIMD的情况下就要动用3个32位的寄存器来描述这个向量。如果进行两个向量的想加运算则需要6个32位寄存器和3次加法运算。如果使用SIMD 技术那么将会启用SIMD的专用寄存器,宽度96位,然后用专用的SIMD指令做一次加法就能完成全部运算。

这里之所以能一次就能完成全部运算,就是因为SIMD指令及SIMD 寄存器被SIMD预处理单元拆分多个相同而且并行的执行流,处理完毕后再合并在一起,得出结果。

注意SIMD的实现针对的是专用指令集,对于intel 而言就是SSE 对于amd 而言就是3D now。

[转]什么是checkpoint

在数据库系统中,写日志和写数据文件是数据库中IO消耗最大的两种操作,在这两种操作中写数据文件属于分散写,写日志文件是顺序写,因此为了保证数据库的性能,通常数据库都是保证在提交(commit)完成之前要先保证日志都被写入到日志文件中,而脏数据块着保存在数据缓存(buffer cache)中再不定期的分批写入到数据文件中。也就是说日志写入和提交操作是同步的,而数据写入和提交操作是不同步的。这样就存在一个问题,当一个数据库崩溃的时候并不能保证缓存里面的脏数据全部写入到数据文件中,这样在实例启动的时候就要使用日志文件进行恢复操作,将数据库恢复到崩溃之前的状态,保证数据的一致性。检查点是这个过程中的重要机制,通过它来确定,恢复时哪些重做日志应该被扫描并应用于恢复。

一般所说的checkpoint是一个数据库事件(event),checkpoint事件由checkpoint进程(LGWR/CKPT进程)发出,当checkpoint事件发生时DBWn会将脏块写入到磁盘中,同时数据文件和控制文件的文件头也会被更新以记录checkpoint信息。

checkpoint的作用

checkpoint主要2个作用:

1.      保证数据库的一致性,这是指将脏数据写入到硬盘,保证内存和硬盘上的数据是一样的;

2.      缩短实例恢复的时间,实例恢复要把实例异常关闭前没有写出到硬盘的脏数据通过日志进行恢复。如果脏块过多,实例恢复的时间也会很长,检查点的发生可以减少脏块的数量,从而提高实例恢复的时间。

通俗的说checkpoint就像word的自动保存一样。

检查点分类

完全检查点(Normal checkpoint)
增量检查点(Incremental checkpoint)
checkpoint相关概念术语

在说明checkpoint工作原理之前我们先了解一些相关的术语。

RBA(Redo Byte Address), Low RBA(LRBA), High RBA(HRBA)

RBA就是重做日志块(redo log block)的地址,相当与数据文件中的ROWID,通过这个地址来定位重做日志块。RBA由三个部分组成:

1.      日志文件序列号(4字节)

2.      日志文件块编号(4字节)

3.      重做日志记录在日志块中的起始偏移字节数(2字节)

通常使用RBA的形式有:

LRBA

数据缓存(buffer cache)中一个脏块第一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为LRBA。

HRBA

数据缓存(buffer cache)中一个脏块最近一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为HRBA。

checkpoint RBA

当一个checkpoint事件发生的时候,checkpoint进程会记录下当时所写的重做日志块的地址即RBA,此时记录的RBA被称为checkpoint RBA。从上一个checkpoint RBA到当前的checkpoint RBA之间的日志所保护的buffer cache中的脏块接下来将会被写入到数据文件当中去。

Buffer checkpoint Queues(BCQ)

Oracle将所有在数据缓存中被修改的脏块按照LRBA顺序的组成一个checkpoint队列,这个队列主要记录了buffer cache第一次发生变化的时间顺序,然后有DBWn进程根据checkpoint队列顺序将脏块写入到数据文件中,这样保证了先发生变更的buffer能先被写入到数据文件中。BCQ的引入是为了支持增量checkpoint的。

Active checkpoint Queue(ACQ)

ACQ中包含了所有活动的checkpoint请求。每次有新checkpoint请求是都会在ACQ中增加一条记录,ACQ记录中包含了相应的checkpoint RBA。checkpoint完成以后相应的记录将被移出队列。

完全检查点(normal checkpoint)

完全检查点工作过程

一个checkpoint操作可以分成三个不同的阶段:

第一阶段,checkpoint进程开始一个checkpoint事件,并记录下checkpoint RBA,这个通常是当前的RBA。
第二阶段,checkpoint进程通知DBWn进程将所有checkpoint RBA之前的buffer cache里面的脏块写入磁盘。
确定脏块都被写入磁盘以后进入到第三阶段,checkpoint进程将checkpoint信息(SCN)写入/更新数据文件和控制文件中。
更新SCN的操作由CKPT进程完成,在Oracle 8.0之后CKPT进程默认是被启用的,如果CKPT进程没有启用的话那相应的操作将由LGWR进程完成。

什么时候发生normal checkpoint

下面这些操作将会触发checkpoint事件:

日志切换,通过ALTER SYSTEM SWITCH LOGFILE。
DBA发出checkpoint命令,通过ALTER SYSTEM checkpoint。
对数据文件进行热备时,针对该数据文件的checkpoint也会进行,ALTER TABLESPACE TS_NAME BEGIN BACKUP/END BACKUP。
当运行ALTER TABLESPACE/DATAFILE READ ONLY的时候。
SHUTDOWN命令发出时。
特别注意:

1.      日志切换会导致checkpoint事件发生,但是checkpoint发生却不会导致日志切换。

2.      日志切换触发的是normal checkpoint,而不是大家所说的增量checkpoint,只不过log switch checkpoint的优先级非常低,当一个log switch checkpoint发生的时候它并不会立即的通知DBWn进程去写数据文件,但是当有其它原因导致checkpoint或者是写入数据文件的RBA超过log switch checkpoint的checkpoint RBA的时候,这次的log switch checkpoint将会被标记成完成状态,同时更新控制文件和数据文件头。我们随后可以做个实验验证这个说法。

checkpoint和SCN有什么关系?

在Oracle中SCN相当于它的时钟,在现实生活中我们用时钟来记录和衡量我们的时间,而Oracle就是用SCN来记录和衡量整个Oracle系统的更改。

Oracle中checkpoint是在一个特定的“时间点”发生的,衡量这个“时间点”用的就是SCN,因此当一个checkpoint发生时SCN会被写入文件头中以记录这个checkpoint。

增量checkpoint

增量checkpoint工作过程

因为每次完全的checkpoint都需要把buffer cache所有的脏块都写入到数据文件中,这样就是产生一个很大的IO消耗,频繁的完全checkpoint操作很对系统的性能有很大的影响,为此Oracle引入的增量checkpoint的概念,buffer cache中的脏块将会按照BCQ队列的顺序持续不断的被写入到磁盘当中,同时CKPT进程将会每3秒中检查DBWn的写入进度并将相应的RBA信息记录到控制文件中。

有了增量checkpoint之后在进行实例恢复的时候就不需要再从崩溃前的那个完全checkpoint开始应用重做日志了,只需要从控制文件中记录的RBA开始进行恢复操作,这样能节省恢复的时间。

发生增量checkpoint的先决条件

恢复需求设定(FAST_START_IO_TARGET/FAST_START_MTTR_TARGET)
LOG_checkpoint_INTERVAL参数值
LOG_checkpoint_TIMEOUT参数值
最小的日志文件大小
buffer cache中的脏块的数量
增量checkpoint的特点

增量checkpoint是一个持续活动的checkpoint。
没有checkpoint RBA,因为这个checkpoint是一直都在进行的,所以不存在normal checkpoint里面涉及的checkpoint RBA的概念。
checkpoint advanced in memory only
增量checkpoint所完成的RBA信息被记录在控制文件中。
增量checkpoint可以减少实例恢复时间。
增量checkpoint相关参数设置

log_checkpoint_interval

设定两次checkpoint之间重做日志块(重做日志块和系统数据块是一样的)数,当重做日志块数量达到设定值的时候将触发checkpoint。

log_checkpoint_timeout

设定两次checkpoint之间的间隔时间,当超时值达到时增量checkpoint将被触发。Oracle建议不用这个参数来控制,因为事务(transaction)大小不是按时间等量分布的。将此值设置成0时将禁用此项设置。

fast_start_io_target

因为log_checkpoint_interval主要看的时候重做日志块的数量,并不能反应buffer cache中脏数据块的修改,因此Oracle又引入了这个参数来实现当脏数据块达到一定数量的时候触发checkpoint,不过此参数实际上控制的是恢复时所需IO的数量。

fast_start_mttr_target

·  此参数是在9i中引入用来代替前面的三个参数的,它定义了数据块崩溃后所需要的实例恢复的时间,Oracle在实际上内在的解释成两个参数:fast_start_io_target和log_checkpoint_interval.如果这两个参数没有显式的指定,计算值将生效.。

·  fast_start_mttr_target可以设定的最大值是3600,即一个小时。它的最小值没有设限,但是并不是说可以设置一个任意小的值,这个值会受最小dirty buffer(最小为1000)的限制,同时还会受初始化时间以及文件打开时间的限制。

·  在设置此参数的时候要综合考虑系统的IO,容量以及CPU等信息,要在系统性能和故障恢复时间之间做好平衡。

·  将此参数设置成0时将禁用fast-start checkpointing,这样能见效系统负载但同时会增加系统的恢复时间。

·  如果fast_start_io_target or log_checkpoint_interval被指定,他们会自动覆盖由fast_start_mttr_target参数计算出来的值。

在10g中,数据库能根据各种系统参数的设置值来自动调整检查点的执行频率,以获得最好的恢复时间以及系统的正常运行影响最小。通过自动checkpoint调整,Orach能在系统低IO操作的时候将脏块写入到数据文件中,因此即时DBA没有设置checkpoint相关的参数值或是设置了一个不合理的值的时候系统还是能获得一个很合理的系统恢复时间。

10g中的增量checkpoint更能体现它持续活动的特点,在10g中,增量checkpoint不是在某一个特定的条件下触发,而是由数据库根据系统参数设置自动触发。

与完全checkpoint的区别

完全checkpoint会将checkpoint的信息写入到控制文件以及数据文件头中
增量checkpoint只会将RBA信息写入到控制文件中。
查看系统的checkpoint动作

我们可以通过将LOG_checkpointS_TO_ALERT设置成TRUE来打开checkpoint的trace,这样就可以跟踪checkpoint的操作了。

ALTER SYSTEM SET LOG_checkpointS_TO_ALERT=TRUE;

这设置以后系统的checkpoint将会被记录alert_$SID.log文件中。

在V$DATAFILE_HEADER里面也保存了发生完全checkpoint的时候一些相关信息,包括checkpoint发生时间、对应SCN已经checkpoint的次数。

select file# NO, status, tablespace_name, name, dbms_flashback.get_system_change_number CUR_SCN,

to_char(resetlogs_time, ‘YYYY-MM-DD HH24:MI:SS’)RST_DT, resetlogs_change# RST_SCN,

to_char(checkpoint_time, ‘YYYY-MM-DD HH24:MI:SS’)CKPT_DT, checkpoint_change# CKPT_SCN, checkpoint_count CKPT_CNT

from v$datafile_header;

/**

NO STATUS TABLESPACE_NAME CUR_SCN RST_DT             RST_SCN CKPT_DT            CKPT_SCN CKPT_CNT

— ——- —————- ——– ——————- ——– ——————- ——— ———

1  ONLINE SYSTEM          533541  2008-01-12 16:51:53 446075  2008-08-04 22:03:58 532354   65

2  ONLINE UNDOTBS1        533541  2008-01-12 16:51:53 446075  2008-08-04 22:03:58 532354   28

3  ONLINE SYSAUX          533541  2008-01-12 16:51:53 446075  2008-08-04 22:03:58 532354   65

4  ONLINE USERS           533541  2008-01-12 16:51:53 446075  2008-08-04 22:03:58 532354   64

5  ONLINE EXAMPLE         533541  2008-01-12 16:51:53 446075  2008-08-04 22:03:58 532354   24

*/

完全检查点

–我们先执行一个

ALTER SYSTEM checkpoint;

–下面是alert文件中的数据结果

Mon Aug 4 22:22:082008

Beginning global checkpoint up to RBA [0x8.c9d4.10], SCN: 533714

Completed checkpoint up to RBA [0x8.c9d4.10], SCN: 533714

–我们能看到完全checkpoint发生的SCN 533714

–下面我们再对照下V$DATAFILE_HEADER中的结果

NO STATUS TABLESPACE_NAME CUR_SCN RST_DT             RST_SCN CKPT_DT            CKPT_SCN CKPT_CNT

— ——- —————- ——– ——————- ——– ——————- ——— ———

1  ONLINE SYSTEM          533790  2008-01-12 16:51:53 446075  2008-08-04 22:22:08 533714   66

2  ONLINE UNDOTBS1        533790  2008-01-12 16:51:53 446075  2008-08-04 22:22:08 533714   29

3  ONLINE SYSAUX          533790  2008-01-12 16:51:53 446075  2008-08-04 22:22:08 533714   66

4  ONLINE USERS           533790  2008-01-12 16:51:53 446075  2008-08-04 22:22:08 533714   65

5  ONLINE EXAMPLE         533790  2008-01-12 16:51:53 446075  2008-08-04 22:22:08 533714   25

–看到了么,checkpoint时间和checkpoint的SCN已经被记录到数据文件头中了。

日志切换时的检查点

–我们先做一次日志切换

ALTER SYSTEM SWITCH LOGFILE;

–然后看看alert里面的记录

Mon Aug 4 22:31:39 2008

Beginning log switch checkpoint up to RBA [0x9.2.10], SCN: 534450

Thread 1 advanced to log sequence 9

Current log# 2 seq# 9 mem# 0: /u/app/oracle/oradata/orcl/redo02.log

Mon Aug 4 22:35:58 2008

Completed checkpoint up to RBA [0x9.2.10], SCN: 534450

–我们能看到checkpoint是在过了一段时间(这里是4分钟)之后才完成的

–接着我们来看下V$DATAFILE_HEADER中的结果

NO STATUS TABLESPACE_NAME CUR_SCN RST_DT             RST_SCN CKPT_DT            CKPT_SCN CKPT_CNT

— ——- —————- ——– ——————- ——– ——————- ——— ———

1  ONLINE SYSTEM          534770  2008-01-12 16:51:53 446075  2008-08-04 22:31:44 534450   67

2  ONLINE UNDOTBS1        534770  2008-01-12 16:51:53 446075  2008-08-04 22:31:44 534450   30

3  ONLINE SYSAUX          534770  2008-01-12 16:51:53 446075  2008-08-04 22:31:44 534450   67

4  ONLINE USERS           534770  2008-01-12 16:51:53 446075  2008-08-04 22:31:44 534450   66

5  ONLINE EXAMPLE         534770  2008-01-12 16:51:53 446075  2008-08-04 22:31:44 534450   26

–在这里我们能发现下V$DATAFILE_HEADER里面记录的SCN和日志切换发生的checkpoint的SCN是一样的,

–这就证明了日志切换是会更新数据文件头的,同时日志切换的checkpoint是一个级别比较低的操作,

–它不会立即完成,这也是出于性能上考虑的。

增量checkpoint查看

这段话明天再实验下当前所知只有在LOG_checkpoint_TIMEOUT设置了非0值之后触发的增量checkpoint会在alert文件中有记录,其他条件触发的增量checkpoint都不会记录在alert文件中。

–下面是当LOG_checkpoint_TIMEOUT设置为1800s的时候所产生的增量checkpoint记录

Sun Aug 3 19:08:56 2008

Incremental checkpoint up to RBA [0x8.e17.0], current log tail at RBA [0x8.1056.0]

Sun Aug 3 19:39:00 2008

Incremental checkpoint up to RBA [0x8.1be0.0], current log tail at RBA [0x8.1c6e.0]

Sun Aug 3 20:09:04 2008

Incremental checkpoint up to RBA [0x8.2af5.0], current log tail at RBA [0x8.2b6a.0]

Sun Aug 3 20:39:07 2008

Incremental checkpoint up to RBA [0x8.3798.0], current log tail at RBA [0x8.3851.0]

Sun Aug 3 21:09:10 2008

Incremental checkpoint up to RBA [0x8.47b9.0], current log tail at RBA [0x8.48bb.0]

Sun Aug 3 21:39:14 2008

Incremental checkpoint up to RBA [0x8.548d.0], current log tail at RBA [0x8.5522.0]

Mon Aug 4 21:05:18 2008

查看fast_start_mttr_target

通过查看V$INSTANCE_RECOVERY动态性能视图可以查看一些MTTR相关的信息。

SELECT TARGET_MTTR,ESTIMATED_MTTR,CKPT_BLOCK_WRITES,CKPT_BLOCK_WRITES FROM V$INSTANCE_RECOVERY

TARGET_MTTR

用户设置的参数FAST_START_MTTR_TARGET的值.

ESTIMATED_MTTR

根据目前脏块数目和日志块数目,评估的现在进行恢复所需要的时间.

CKPT_BLOCK_WRITES

检查点写完的块数目.

CKPT_BLOCK_WRITES

额外的因为检查点引起的数据库写入操作(因为不必要的检查点的产生,设置一个非常小的系统恢复时间将会对性能产生负面影响,为了帮助管理员监测这个参数设置较小时对数据库的影响,这个视图显示了这个列)