星期五, 十一月 30, 2007

Locale 详解

locale 是国际化与本土化过程中的一个非常重要的概念,个人认为,对于中文用户来说,通常会涉及到的国际化或者本土化,大致包含三个方面:看中文,写中文,与 window中文系统的兼容和通信。从实际经验上看来,locale的设定与看中文关系不大,但是与写中文,及window分区的挂载方式有很密切的关 系。本人认为就像一个纯英文的Windows能够浏览中文,日文或者意大利文网页一样,你不需要设定locale就可以看中文。那么,为什么要设定 locale呢?什么时候会用到locale呢?  
一、为什么要设定locale 正如前面我所讲的,设定locale与你能否浏览中文的网页没有直接的关系,即便你把locale设置成en_US.ISO-8859-1这样一个标准的 英文locale你照样可以浏览中文的网页,只要你的系统里面有相应的字符集(这个都不一定需要)和合适的字体(如simsun),浏览器就可以把网页翻 译成中文给你看。具体的过程是网络把网页传送到你的机器上之后,浏览器会判断相应的编码的字符集,根据网页采用的字符集,去字体库里面找合适的字体,然后 由文字渲染工具把相应的文字在屏幕上显示出来。  

在下文本人会偶尔把字符集比喻成密码本,个人觉得对于一些东西比较容易理解,假如你不习惯的话,把全文copy到任何文本编辑器,用字符集替换密码本即可。  

那 有时候网页显示乱码或者都是方框是怎么回事呢?个人认为,显示乱码是因为设定的字符集不对(或者没有相应的字符集),例如网页是用UTF-8编码的,你非 要用GB2312去看,而系统根据GB2312去找字体,然后在屏幕上显示,当然是一堆的乱码,也就是说你用一个错误的密码本去翻译发给你的电报,当然内 容那叫一个乱;至于有些时候浏览的网页能显示一部分汉字,但有很多的地方是方框,能够显示汉字说明浏览器已经正确的判断出了网页的编码,并在字体库里面找 到了相应的文字,但是并不是每个字体库都包含某个字符集全部的字体的缘故,有些时候会显示不完全,找一个比较全的支持较多字符集的字体就可以了。  

既然我能够浏览中文网页,那为什么我还要设定locale呢?  

其 实你有没有想过这么一个问题,为什么gentoo官方论坛上中文论坛的网页是用UTF-8编码的(虽然大家一直强烈建议用GB2312编码),但是新浪网 就是用GB2312编码的呢?而Xorg的官方网页竟然是ISO-8859-15编码的,我没有设定这个locale怎么一样的能浏览呢?这个问题就像是 你有所有的密码本,不论某个网站是用什么字符集编码的,你都可以用你手里的密码本把他们翻译过来,但问题是虽然你能浏览中文网页,但是在整个操作系统里面 流动的还是英文字符。所以,就像你能听懂英语,也能听懂中文。 最根本的问题是:你不可以写中文。  

当你决定要写什么东西的时候,首先 要决定的一件事情是用那种语言,对于计算机来说就是你要是用哪一种字符集,你就必须告诉你的linux系统,你想用那一本密码本去写你想要写的东西。知道 为什么需要用GB2312字符集去浏览新浪了吧,因为新浪的网页是用GB2312写的。  

为了让你的Linux能够输入中文,就需要把 系统的locale设定成中文的(严格说来是locale中的语言类别LC_CTYPE ),例如zh_CN.GB2312、zh_CN.GB18030或者zh_CN.UTF-8。很多人都不明白这些古里古怪的表达方式。这个外星表达式规定 了什么东西呢?这个问题稍后详述,现在只需要知道,这是locale的表达方式就可以了。  

二、到底什么是locale? locale这个单词中文翻译成地区或者地域,其实这个单词包含的意义要宽泛很多。Locale是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。  

这 个用户环境可以按照所涉及到的文化传统的各个方面分成几个大类,通常包括用户所使用的语言符号及其分类(LC_CTYPE),数字 (LC_NUMERIC),比较和排序习惯(LC_COLLATE),时间显示格式(LC_TIME),货币单位(LC_MONETARY),信息主要是 提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES),姓名书写方式(LC_NAME),地址书写方式(LC_ADDRESS),电话号码书写方式 (LC_TELEPHONE),度量衡表达方式(LC_MEASUREMENT),默认纸张尺寸大小(LC_PAPER)和locale对自身包含信息的 概述(LC_IDENTIFICATION)。  

所以说,locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地 区的locale就是根据这几大类的习惯定义的,这些locale定义文件放在/usr/share/i18n/locales目录下面,例如 en_US, zh_CN and de_DE@euro都是locale的定义文件,这些文件都是用文本格式书写的,你可以用写字板打开,看看里边的内容,当然出了有限的注释以外,大部分 东西可能你都看不懂,因为是用的Unicode的字符索引方式。  

对于de_DE@euro的一点说明,@后边是修正项,也就是说你可 以看到两个德国的locale: /usr/share/i18n/locales/de_DE@euro /usr/share/i18n/locales/de_DE 打开这两个locale定义,你就会知道它们的差别在于de_DE@euro使用的是欧洲的排序、比较和缩进习惯,而de_DE用的是德国的标准习惯。   

上面我们说到了zh_CN.GB18030的前半部分,后半部分是什么呢?大部分Linux用户都知道是系统采用的字符集。  

三、 什么是字符集? 字符集就是字符,尤其是非英语字符在系统内的编码方式,也就是通常所说的内码,所有的字符集都放在/usr/share/i18n/charmaps,所 有的字符集也都是用Unicode编号索引的。Unicode用统一的编号来索引目前已知的全部的符号。而字符集则是这些符号的编码方式,或者说是在网络 传输,计算机内部通信的时候,对于不同字符的表达方式,Unicode是一个静态的概念,字符集是一个动态的概念,是每一个字符传递或传输的具体形式。就 像 Unicode编号U59D0是代表姐姐的“姐”字,但是具体的这个字是用两个字节表示,三个字节,还是四个字节表示,是字符集的问题。例如:UTF-8 字符集就是目前流行的对字符的编码方式,UTF-8用一个字节表示常用的拉丁字母,用两个字节表示常用的符号,包括常用的中文字符,用三个表示不常用的字 符,用四个字节表示其他的古灵精怪的字符。而GB2312字符集就是用两个字节表示所有的字符。需要提到一点的是Unicode除了用编号索引全部字符以 外,本身是用四个字节存储全部字符,这一点在谈到挂载windows分区的时候是非常重要的一个概念。所以说你也可以把Unicode看作是一种字符集 (我不知道它和UTF-32的关系,反正UTF-32就是用四个字节表示所有的字符的),但是这样表述符号是非常浪费资源的,因为在计算机世界绝大部分时 候用到的是一个字节就可以搞定的 26个字母而已。所以才会有UTF-8,UTF-16等等,要不然大同世界多好,省了这许多麻烦。
四、zh_CN.GB2312到底是在说什么? Locale 是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。一个locale的书写格式为: 语言[_地域[.字符集]]. 所以说呢,locale总是和一定的字符集相联系的。下面举几个例子:  

1、我说中文,身处中华人民共和国,使用国标2312字符集来表达字符。 zh_CN.GB2312=中文_中华人民共和国+国标2312字符集。  

2、我说中文,身处中华人民共和国,使用国标18030字符集来表达字符。 zh_CN.GB18030=中文_中华人民共和国+国标18030字符集。  

3、我说中文,身处中华人民共和国台湾省,使用国标Big5字符集来表达字符。 zh_TW.BIG5=中文_台湾.大五码字符集  

4、我说英文,身处大不列颠,使用ISO-8859-1字符集来表达字符。 en_GB.ISO-8859-1=英文_大不列颠.ISO-8859-1字符集  

5、我说德语,身处德国,使用UTF-8字符集,习惯了欧洲风格。 de_DE.UTF-8@euro=德语_德国.UTF-8字符集@按照欧洲习惯加以修正  

注意不是de_DE@euro.UTF-8,所以完全的locale表达方式是 [语言[_地域][.字符集] [@修正值]  

生成的locale放在/usr/lib/locale/目录中,并且每个locale都对应一个文件夹,也就是说创建了de_DE@euro.UTF-8 locale之后,就生成/usr/lib/locale/de_DE@euro.UTF-8/目录,里面是具体的每个locale的内容。  

五、 怎样去自定义locale 在gentoo生成locale还是很容易的,首先要在USE里面加入userlocales支持,然后编辑locales.build文件,这个文件用 来指示glibc生成locale文件。 很多人不明白每一个条目是什么意思。 其实根据上面的说明现在应该很明确了。  

File: /etc/locales.build en_US/ISO-8859-1 en_US.UTF-8/UTF-8  

zh_CN/GB18030 zh_CN.GBK/GBK zh_CN.GB2312/GB2312 zh_CN.UTF-8/UTF-8  

上面是我的locales.build文件,依次的说明是这样的:  

en_US/ISO-8859-1:生成名为en_US的locale,采用ISO-8859-1字符集,并且把这个locale作为英文_美国locale类的默认值,其实它和en_US.ISO-8859-1/ISO-8859-1没有任何区别。  

en_US.UTF-8/UTF-8:生成名为en_US.UTF-8的locale,采用UTF-8字符集。  

zh_CN/GB18030:生成名为zh_CN的locale,采用GB18030字符集,并且把这个locale作为中文_中国locale类的默认值,其实它和zh_CN.GB18030/GB18030没有任何区别。  

zh_CN.GBK/GBK: 生成名为zh_CN.GBK的locale,采用GBK字符集。 zh_CN.GB2312/GB2312:生成名为zh_CN.GB2312的locale,采用GB2312字符集。 zh_CN.UTF-8/UTF-8:生成名为zh_CN.UTF-8的locale,采用UTF-8字符集。  

关于默认locale,默认locale可以简写成en_US或者zh_CN的形式,只是为了表达简单而已没有特别的意义。  

Gentoo 在locale定义的时候掩盖了一些东西,也就是locale的生成工具:localedef。 在编译完glibc之后你可以用这个localedef 再补充一些locale,就会更加理解locale了。具体的可以看 localedef 的manpage。  

$localedef -f 字符集 -i locale定义文件 生成的locale的名称 例如 $localedef -f UTF-8 -i zh_CN zh_CN.UTF-8  

上面的定义方法和在locales.build中设定zh_CN.UTF-8/UTF-8的结果是一样一样的。  

六、locale的五脏六腑  

刚 刚生成了几个locale,但是为了让它们生效,必须告诉Linux系统使用那(几)个locale。这就需要对locale的内部机制有一点点的了解。 在前面我已经提到过,locale把按照所涉及到的文化传统的各个方面分成12个大类,这12个大类分别是: 1、语言符号及其分类(LC_CTYPE) 2、数字(LC_NUMERIC) 3、比较和排序习惯(LC_COLLATE) 4、时间显示格式(LC_TIME) 5、货币单位(LC_MONETARY) 6、信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES) 7、姓名书写方式(LC_NAME) 8、地址书写方式(LC_ADDRESS) 9、电话号码书写方式(LC_TELEPHONE) 10、度量衡表达方式(LC_MEASUREMENT) 11、默认纸张尺寸大小(LC_PAPER) 12、对locale自身包含信息的概述(LC_IDENTIFICATION)。  

其 中,与中文输入关系最密切的就是 LC_CTYPE, LC_CTYPE 规定了系统内有效的字符以及这些字符的分类,诸如什么是大写字母,小写字母,大小写转换,标点符号、可打印字符和其他的字符属性等方面。而locale定 义zh_CN中最最重要的一项就是定义了汉字(Class “hanzi”)这一个大类,当然也是用Unicode描述的,这就让中文字符在Linux系统中成为合法的有效字符,而且不论它们是用什么字符集编码 的。  

LC_CTYPE % This is a copy of the "i18n" LC_CTYPE with the following modifications: - Additional classes: hanzi  

copy "i18n"  

class "hanzi"; / % ..;/ ..;/ ;;;;;;;;/ ;;;;;;;;/ ;;;; END LC_CTYPE  

在en_US的locale定义中,并没有定义汉字,所以汉字不是有效字符。所以如果要输入中文必须使用支持中文的locale,也就是zh_XX,如zh_CN,zh_TW,zh_HK等等。  

另 外非常重要的一点就是这些分类是彼此独立的,也就是说LC_CTYPE,LC_COLLATE和 LC_MESSAGES等等分类彼此之间是独立的,可以根据用户的需要设定成不同的值。这一点对很多用户是有利的,甚至是必须的。例如,我就需要一个能够 输入中文的英文环境,所以我可以把LC_CTYPE设定成zh_CN.GB18030,而其他所有的项都是en_US.UTF-8。  

七、怎样设定locale呢?  

设 定locale就是设定12大类的locale分类属性,即 12个LC_*。除了这12个变量可以设定以外,为了简便起见,还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系: LC_ALL>LC_*>LANG 可以这么说,LC_ALL是最上级设定或者强制设定,而LANG是默认设定值。 1、如果你设定了LC_ALL=zh_CN.UTF-8,那么不管LC_*和LANG设定成什么值,它们都会被强制服从LC_ALL的设定,成为 zh_CN.UTF-8。 2、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*=en_US.UTF-8,并且没有设定LC_ALL的话,那么系统的locale 设定以LC_*=en_US.UTF-8。 3、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*,和LC_ALL均未设定的话,系统会将LC_*设定成默认值,也就是LANG的值 zh_CN.UTF-8 。 4、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_CTYPE=en_US.UTF-8,其他的LC_*,和LC_ALL均未设定的话, 那么系统的locale设定将是:LC_CTYPE=en_US.UTF-8,其余的 LC_COLLATE,LC_MESSAGES等等均会采用默认值,也就是LANG的值,也就是LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=zh_CN.UTF-8。  

所以,locale是这样设定的: 1、如果你需要一个纯中文的系统的话,设定LC_ALL= zh_CN.XXXX,或者LANG= zh_CN.XXXX都可以,当然你可以两个都设定,但正如上面所讲,LC_ALL的值将覆盖所有其他的locale设定,不要作无用功。 2、如果你只想要一个可以输入中文的环境,而保持菜单、标题,系统信息等等为英文界面,那么只需要设定LC_CTYPE=zh_CN.XXXX,LANG = en_US.XXXX就可以了。这样LC_CTYPE=zh_CN.XXXX,而LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=en_US.XXXX。 3、假如你高兴的话,可以把12个LC_*一一设定成你需要的值,打造一个古灵精怪的系统: LC_CTYPE=zh_CN.GBK/GBK(使用中文编码内码GBK字符集); LC_NUMERIC=en_GB.ISO-8859-1(使用大不列颠的数字系统) LC_MEASUREMEN=de_DE@euro.ISO-8859-15(德国的度量衡使用ISO-8859-15字符集) 罗马的地址书写方式,美国的纸张设定……。估计没人这么干吧。 4、假如你什么也不做的话,也就是LC_ALL,LANG和LC_*均不指定特定值的话,系统将采用POSIX作为lcoale,也就是C locale。

Read More...

星期四, 十一月 29, 2007

LQ035Q7DH01参数

为方便客户调试SHARP LQ035Q7DH01 LCD,现在我们将该款LCD主要的几个参数公布如下:

/* Sharp LQ035 portrait mode ADTFT display parameters */
const LCD_PARAM_T sharp_lq035 =
{
  21,     /* Horizontal back porch */
  11,     /* Horizontal front porch */
  13,     /* HSYNC pulse width */
  240,     /* Pixels per line */
  3,     /* Vertical back porch */
  4,     /* Vertical front porch */
  2,     /* VSYNC pulse width */
  320,     /* Lines per panel */
  0,     /* Do not invert output enable */
  1,     /* Invert panel clock */
  1,     /* Invert HSYNC */
  0,     /* Do not invert VSYNC */
  1,     /* AC bias frequency (not used) */
  16,     /* Bits per pixel */

Read More...

星期一, 十一月 26, 2007

CS8900 base address的确定方法『转』

开始研究tftp的实现方法,框架基本上是(从底层向上):媒介->IP->UDP->TFTP。其中,CS8900A就可以完成 PHY层和MAC层的所有工作,在媒介的上部应该还有一个LLC(logical link control),IP层也不仅仅包含IP协议,另外还需要有arp协议来确定host的mac地址。这个整体的框架后面详细介绍,下面先简略介绍 cs8900a的base address的确定方法和探测程序。
cs8900a实际上已经比较老了,性能和价格上都比不过dm9000,Linux 2.6的内核默认的是支持dm9000的以太网控制器。但是EDUKIT-III上仍然使用的是cs8900a,所以还是专心看cs8900a。要注意, 一是以学习的态度去研究,二是总结阅读datasheet的方法。
首先看看cs8900a到底是什么。

·Single-Chip IEEE 802.3 Ethernet Controller with Direct ISA-Bus Interface
·Maximum Current Consumption = 55 mA (5V Supply)
·3 V or 5 V Operation
·Industrial Temperature Range
· Comprehensive Suite of Software Drivers Available
·Efficient PacketPage Architecture Operates in I/O and Memory Space, and as DMA Slave
·Full Duplex Operation
·On-Chip RAM Buffers Transmit and ReceiveFrames
·10BASE-T Port with Analog Filters, Provides:
- Automatic Polarity Detection and Correction
·AUI Port for 10BASE2, 10BASE5 and 10BASE-F
·Programmable Transmit Features:
- Automatic Re-transmission on Collision
- Automatic Padding and CRC Generation
·Programmable Receive Features:
- Stream Transfer; for Reduced CPU Overhead
- Auto-Switch Between DMA and On-Chip Memory
- Early Interrupts for Frame Pre-Processing
- Automatic Rejection of Erroneous Packets
·EEPROM Support for Jumperless Configuration
·Boot PROM Support for Diskless Systems
·Boundary Scan and Loopback Test
·LED Drivers for Link Status and LAN Activity
·Standby and Suspend Sleep Modes

可以看出,cs8900a最重要的部分就是:
·ISA总线接口。这部分可以使外部的glue logic最小,简化编程,方便设计。
·集成10BASE-T transmit and receive filters。这个加上专用变压器和RJ45对应的网线,就可以完成PHY层的功能。所以,硬件设计时不需要考虑PHY芯片了。at91rm9200集 成了以太网控制器,但是只是实现了MAC层的功能,所以需要扩展一个PHY层芯片完成网络接口的设计。
·特殊的PacketPage架构。这实际上是cs8900a的特色,本来IO访问模式和memory访问模式是不同的,但是cs8900a屏蔽了这种差异,提供了一个统一的接口。这样在程序设计上,就可以使用统一的内存空间,来完成对cs8900a的操作。
·EEPROM的支持。
现在就PacketPage架构和两种访问模式展开分析。

The CS8900A architecture is based on a unique, highly-efficient method of accessing internal registers and buffer memory known as PacketPage. PacketPage provides a unified way of controlling the CS8900A in Memory or
I/O space that minimizes CPU overhead and simplifies software. It provides a flexible set of performance features and configuration options, allowing designers to develop Ethernet circuits that meet their particular system requirements.

cs8900a有两种访问模式:IO模式和MEM模式。在IO模式下,cs8900a占用host最小的空间,仅仅16个字节(8个16bit的IO ports)。对地址空间紧张的系统来说,是一个合适的选择。在MEM模式下,cs8900a占用4K的空间,这是软件可以直接访问cs8900a的内部 寄存器,而且这4K的空间还分成了6个组成部分,具体可以参考datasheet的4.1.1部分。
cs8900a默认的是IO模式。在系统设计时,最好两种模式都要预留出来。原因有很多,首先,大多数情况下,MEM模式性能更高。因为ISA内存操作比 IO操作需要更少的时钟周期。所以最好有mem模式。其次呢,如果内存空间不可用,或者特殊操作时,IO模式是唯一的选择,而且如果使用了EEPROM, 板子发生故障时,EEPROM通常是空白的,为了对EEPROM编程,cs8900a也必须工作在IO模式。综上两种分析,系统设计还是要设计两种访问方 式为好。在ISA总线接口中,I/O空间和内存空间是独立寻址的,因此它们有各自不同的读写信号。但ARM体系中,I/O空间和内存空间是统一寻址。问题 就出来了,如果两种访问模式同时存在,那么如何区分是那种访问模式呢?
这个在硬件设计中是很普遍的问题。电路设计的时候用高位地址线(ADDR24)经过组合逻辑的译码来区分I/O空间和内存空间的读写。cs8900a只需 要20根地址现,而s3c2410的地址线是32条。那么可以让a[19:0]对应cs8900a的sa[19:0],拿出一条地址线A24来区分两种模 式。我画了原理图(注意,这仅仅是组合逻辑译码的一种,可以有其他的方式,这个就有硬件设计来决定了),如下:
500)this.width=500;" border="0" height="384" width="500">
文件: 1.rar
大小: 25KB
下载: 下载
通过上述的原理图,很容易明白,A24地址线为低时,为MEM模式。A24为高时,为IO模式。另外,cs8900a可以接在不同的bank。比如, EDUKIT接在nGCS3,基址是0x18000000,那么很明显,MEM模式的基地址是0x18000000,而IO模式的基地址是 0x18000000+(1<<24),也就是0x19000000。但是IO模式的基地址还没有最终结果呢。看datasheet,发现 packetpage偏移0x0020的地方为IO base address。在复位以后,如果没有EEPROM,那么该寄存器的值就是默认的0x0300。如果采用IO方式,那么初始时对应的该寄存器始终为 0x0300,前面得到的0x19000000再加上这个0x300才能找到最终8个16bitsIO ports的首地址。以后所有的操作都是通过这8个IO ports来进行的,包括访问MEM模式的那些寄存器。也就是MEM要访问那些内部寄存器,只是需要直接寻址就可以了,而IO模式则要先找到IO ports,然后通过这些IO ports来寻找到内部寄存器。显然,在效率上又差了一层。
下面看看EDUKIT-III的不同。EDUKIT-III采用了核心板+底板的设计方法。核心板SoC的A24最终经过电平转换芯片 74LVCH62245成为AB24,然后经过CPLD处理逻辑关系得到相应的IO和MEM控制信号。在CPLD中的逻辑处理跟上面原理图的处理是相同 的,不过实验箱需要处理的逻辑太多,用CPLD要好。这个也是看了好长时间的电路图才推断出来的。
由此可见base address的计算方法如下(假定选择nGCSn,对应bank的首地址为nGCS_ADDR)
MEM模式: base address = nGCS_ADDR
IO模式: base address = nGCS_ADDR + (1 << 24) + 0x0300.
当然,还有的默认前提就是使用了A24这条地址线来进行区分。当然,如果你不使用A24,只采用IO模式,不支持MEM模式,那么你的基地址完全可以是 nGCS_ADDR+0x0300。需要注意的是,在弄清楚原理的情况下,一定要看硬件设计如何,这样才能确定基地址。

备注:关于IO mode和memory mode的比较
I/O mode is 99.6% as fast as Memory mode. Also, since the CS8900A defaults to I/O and you don't need glue logic in most systems in I/O mode, Cirrus recommends I/O mode.

Read More...

星期六, 十一月 24, 2007

S3C2410启动信息注释(vivi部分)『转』

uclinux的启动主要分为两个阶段:
第一部分bootloader启动阶段
第二部分linux 内核初始化和启动阶段
     第一节:start_kernel
     第二节:用户模式( user_mode )开始,start_kernel结束
     第三节:加载linux内核完毕,转入cpu_idle进程

Specification of the machine

- CPU: S3C2410
- MEM: 64MB (bank 0)
- ROM: 64MB (Inte Starata Flash Memory)
- got UART ports

64MB RAM (DRAM)

0x3400 0000 +----------------------+
                  |VIVI RAM (size: 1M)    |
0x33F0 0000 +----------------------+ VIVI_RAM_BASE
                  |HEAP AREA(size: 1M)   |
0x33E0 0000 +----------------------+ HEAP_BASE
                  |MMU TABLE(size: 16k)  |
0x33DF C000 +----------------------+ MMU_TABLE_BASE
                 
|                               |
           mtd partition table (size: 16k)| MTD_PART_SIZE -----\
0x33DF 8000 +----------------------+                               |
          vivi parameter table(size: 16k)| PARAMETER_TLB_SIZE  | vivi pri data
0x33DF 4000 |----------------------+                               |
        
linux command line (size: 16k)  | LINUX_CMD_SIZE  -----/
                  |                               |

0x33DF 0000 +----------------------+ VIVI_PRIV_RAM_BASE
                  |                              |
                  |   free memory            |
                  |                              |
0x3010 8000 +----------------------+
                  |   kernel (size: 1MB)     |
0x3000 8000 +----------------------+
                  |                              |
                  |   free memory            |
                  |                              |
0x3000 0100 +----------------------+
           kernel param (size 256Byte)  |
0x3000 0000 +----------------------+ DRAM_BASE


64MB ROM (NAND Flash)

* 0x0400 0000 +-----------------------------+
*                   |                                         |
*                   | jffs2 (size: 61M)                   | user
*                   |                                         |
* 0x0030 0000 +-----------------------------+
*                   | root  (size: 2048k)                 |
* 0x0010 0000 +-----------------------------+
*                   | kernel (size: 832k)                |
* 0x0003 0000 +-----------------------------+
*                   | param (size: 64k)                   |
* 0x0002 0000 +-----------------------------+
*                   | vivi  (size: 128k)                  |
* 0x0000 0000 +-----------------------------+

[root@localhost root]# minicom
Welcome to minicom 2.00.0


OPTIONS: History Buffer, F-key Macros, Search History Buffer, I18nCompiled on Jan 25 2003, 00:15:18.Press CTRL-A Z for help on special keys


minicom信息


VIVI version 0.1.4 (root@BC) (gcc version 2.95.2 20000516 (release) [Rebel.com]5


Bootloader头信息,版本等,这个因不同的bootloader的设计而有所不同,由此你能看出bootloader的版本信息,有很多使用的是通用的bootloader,如u-boot,redboot等。

链接 Boot Loader  VIVI

源代码: vivi/lib/version.c vivi/main.c


#define VIVI_RELEASE "0.1.4"
#define VIVI_COMPILE_BY "root"
#define VIVI_COMPILE_HOST "localhost.localdomain"
#define VIVI_COMPILER "gcc version 2.95.2 20000516 (release)[Rebel.com]"
#define UTS_VERSION "#0.1.4 六 6月 5 05:27:07 CST 2004"

const char *vivi_banner = "VIVI version " VIVI_RELEASE " (" VIVI_COMPILE_BY "@" VIVI_COMPILE_HOST ") (" VIVI_COMPILER ") " UTS_VERSION "\r\n";putstr(vivi_banner);


MMU table base address = 0x33DFC000
Succeed memory mapping.


链接 MMU

    内存映射(memory map)就是指在整个4GB物理地址空间中有哪些地址范围被分配用来寻址系统的RAM单元。比如,在SA-1100CPU中,从0xC000,0000开 始的512M地址空间被用作系统的RAM地址空间,而在Samsung S3C44B0X CPU中,从0x0c00,0000到0x1000,0000之间的64M地址空间被用作系统的RAM地址空间。虽然 CPU 通常预留出一大段足够的地址空间给系统 RAM,但是在搭建具体的嵌入式系统时却不一定会实现CPU预留的全部RAM地址空间。也就是说,具体的嵌入式系统往往只把CPU预留的全部RAM地址空 间中的一部分映射到RAM单元上,而让剩下的那部分预留RAM地址空间处于未使用(unused)状态。由于上述这个事实,因此Boot Loader的stage2必须在它想干点什么之前——比如,将存储在flash上的内核映像读到RAM空间中——检测整个系统的内存映射情况,也即它必 须知道CPU预留的全部RAM地址空间中的哪些被真正映射到RAM地址单元,哪些是处于unused状态的。
    VIVI中用CONFIG_BOOTUP_MEMTEST中的memtest完成基本的RAM检测,针对
Samsung S3C2410 CPU从0x3000,0000到0x3400,0000之间的64M地址空间被用作系统的RAM地址空间。

源代码:vivi/arch/s3c2410/mmu.c

#define MMU_TABLE_BASE (HEAP_BASE - MMU_TABLE_SIZE)
#define HEAP_BASE (VIVI_RAM_BASE - HEAP_SIZE)
#define VIVI_RAM_BASE (DRAM_BASE + DRAM_SIZE - VIVI_RAM_SIZE)
#define DRAM_BASE DRAM_BASE0
#define DRAM_BASE0       0x30000000      /* base address of dram bank 0 */
#define DRAM_SIZE        SZ_64M
#define SZ_8M            0x00800000
#define VIVI_RAM_SIZE    SZ_1M
#define HEAP_SIZE        SZ_1M
#define SZ_1M            0x00100000
#define MMU_TABLE_SIZE   SZ_16K
#define SZ_16K           0x00004000static
unsigned long *mmu_tlb_base = (unsigned long *) MMU_TABLE_BASE;
putstr_hex("MMU table base address = 0x", (unsigned long)mmu_tlb_base);

源代码:vivi/main.c

mem_map_init();
mmu_init();
putstr("Succeed memory mapping.\r\n");



NAND device: Manufacture ID: 0xec, Chip ID: 0x76 (Samsung K9D1208V0M)

链接:闪存芯片

NAND Flash:1989年,东芝公司发明。是以块和页为单位来读写的,不能随机访问某个指定的点。因而相对来说读取速度较慢,而擦除和写入的速度则比较快。一般适用在大容量的多媒体应用中,如:CF,SM。
NOR  Flash:Intel于1988年发明.随机读取的速度比较快,随机按字节写,写入和擦除速度很低。一般适合应用于数据/程序的存贮应用中,如:手机,机顶盒。NOR还可以片内执行(execute-in-place)XIP。

简单的说,NAND类似于硬盘,NOR类似于内存

源代码:vivi/drivers/mtd/nand/smc_core.c


struct nand_flash_dev {
    char * name;
    int manufacture_id;
    int model_id;
    int chipshift;
    char page256;
    char pageadrlen;
    unsigned long erasesize;
};
static struct nand_flash_dev nand_flash_ids[] = {
  {"Toshiba TC5816BDC",     NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},    // 2Mb 5V
  {"Toshiba TC58V16BDC",    NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},    // 2Mb 3.3V
  {"Toshiba TC5832DC",      NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},    // 4Mb 5V
  {"Toshiba TC58V32DC",     NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},    // 4Mb 3.3V
  {"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},    // 8Mb 3.3V
  {"Toshiba TH58V128DC",    NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},    // 16Mb
  {"Toshiba TC58256FT/DC",  NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},    // 32Mb
  {"Toshiba TH58512FT",     NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},    // 64Mb
  {"Toshiba TH58NS100/DC",  NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000},    // 128Mb
  {"Samsung KM29N16000",    NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},    // 2Mb 5V
  {"Samsung KM29W16000",    NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},    // 2Mb 3.3V
  {"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},    // 4Mb 5V
  {"Samsung KM29W32000",    NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},    // 4Mb 3.3V
  {"Samsung unknown 4Mb",   NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},    // 4Mb 3.3V
  {"Samsung KM29U64000",    NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},    // 8Mb 3.3V
  {"Samsung KM29U128T",     NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},    // 16Mb
  {"Samsung KM29U256T",     NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},    // 32Mb
  {"Samsung K9D1208V0M",    NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},    // 64Mb
  {"Samsung K9D1G08V0M",    NAND_MFR_SAMSUNG, 0x79, 27, 0, 3, 0x4000},    // 128Mb
  {NULL,}
};
mtd->name = nand_flash_ids[i].name;
printk("NAND device: Manufacture ID:" \
                " 0x%02x, Chip ID: 0x%02x (%s)\n",
                nand_maf_id, nand_dev_id, mtd->name);


Could not found stored vivi parameters. Use default vivi parameters.

vivi参数

vivi_parameter_t default_vivi_parameters[] = {
    { "mach_type",            MACH_TYPE,    NULL },
    { "media_type",            MT_S3C2410,    NULL },
    { "boot_mem_base",        0x30000000,    NULL },
    { "baudrate",            UART_BAUD_RATE,    NULL },
    { "xmodem_one_nak",        0,        NULL },
    { "xmodem_initial_timeout",    300000,        NULL },
    { "xmodem_timeout",        1000000,    NULL },
    { "ymodem_initial_timeout",    1500000,    NULL },
    { "boot_delay",            0x1000000,    NULL }
};
#define MACH_TYPE        193
#define MT_S3C2410       MT_SMC_S3C2410
#define UART_BAUD_RATE   115200

源代码:vivi/lib/priv_data.c

int init_priv_data(void)
{
    int ret_def;
#ifdef CONFIG_PARSE_PRIV_DATA //#define CONFIG_PARSE_PRIV_DATA 1
    int ret_saved;
#endif
    ret_def = get_default_priv_data();
#ifdef CONFIG_PARSE_PRIV_DATA
    ret_saved = load_saved_priv_data();
    if (ret_def && ret_saved) {
        printk("Could not found vivi parameters.\n");
        return -1;
    } else if (ret_saved && !ret_def) {
        printk("Could not found stored vivi parameters.");
        printk(" Use default vivi parameters.\n");
    } else {
        printk("Found saved vivi parameters.\n");
    }
#else
    if (ret_def) {
        printk("Could not found vivi parameters\n");
        return -1;
    } else {
        printk("Found default vivi parameters\n");
    }
#endif

#ifdef CONFIG_DEBUG_VIVI_PRIV
    display_param_tlb();
    display_mtd_partition();
#endif
    return 0;



Press Return to start the LINUX now, any other key for vivi

按回车进入linux,其它键进vivi。当然,从vivi中boot也可以。

源代码:vivi/main.c

void boot_or_vivi(void)
{
    char c;
    int ret;
    ulong boot_delay;

    boot_delay = get_param_value("boot_delay", &ret);
    if (ret) boot_delay = DEFAULT_BOOT_DELAY;
    /* If a value of boot_delay is zero,
     * unconditionally call vivi shell */
    if (boot_delay == 0) vivi_shell();


    /*
     * wait for a keystroke (or a button press if you want.)
     */
    printk("Press Return to start the LINUX now, any other key for vivi\n");
    c = awaitkey(boot_delay, NULL);
    if (((c != '\r') && (c != '\n') && (c != '\0'))) {
        printk("type \"help\" for help.\n");
        vivi_shell();
    } // 有问题,'\r' '\n'都是回车,'\0'是什么?
    run_autoboot();

    return;
}
【注:这里还有个小问题。就是在这里添加的时候,\n\r要合起来用,不能只用\n。原因如下:
    计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
    于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
    这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。
    后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<换行><回车>”,即“\ n\r”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
    这几个地方我都遇到过,不过一直没有搞清楚。现在才算是找到根源了。】



Copy linux kernel from 0x00030000 to 0x30008000, size = 0x00100000 ... done

    启 动linux kernel,kernel映像必须被放到MTD设备的一个分区中,from、size分别表示linux kernel起始地址和kernel的大小。为什么要指定kernel大小呢?因为kernel首先要被copy到boot_mem_base + 0x8000的地方,然后在boot_mem_base + 0x100开始的地方设置内核启动参数。要拷贝 kernel,当然需要知道kernel的大小啦,这个大小不一定非要和kernel实际大小一样,但是必须大于等于kernel的大小。(单位字节)
  
    media_type是指定的媒介类型,因为boot命令对不同媒介的处理方式是不同的,例如如果kernel在 SDRAM中,那么boot执行的过程中就可以跳过拷贝kernel映像到SDRAM中这一步骤了
   
Boot命令识别的媒介类型有以下三种:
ram 表示从RAM中启动linux kernel,linux kernel必须要放在RAM中,我的S3C2410平台就是如此。
nor 表示从NOR Flash中启动linux kernel,linux kernel必须已经被烧写到了NOR Flash中
smc 表示从NAND Flash中启动linux kernel,linux kernel必须已经被烧写到了NAND Flash中 


源代码:vivi/lib/boot-kernel.c

    int boot_kernel(ulong from, size_t size, int media_type)
{
    int ret;
    ulong boot_mem_base;    /* base address of bootable memory */
    ulong to;

    boot_mem_base = get_param_value("boot_mem_base", &ret);
    if (ret) {
        printk("Can't get base address of bootable memory\n");
        printk("Get default DRAM address. (0x%08lx\n", DRAM_BASE);
        boot_mem_base = DRAM_BASE;
    }   //boot_mem_base = 0x30000000

    /* copy kerne image */
    to = boot_mem_base + LINUX_KERNEL_OFFSET;
        // #define LINUX_KERNEL_OFFSET    0x8000
        // to = 0x30008000
    printk("Copy linux kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",from, to, size);
    ret = copy_kernel_img(to, (char *)from, size, media_type);
        // 将内核镜像从NAND FLASH拷入RAM
        //
media_type=MT_SMC_S3C2410
    if (ret) {
        printk("failed\n");
        return -1;
    } else {
        printk("done\n");
    }

    return 0;
}

  
void command_boot(int argc, const char **argv)
{
    int media_type = 0;
    ulong from = 0;
    size_t size = 0;
    mtd_partition_t *kernel_part;
    int ret;
   
    media_type = get_param_value("media_type", &ret);
            if (ret) {
                printk("Can't get default 'media_type'\n");
                return;
            }
    kernel_part = get_mtd_partition("kernel");
            if (kernel_part == NULL) {
                printk("Can't find default 'kernel' partition\n");
                return;
            }
    from = kernel_part->offset;
    size = kernel_part->size;
    boot_kernel(from, size, media_type);
}

user_command_t boot_cmd = {
    "boot",
    command_boot,
    NULL,
    "boot [{cmds}] \t\t\t-- Booting linux kernel"
};

zImage magic = 0x016f2818

判断内核文件是否为压缩镜像,而当前文件是压缩镜像


源文件: vivi/lib/boot-kernel.c

#define LINUX_ZIMAGE_MAGIC    0x016f2818

if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {
       printk("Warning: this binary is not compressed linux kernel image\n");
       printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
    } else {
        printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
    }

Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/bon/3 init=/linuxrc console=ttyS0"


设置linux参数和控制行

static void setup_linux_param(ulong param_base)
{
/*
linux parameters*/
    struct param_struct *params = (struct param_struct *)param_base;
    char *linux_cmd;
    printk("Setup linux parameters at 0x%08lx\n", param_base);
    memset(params, 0, sizeof(struct param_struct));
    params->u1.s.page_size = LINUX_PAGE_SIZE;
    params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT);

/* set linux command line */
    linux_cmd = get_linux_cmd_line();//
linux_cmd = 0x33DF8008
    if (linux_cmd == NULL) {
        printk("Wrong magic: could not found linux command line\n");
    } else {
        memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
        printk("linux command line is: \"%s\"\n", linux_cmd);
    }
}

//
#define boot_mem_base 0x30000000
//#define LINUX_PARAM_OFFSET 0x100
setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);


MACH_TYPE = 193

/* Get machine type */
    mach_type = get_param_value("mach_type", &ret);
    printk("MACH_TYPE = %d\n", mach_type);

NOW, Booting Linux......

激动人心的消息,终于可以引导linux了。。。

源代码: vivi/lib/boot-kernel.c

printk("NOW, Booting Linux......\n");
    call_linux(0, mach_type, to);

#elif defined(CONFIG_ARCH_S3C2410)
void  call_linux(long a0, long a1, long a2)
{
    cache_clean_invalidate();
    tlb_invalidate();

__asm__(
    "mov    r0, %0\n"
    "mov    r1, %1\n"
    "mov    r2, %2\n"
    "mov    ip, #0\n"
    "mcr    p15, 0, ip, c13, c0, 0\n"    /* zero PID */
    "mcr    p15, 0, ip, c7, c7, 0\n"    /* invalidate I,D caches */
    "mcr    p15, 0, ip, c7, c10, 4\n"    /* drain write buffer */
    "mcr    p15, 0, ip, c8, c7, 0\n"    /* invalidate I,D TLBs */
    "mrc    p15, 0, ip, c1, c0, 0\n"    /* get control register */
    "bic    ip, ip, #0x0001\n"        /* disable MMU */
    "mcr    p15, 0, ip, c1, c0, 0\n"    /* write control register */
    "mov    pc, r2\n"
    "nop\n"
    "nop\n"
    : /* no outpus */
    : "r" (a0), "r" (a1), "r" (a2)
    );
//全是汇编,有空再研究

Boot Loader 调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START+0x8000 地址处。在跳转时,下列条件要满足: 

1. CPU 寄存器的设置: 
R0=0;
R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。 
R2=启动参数标记列表在 RAM 中起始基地址; 

2. CPU 模式:
必须禁止中断(IRQs和FIQs);
CPU 必须 SVC 模式;

3. Cache 和 MMU 的设置:
MMU 必须关闭;
指令 Cache 可以打开也可以关闭;
数据 Cache 必须关闭;

Read More...

嵌入式一些有用的东西

一、嵌入式系统
嵌入式系统概述 http://blogimg.chinaunix.net/blog/upfile/070926202343.pdf
嵌入式系统的发展现状 http://blogimg.chinaunix.net/blog/upfile/070929025142.pdf
符号说明 http://blogimg.chinaunix.net/blog/upfile/070924162110.pdf

二、视频监控
视频监控系统研究现状 http://blogimg.chinaunix.net/blog/upfile/070928034009.pdf
视频监控系统的发展历程 http://blogimg.chinaunix.net/blog/upfile/070924163711.pdf
视频监控系统的发展方向 http://blogimg.chinaunix.net/blog/upfile/070928034003.pdf
视频监控系统的组成 http://blogimg.chinaunix.net/blog/upfile/070924163839.pdf

三、视频数据采集
3.1 S3C2410概述 http://blogimg.chinaunix.net/blog/upfile/070926202329.pdf
vivi_理论 http://blogimg.chinaunix.net/blog/upfile/070926202336.pdf

3.2 Linux_理论 http://blogimg.chinaunix.net/blog/upfile/070926202850.pdf
内核的编译_理论 http://blogimg.chinaunix.net/blog/upfile/070926203800.pdf

3.3 OV511摄像头
采用USB摄像头 http://blogimg.chinaunix.net/blog/upfile/070929025205.pdf
OV511与OV7610_理论 http://blogimg.chinaunix.net/blog/upfile/070926202318.pdf
OV7620_理论 http://blogimg.chinaunix.net/blog/upfile/070929025211.pdf

四、视频数据压缩编码
MPEG-4_理论 http://blogimg.chinaunix.net/blog/upfile/070928033956.pdf

五、视频数据传输
流媒体理论基础 http://blogimg.chinaunix.net/blog/upfile/070924162338.pdf
ASF流格式 http://blogimg.chinaunix.net/blog/upfile/070924153047.pdf
RTP/RTCP

六、视频分析处理
图形用户界面及MiniGUI_理论http://blogimg.chinaunix.net/blog/upfile/070929025158.pdf
RGB和YUV颜色空间_理论 http://blogimg.chinaunix.net/blog/upfile/070928032645.pdf
   数字图像处理技术 http://blogimg.chinaunix.net/blog/upfile/070929025152.pdf

Read More...

回归Flock

ScribeFire.一段时间,发文本的基本没问题,但是今天在写代码的时候发现,代码还是被执行了,无奈还是flock了,还是flock发着舒服
呵呵

Read More...

S3C2410启动信息注释(user_mode部分)『转』

uclinux的启动主要分为两个阶段: 第一部分bootloader启动阶段 第二部分linux 内核初始化和启动阶段 第一节:start_kernel 第二节:用户模式( user_mode )开始,start_kernel结束 第三节:加载linux内核完毕,转入cpu_idle进程

Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039

英国威尔士,斯旺西大学的NET3.039, TCP/IP 协议栈。
此信息,在linux启动过程中都会出现。
Initializing RT netlink socket
BlueZ Core ver 2.4 Copyright (C) 2000,2001 Qualcomm Inc
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
CPU clock = 202.800000 Mhz, HCLK = 101.400000 Mhz, PCLK = 50.700000 Mhz

对Socket的初始化,socket_init(),Netlink 一种路由器管理协议(linux-2.4.22\net\core\Rtnetlink.c,Routing netlink socket interface: protocol independent part。 其中RT是route路由的意思。这句输出是在create产生rtnetlink的socket套接字时的一个调试输出。)

此信息,在linux启动过程中都会出现。

Initializing S3C2410 buffer pool for DMA workaround

初始化内存池

Starting kswapd

启动交换守护进程kswapd,进程IO操作例程kpiod。

kswapd可以配合kpiod运行。进 程有时候无事可做,当它运行时也不一定需要把其所有的代码和数据都放在内存中。这就意味着我们可以通过把运行中程序不用的内容切换到交换分区来更好的是利 用内存。大约每隔1秒,kswapd醒来并检查内存情况。如果在硬盘的东西要读入内存,或者内存可用空间不足,kpiod就会被调用来做移入/移出操作。 kswapd负责检查,kpiod负责移动。

devfs: v1.10 (20020120) Richard Gooch (rgooch@atnf.csiro.au)
devfs: boot_options: 0x1


Devfs模块的输出信息。设备文件系统devfs,版本1.12c

Samsung S3C2410X (i2c) algorithm module version 2.6.1 (20010830)
iic_s3c2410_init: Samsung S3C2410X iic adapter module version 2.6.1 (20010830)
i2c-dev.o: Registered 'Samsung S3C2410X IIC adapter' as minor 0
s3c2410_init: Initialized IIC on S3C2410X, 386kHz clock
iic_s3c2410_init: initialized iic-bus at 0xf4000000.


I2C

tts/%d0 at I/O 0x50000000 (irq = 52) is a S3C2410
tts/%d1 at I/O 0x50004000 (irq = 55) is a S3C2410
tts/%d2 at I/O 0x50008000 (irq = 58) is a S3C2410

Console: switching to colour frame buffer device 80x60
Installed S3C2410 frame buffer


framebuffer

pty: 256 Unix98 ptys configured

Pty模块的输出信息,与控制台操作有关的设置。
将通过 devpts 文件系统使用 Unix98 PTYs,(Pseudo-ttys (telnet etc) device是伪ttys设备的缩写。
  • ① TTY(/dev/tty)是TeleTYpe的一个老缩写,为用户输入提供不同控制台的设备驱动程序。它的名字来源于实际挂接到 UNIX系统的、被称为电传打字机(teletype)的终端。在Linux下,这些文件提供对虚拟控制台的支持,可以通过按<Alt-F1>到<Alt -F6>键来访问这些虚拟控制台。这些虚拟控制台提供独立的、同时进行的本地登录对话过程
  • ② ttys(/dev/ttys)是计算机终端的串行接口。/dev/ttyS0对应MS-DOS下的 COM1。

使 用 make dev脚本MAKEDEV来建立pty文件。这样系统内核就支持Unix98风格的pty了。在进行Telnet登录时将要用到/dev/pty设备。 pty是伪终端设备,在远程登录等需要以终端方式进行连接,但又并非真实终端的应用程序中必须使用这种设备,如telnet或xterm等程序。 Linux 2.2以后增添了UNIX98风格的Pty设备,它使用一个新的文件系统(devpts针对伪终端的文件系统)和一个克隆的设备cloning device来实现其功能。

linux-2.4.22\drivers\char\Pty.c, 在devfs_mk_dir (NULL, "pts", NULL);时会输出上面的信息。

s3c44b0-kbd initialized
s3c2410-ts initialized
s3c2410-adc initialized
S3C2410 Real Time Clock Driver v0.1

S3C2410键盘、 、ad转换器、实时时钟初始化

block: 128 slots per queue, batch=32
Uniform Multi-Platform E-IDE driver Revision: 6.31
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xxne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
Last modified Nov 1, 2000 by Paul Gortmaker

ide块设备驱动

eth0: NE2000 found at 0xd1000200, using IRQ 2.
PPP generic driver version 2.4.1

网卡驱动,基地址为:
0xd1000200,中断号:2

SCSI subsystem driver Revision: 1.00
request_module[scsi_hostadapter]: Root fs not mounted

USB设备信息,USB会被当做SCSI来处理。

UDA1341 audio driver initialized

声卡驱动

NAND device: Manufacture ID: 0xec, Chip ID: 0x76 (Samsung K9D1208V0M)
Find a MTD partition from BONFS -> nandflash0 (bon4)
Creating 1 MTD partitions on "Samsung K9D1208V0M":
0x00430000-0x03f30000 : "nandflash0 (bon4)"
devfs_mk_dir(bon): using old entry in dir: c03650a0 ""
bon0: 00000000-00020000 (00020000) 00000000
bon1: 00020000-00030000 (00010000) 00000000
bon2: 00030000-00130000 (00100000) 00000000
bon3: 00130000-00430000 (00300000) 00000000
bon4: 00430000-03f30000 (03b00000) 00000001
bon5: 03f30000-03ffc000 (000cc000) 00000000


NAND device

flash提供了写BUFFER的命令来加快对flash上块的操作。对Flash擦除和写数据是很慢的。如果用写BUFFER的命令会快一点。据 手册上说,会快20倍。Buffer Size :5 bytes的buffer缓冲不是每个块都有,是整个flash只有一个5 bytes的buffer,用写BUFFER命令对所有的块进行写操作,都要用同一个buffer,写Buffer是主要检查buffer是否 available,其实buffer起缓冲作用,来提高工作效率。

比如某flash有128个128K字节 块。允许用户对任意块进行字节编程和写缓冲器字节编程操作,每字节编程时间为210μs;若采用写缓冲器字节编程方式,32字节编程共需218μs,每字 节编程时间仅为6.8μs。芯片的块擦除时间为1s,允许在编程或块擦除操作的同时进行悬挂中断去进行读操作,待读操作完成后,写入悬挂恢复命令,再继续 编程或块擦除。

此处为重要信息部分,需要特别留意。在内存中映射过的flash,创建三个MTD分区:flash上的内容将被映射到内存中的对应地址
前128K为BootLoader--->0x00000000-0x00020000
接着的128K为系统配置信息Config存放的位置--->0x00020000-0x00040000
再后面的 16M - 2X128K 为romfs的存放处.--->0x00040000-0x01000000
上面的内容,大家可以根据前面的换算公式得到。
A> 编译的bootloader一般大小约50K左右;
B> 在此处就知道了配置信息config是放在第2分区中的;
C> 制作的romfs的大小,一般为8M或10M左右,所以能放得下;

对于linux 的根文件系统,目前有三种块设备的驱动可以选择,它们分别是:

a) Blkmem 驱动
b) MTD 驱动
c) RAM disk 驱动

Blkmem 驱动是专门为uclinux 开发的一种块设备驱动,它是uclinux系统中最为古老和通用的块设备驱动。它原理相对简单但是配置比较复杂,需要根据你即的Flash的分区使用情况 来修改代码。当然修改的结果是它可以对一些NOR型的Flash进行读写操作。不过目前支持的Flash类型不够多。如果新加入对一种Flash的支持需 要作的工作量比较大。

Linux的MTD驱动是标准Linux的Flash驱动。它支持大量的设备, 有足够的功能来定义Flash的分区,进行地址映射等等。使用MTD你可以在一个系统中使用不同类型的Flash。它可以将不同的Flash组合成一个线 性的地址让你来使用。在标准的Linux 2.4内核中MTD有一系列的选项,你可以根据个人系统的需要来选择,定制。

另 外一种选择就是RAM disk 驱动。在PC上它经常用于没有硬盘的Linux的启动过程。它和Flash没有直接的关系。不过当Flash上启动的是经过压缩的内核时。RAM disk 可以作为根文件系统。MTD 驱动提供了对Flash强大的支持,你通过它甚至可以在Flash上运行一个可以读写的真正的文件系统,比如JFFS2。而Blkmem驱动则望尘莫及

usb.c: registered new driver usbdevfs
usb.c: registered new driver hub
usb-ohci.c: USB OHCI at membase 0xe9000000, IRQ 26
usb.c: new USB bus registered, assigned bus number 1
hub.c: USB hub found
port #1 suspened!
port #0 alived!
hub.c: 1 port detected
Initializing USB Mass Storage driver...
usb.c: registered new driver usb-storage
USB Mass Storage support registered.

USB信息


NET4: Linux TCP/IP 1.0 for NET4.0

调用inet_init [ linux-2.4.22\net\ipv4\Af_inet.c ]时的输出信息, 在启动过程中被socket.c调用到。
IP Protocols: ICMP, UDP, TCP, IGMP

列出可以支持的IP协议,此处为kernel源代码inet_add_protocol(p);的输出。在linux启动过程中,都会看到这句的输出。

IP: routing cache hash table of 512 buckets, 4Kbytes

IP路由代码的输出信息。

ip_rt_init [ linux-2.4.22\net\ipv4\Route.c ],设置 IP module,路由缓冲hash表

TCP: Hash tables configured (established 4096 bind 4096)

TCP协议初始化输出信息。tcp_init [ linux-2.4.22\net\ipv4\Tcp.c ]

NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.

UNIX网络协议信息。

af_unix_init[ linux-2.4.22\net\unix\Af_unix.c ], 多种连接的一种(IPv4, UNIX domain sockets, IPv6和IrDA). SMP 对称多处理器—Symmetrical Multi Processing,这里主要是指UNIX的一些网络协议。

上面的关于网络的输出信息是在linux启动信息中都会出现的。

NetWinder Floating Point Emulator V0.95 (c) 1998-1999 Rebel.com



VFS: Mounted root (cramfs filesystem).

虚拟文件系统VFS(Virtual Filesystem Switch)的输出信息。

再次强调一下 一个概念。VFS 是一种软件机制,也可称它为 Linux 的文件系统管理者,它是用来管理实际文件系统的挂载点,目的是为了能支持多种文件系统。kernel会先在内存中建立一颗 VFS 目录树,是内存中的一个数据对象,然后在其下挂载rootfs文件系统,还可以挂载其他类型的文件系统到某个子目录上。


Mounted devfs on /dev

加载devfs设备管理文件系统到dev安装点上。/dev是我们经常会用到的一个目录。在2.4的kernel中才有使用到。每次启动时内核会自动挂载devfs。

devfs 提供了访问内核设备的命名空间。它并不是建立或更改设备节点,devfs只是为你的特别文件系统进行维护。一般我们可以手工mknod创件设备节点。 /dev目录最初是空的,里面特定的文件是在系统启动时、或是加载模组后驱动程序载入时建立的。当模组和驱动程序卸载时,文件就消失了。


Freeing init memory: 68K

释放1号用户进程init所占用的内存。

yaffs: dev is 7937 name is "1f:01"
mount: Mounting ramfs on /root failed: No such file or directory


VFS

cramfs 是 Linus Torvalds 本人开发的一个适用于嵌入式系统的小文件系统。由于它是只读的,所以,虽然它采取了 zlib 做压缩,但是它还是可以做到高效的随机读取。 cramfs 不会影响系统读取文件的速度,又是一个高度压缩的文件系统。

我们制作image文件之后,我们还要考虑怎样才能在系统运行的时候,把这个 image 文件 mount 上来,成为一个可用的文件系统。由于这个 image 文件不是一个通常意义上的 block 设备,我们必须采用 loopback 设备来完成这一任务,如:
mount -o loop -t cramfs /usr.img /usr

这样,就可以经由 loopback 设备,把 usr.img 这个 cramfs 的 image 文件 mount 到 /usr 目录上去了。内核中需要对loopback这个设备的支持。
cramfs 的压缩效率一般都能达到将近 50%。
Cramfs通过优化索引节点表的尺寸和除去传统文件系统中文件之间的空间浪费来达到节约空间的目的。它还使用了zlib压缩,实现优于2:1的压缩比例。解压缩过程的系统开销并不是很大,因为Cramfs支持指定单块的解压,而并不必解压缩整个文件。
Cramfs不仅能节省空间,还能避免非正常关机导致的等待fsck或手工进行fsck的麻烦。它通过只读的方式达到这一目的。

BusyBox v1.00 (2005.01.20-11:59+0000) Built-in shell (ash)

BusyBox

Enter 'help' for a list of built-in commands.

help

runing /etc/profile ok
[/mnt/yaffs]


OK

Read More...

S3C2410启动信息注释(start_kernel部分)『转』

uclinux的启动主要分为两个阶段:
第一部分bootloader启动阶段
第二部分linux 内核初始化和启动阶段
     第一节:start_kernel
     第二节:用户模式( user_mode )开始,start_kernel结束
     第三节:加载linux内核完毕,转入cpu_idle进程


Uncompressing Linux...........

从此句开始进入linux代码

Linux version 2.4.18-rmk7-pxa1 (root@BC) (gcc version 2.95.2 20000516(release)5

linux版本信息和编译信息

源代码:
/init/version.c
/include/linux/version.h
/include/linux
/Compile.h


const char *linux_banner =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

#define UTS_RELEASE "2.4.18-rmk7-pxa1"

#define UTS_VERSION "#16 一 9月 5 15:18:05 CST 2005"
#define LINUX_COMPILE_TIME "15:18:05"
#define LINUX_COMPILE_BY "root"
#define LINUX_COMPILE_HOST "BC"
#define LINUX_COMPILE_DOMAIN ""
#define LINUX_COMPILER "gcc version 2.95.2 20000516 (release) [Rebel.com]"

CPU: ARM/CIRRUS Arm920Tsid(wb) revision 0

ARM920T

Cirrus Logic 公司是一家享有世界盛名为众多消费和工业市场开发高精度模拟和混合信号集成电路的半导体公司。公司为消费和工业市场提供各种嵌入式处理器IC,例如适用于消费和专业用音频设备的音频最佳化数字信号处理器和基于ARM的嵌入式处理器。音频和工业市场最受尊重的品牌如 Bose、Harman International、IO、Onkyo、Marantz、Panasonic、Philips、Pioneer、Samsung及Sony都采用了Cirrus Logic公司的技术。

Machine: Samsung-SMDK2410

SMDK2410是Samsung的S3C2410的Reference board,即公板

公板是芯片厂家提供的样板卡。现在市面上的产品绝大多数都是公板的,因为使用公板可以减少研发成本,特别是现在产品的推陈出新速度很快,造成绝大多数生产厂商为了追新,只能使用公板。

On node 0 totalpages: 16384
zone(0): 16384 pages
zone(1): 0 pages
zone(2): 0 pages

预留内存大小,在节点0上总共16页, zone(0)设置最小内存为12MB, zone(1)和zone(2)为0页。

Kernel command line: noinitrd root=/dev/bon/3 init=/linuxrc console=ttyS0

Kernel启动命令设为:
/dev/bon/3(在后面的说明中会看到/dev/bon/3是指的flash上的romfs分区。),用来指定根文件系统所在的位置,kernel会将块设备/dev/bon/3当作文件系统来处理。也就是说,内核会根据上面的kernel命令行,知道只读文件系统romfs将是根文件系统rootfs。

start_kernel(void) 中输出的上面的这句信息。这行命令是在linux内核启动过程中都会输出的一句。

Console: colour dummy device 80x30

代码中console_init()的输出信息, 显示控制台属性:一般使用VGA text console,标准是80 X 25行列的文本控制台,这里是对属性进行了设置。

Calibrating delay loop... 99.94 BogoMIPS

BogoMIPS

Calibrate:校准, 进入时延校准循环。这里是对CPU进行一个实时测试,来得到一个大体的MIPS数值。

上面这个输出,在所有的linux系统启动中都会打印出来。

Memory: 64MB = 64MB total
Memory: 62360KB available (1603K code, 437K data, 68K init)

进入内存初始化:mem_init(void), [arch/i386/mm/init.c]

当前内存使用情况,将列出总的内存大小, 及分配给内核的内存大小:包括代码部分,数据部分,初始化部分,总共刚好4M。请留意此处的内核的内存大小的各个值。

Dentry-cache hash table entries: 8192 (order: 4, 65536 bytes)
Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
Mount-cache hash table entries: 1024 (order: 1, 8192 bytes)
Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes)
Page-cache hash table entries: 16384 (order: 4, 65536 bytes)

进入虚拟文件系统VFS初始化:vfs_caches_init()

在内存中建立各个缓冲hash表,为kernel对文件系统的访问做准备,VFS目录树用了类似这样的结构表。

上面的输出信息,在一般的linux启动过程中都会看到。

名词:

    一个单独的dentry通常包含一个指向i节点(inode)的指针。i节点存在于磁盘驱动器上,它可以是一个规则文件,目录,FIFO文件,等等。 Dentry存在于RAM中,并且永远不会被存到磁盘上:它们仅仅为了提高系统性能而存在。i节点存在于磁盘上,当需要时被拷入内存中,之后对它的任何改 变将被写回磁盘。存在于RAM中的i节点就是VFS的i节点,dentry所包含的指针指向的就是它。
POSIX conformance testing by UNIFIX

conformance:顺应, 一致。即POSIX适应性检测。UNIFIX是一家德国的技术公司,Linux 原本要基于 POSIX.1
的, 但是 POSIX 不是免费的, 而且 POSIX.1 证书相当昂贵. 这使得 Linux 基于 POSIX 开发相当困难.
Unifix公司(Braunschweig, 德国) 开发了一个获得了 FIPS 151-2 证书的 Linux 系统. 这种技术用于
Unifix 的发行版 Unifix Linux 2.0 和 Lasermoon 的 Linux-FT。

在2.6的内核中就将上面的这句输出给拿掉了。

Read More...

QQ笔试『转』

声明:以下问题仅供本校园网校内师弟师妹为了考察自己学习的参考,不要传播

1 计算 a^b << 2 (运算符优先级问题)
int a = 2;
int b = 1;
int c = 2;
cout << (a ^ b << c);
6
2 根据先序中序求后序

3 a[3][4]哪个不能表示 a[1][1]: *(&a[0][0]) *(*(a+1)+1) *(&a[1]+1) *(&a[0][0]+4)
cout << *(&a[1][1]) << endl
       <<*(*(a+1)+1) << endl
       << *(&a[1]+1) << endl
       << *(&a[0][0]+4);
6
6
0012FEC8
5

4 for(int i...)
for(int j...)
printf(i,j);
printf(j)
会出现什么问题
 
J没有定义,不在其作用域


5 for(i=0;i<10;++i,sum+=i);的运行结果

6 10个数顺序插入查找二叉树,元素62的比较次数

7 10个数放入模10hash链表,最大长度是多少

8 fun((exp1,exp2),(exp3,exp4,exp5))有几个实参
 2 个

9 希尔 冒泡 快速 插入 哪个平均速度最快

10 二分查找是 顺序存储 链存储 按value有序中的哪些

11 顺序查找的平均时间

12 *p=NULL *p=new char[100] sizeof(p)各为多少 4

13 频繁的插入删除操作使用什么结构比较合适,链表还是数组

14 enum的声明方式 enum COLOR{RED,BLUE,GREEN};

15 1-20的两个数把和告诉A,积告诉BA说不知道是多少,
B也说不知道,这时A说我知道了,B接着说我也知道了,问这两个数是多少

大题:

1 把字符串转换为小写,不成功返回NULL,成功返回新串

char* toLower(char* sSrcStr)
{
char* sDest= NULL;
if( __1___)
{
int j;
sLen = strlen(sSrcStr);
sDest = new [_______2_____];
if(*sDest == NULL)
return NULL;
sDest[sLen] = '\0';
while(_____3____)
sDest[sLen] = toLowerChar(sSrcStr[sLen]);
}
return sDest;
}
 
char toLowerChar(char a)
{
    if(a >= 'A' && a <= 'Z')
       return a - 'A' + 'a';
}
 
char* toLower(char* sSrcStr)
{
    char* sDest= NULL;
    if(sSrcStr)
    {
       int j;
       int sLen = strlen(sSrcStr);
       sDest = new char[sLen + 1];
       if(*sDest == NULL)
           return NULL;
       sDest[sLen] = '\0';
       while(sLen--)
           sDest[sLen] = toLowerChar(sSrcStr[sLen]);
    }
    return sDest;
}


2 把字符串转换为整数 例如:"-123" -> -123

main()
{
.....
if( *string == '-' )
n = ____1______; -1* num(string+1)
else
n = num(string);
.....
}

int num(char* string)
{
for(;!(*string==0);string++)
{
int k;
k = __2_____; *string
j = --sLen;
while( __3__) j--
k = k * 10;
num = num + k;
}
return num;
}

附加题:

1 linux下调试core的命令,察看堆栈状态命令

2 写出socks套接字 服务端 客户端 通讯程序

3 填空补全程序,按照我的理解是添入:win32调入dll的函数名
查找函数入口的函数名 找到函数的调用形式
把formView加到singledoc的声明 将singledoc加到app的声明

4 有关系 s(sno,sname) c(cno,cname) sc(sno,cno,grade)
1 问上课程 "db"的学生no
2 成绩最高的学生号
3 每科大于90分的人数
 
 
 
腾讯
    待遇:硕士年薪10万,本科年薪7万
    1)笔试: C++,基础题目与程序员考试水平相当。
    附加题:
    1.有10亿个浮点数,从中找出1万个最大的数。写一个高性能的算法
    2.Unix后台进程的实现
    3.MFC的多文档模板的加载
    4.数据库SQL语句查询
    2)面试
     技术1面:感觉腾讯的面试安排不是很合理,进去之后有12个面试官,随便找一个面。面我的是个铁面判官,问了几个问题,DirectX技术有没有接触过? 2D,3D引擎原理?我一头雾水,跟他没什么好谈的,感觉,彼此都不感兴趣。然后他就问了一个很基础的问题,写一个程序:从双向循环链表中删除一个节点。 这个当然没有什么问题。不过出来后感觉就没戏
 

1.请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句

#define check(a,b) char*r=((a)-(b))==abs((a)-(b))? "greater":"less"


2.如何输出源文件的标和目前执行行的行数

cout<<"Filename"<<_ _FILE__<<"Line"<<__LINE__<<endl;

3、两个数相乘,小数点后位数没有限制,请写一个高精度算法
4、写一个病毒

while(1)

{

       int *p=new int [10000000];

}
5、有A、B、C、D四个人,要在夜里过一座桥。他们通过这座桥分别需要耗时1、2、5、10分钟,只有一支手电,并且同时最多只能两个人一起过桥。请问,如何安排,能够在17分钟内这四个人都过桥?
AB过2分 A回来1分     3

CD过10     B回来2分     12

AB过2分 共计3+2+12=17


2005年腾讯招聘
选择题(60)
        c/c++ os linux 方面的基础知识 c的Sizeof函数有好几个!
程序填空(40)


1.(20) 4空x5
        不使用额外空间,将 A,B两链表的元素交叉归并


2.(20) 4空x5
MFC        将树序列化 转存在数组或 链表中!

1, 计算 a^b << 2 (运算符优先级问题) :<<的优先级高于^

2 根据先序中序求后序

3 a[3][4]哪个不能表示 a[1][1]: *(&a[0][0]) *(*(a+1)+1) *(&a[1]+1) *(&a[0][0]+4)      :*(&a[0][0]+4)应加5        *(&a[1]+1)

4 for(int i...)
          for(int j...)
            printf(i,j);
            printf(j)
        会出现什么问题 :j没有定义,不在其作用域内

5 for(i=0;i<10;++i,sum+=i);的运行结果 :55先执行循环体再执行++i,sum+=i

6 10个数顺序插入查找二叉树,元素62的比较次数

7 10个数放入模10hash链表,最大长度是多少

8 fun((exp1,exp2),(exp3,exp4,exp5))有几个实参 :两个,其中括号内的","为逗号运算符

9 希尔 冒泡 快速 插入 哪个平均速度最快

10 二分查找是 顺序存储 链存储 按value有序中的哪些

11 顺序查找的平均时间

12 *p=NULL *p=new char[100] sizeof(p)各为多少    :都是4

13 频繁的插入删除操作使用什么结构比较合适,链表还是数组    :链表

14 enum的声明方式 enum COLOR{RED,BLUE,GREEN};

15 1-20的两个数把和告诉A,积告诉B,A说不知道是多少,

问题:A从2到99之间抽了2个数字,把和告诉B,积告诉C
B说我不知道这2个数,但是C也肯定不知道
C说我开始确实不知道,但是现在知道了
B说这样我也知道了
求这2个数.为什么?
我的解答
首先,正确答案是4和13
设B得到的和记做B,C得到的积记做C,这两个数记做x和y。
1.预备结论,
a)100以内的质数有25个,如下:
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
b)歌德巴赫猜想,任何大于6的偶数都能写成两个奇质数的和。
c)B明显大于等于6,而小于等于196
2.一些更要结论。
a)B不可能是偶数。因为B如果是偶数,而偶数都能写成两个奇质数的和,例如22=5+17,那么如果C=5*17=85,则因为C=85只有 一种质因数分解方式,所以C知道这两个数是5和17。也就是说,B说“我不知道这2个数,但是C也肯定不知道”这句话是错误的,C有可能知道。
b)B是奇数,并且一定不能写成两个质数的和。例如若B=19,那么就有可能是2和17,如果C=34=2*17,只有一种质因数分解方式,所以C知道这两个数。
那么不能写成两个质数的和的奇数见下:记做集合M
11,17,23,27,29,35,37,41,47,51,53,57,59,65,67,71,77,79,83,87,89,93,95,97,还有100至196之间的奇数(因为例如103,虽然=101+2,但是101一经大于100)
这些数的思路是这样的,奇数=两个质数和,那一定有一个数是2。不如分析30-40的,可以用排除法,奇数有31,33,35,37,39,但是29+2=31,31+2=33,37+2=39所以要排除31,33,39剩余35,37。
所以B只可能是集合M中的数。
c)B可有多种可能的分解方式,但是只有一种是可以确定的。这句话如果不理解,后面有例子。
3.实际这个题可以分为两个重要部分,一是找到一组这样个数,并证明这组数符合条件,而是证明其它的数组不满足条件。本人只能证明的一部分,第二部分我目前没有更好的方法,只能是列举排除法。
4.下面实例分析
a)若B=11
x=2,y=9,那么C=18=3*6,C会这样想,如果是3和6,那么B=9,而9可以是2+7,那么我C就是14,我肯定可以知道是2和7,所以不能是3和6。也就是说若B=11,B可以判断出是x=2,y=9
x=3,y=8,那么C=24=2*12=4*6,无论2+12,还是4+6都是偶数,可以排除,B可以判断出是x=2,y=9
x=4,y=7,C=2*14,2+16也可以排除,B可以判断出是x=2,y=9
x=5,y=6,C=2*15,2+15=17,17是集合M中的数,也就是说C知道这两个数是什么,但是B不能确定。
B有三组可以确定,那么,B就不知道究竟是那组了,只有一组能判断出来才可以。
一个结论:
(ⅰ)C可以有多中分解方式,但分解中的x+y的和如果是M中的数,那说明这种分解方式不能排除,反之则能排除。
(ⅱ)如果B的几种不同分解方式,有两个或以上的C可以确定,那么这样的B不满足条件(B说这样我也知道了)
(ⅲ)如果C的分解方式中x或y是4,8,16……2^2,另一个是质数,那么这种分解方式可以排除,因为,此时C的其他分解方式不过是,把质因数2分给质数,这样两个数都是偶数了,那么和B也成了偶数,这和前面的结论是矛盾的。
b)若B=17
x=2,y=15,那么C=30=5*6,5+6=11,属于M,不能排除。
x=3,y=14,那么C=42=2*21,2+21=23,属于M,不能排除。
x=4,y=13,那么C=52=2*26,2+26=28,不属于M,可以排除。
x=5,y=12,那么C=60=3*20,3+20=23,属于M,不能排除。
x=6,y=11,那么C=66=2*33,2+33=35,属于M,不能排除。
x=7,y=10,那么C=70=2*35,2+35=37,属于M,不能排除。
x=8,y=9,那么C=72=3*24,2+24=27,属于M,不能排除。
这样,只有一组可以排除,那就是说,如B=17,C根据他知道的积,只有在C=52时,C才能判断出来,其余不能判断。
c)其他的排除法,我只给出可以排除的两种方法。(运用了结论(ⅲ))
23=4+17=16+7。。27=4+23=8+19。。29=2+27=16+13。。35=4+31=32+3。。
37=8+29=32+5。。41=4+37=32+9。。47=4+43=16+31。。51=4+47=8+43。。
53=4+47=8+43。。57=4+53=16+41。。59=4+55=16+43。。65=4+61=16+49。。
67=8+59=64+3。。71=4+67=64+7。。77=4+73=64+13。。79=8+71=64+15。。
83=4+79=64+19。。87=4+83=64+23。。89=16+73=64+25。。91=8+83=64+27。
93=4+89=64+29。。97=4+93=64+33。。
超过100的奇数属于集合M,所以还要研究这些数,当实在过于繁琐,可以用64,32,尤其是64,因为它再乘以任何质数都将超过100,所以很容易找到一种,至于另一种留给读者吧。

B也说不知道,这时A说我知道了,B接着说我也知道了,问这两个数是多少


大题:

1 把字符串转换为小写,不成功返回NULL,成功返回新串

char* toLower(char* sSrcStr)
{
          char* sDest= NULL;
          if( __1___)
          {
              int j;
              sLen = strlen(sSrcStr);
              sDest = new [_______2_____];
              if(*sDest == NULL)
                  return NULL;
              sDest[sLen] = '\0';
              while(_____3____)
                 sDest[sLen] = toLowerChar(sSrcStr[sLen]);
          }
          return sDest;
}
1sSrcStr!=NULL   2 sLen+1    3--sLen&&isUpper(sSrcStr[sLen])
2 把字符串转换为整数 例如:"-123" -> -123

main()
{
          .....
          if( *string == '-' )
              n = ____1______;
          else
              n = num(string);
          .....
}

int num(char* string)
{
          for(;!(*string==0);string++)
          {
              int k;
              k = __2_____;
              j = --sLen;
              while( __3__)
                  k = k * 10;
              num = num + k;
          }
          return num;
}
-num(*string++)    int(*string)   j--
附加题:

1 linux下调试core的命令,察看堆栈状态命令

2 写出socks套接字 服务端 客户端 通讯程序

3 填空补全程序,按照我的理解是添入:win32调入dll的函数名  
        查找函数入口的函数名 找到函数的调用形式
        把formView加到singledoc的声明 将singledoc加到app的声明

4 有关系 s(sno,sname) c(cno,cname) sc(sno,cno,grade)
        1 问上课程 "db"的学生no
        2 成绩最高的学生号
        3 每科大于90分的人数

1。有一栋十层楼的楼,在每个电梯门口放上一颗钻石,这些钻石的大小不同,一人坐电梯从一楼,电梯每到一层楼都开一次门,而且这个人能准确的分辨钻石的大小,请问怎么样能拿到最大的钻石,只有一次机会(就是出了电梯门就进不来了)

2。请估计广州中信大厦是否坚固,写出推理过程。
学校里成绩的高低好坏,对人生来说还言之过早。

1,为节省空间,两个栈共用一个空间,栈底在两边,问什么时候表明空间用完

    答案:栈顶相遇时
    这道题就是很基础的一个题目,因为是第一道题,所以印象比较深^_^
2,char A[5]; char* B ="abcdefg"; void * C; C = new char[100];
      sizeof(A) sizeof(B) size(C)
5,4,4
 
3,爸爸,妈妈,妹妹,小强,至少两个人同一生肖的概率是多少
      1- 12*11*10*9/12*12*12*12 = 43% ,我忘用1减了....
 
然后还有几个看程序给结果的题,考察了类,指针的内容
第二部分:程序填空
   主要要能看出他的思路
第三部分:写代码
     1,关于mfc的,一个控件,显示时间,1s钟刷新一次
     2,SQL语言进行简单的数据库操作,建表,查询,求平均工资等
     不记得语言了,因此只好自创....ft
     3,Unix进程通信有哪些方式,各有什么特点?
     (其中A卷给的是道网络编程题目)
第四部分:主观题
考rp的,比较无聊,手都写酸了....
程序4说明]
 
设 M 叉树采用列表法表示,即每棵子树对应一个列表,列表的结构为:子树根结点的值部分
(设为一个字符) 和用“( )”,括起来的各子树的列表 (如有子树的话) ,各子列表间用“
,”,分隔。例如下面的三叉树可用列表 a( b( c,d ),e,f( g,h,i ))表示。
 
本程序输入列表,生成一棵 M 叉树,并由 M 叉树输出列表。假定输入无错误。
[程序4]
#include〈stdio.h〉
#include〈stdlib.h〉
#define M 3
typedef struct node{ char val;
struct node *subTree[M];
} NODE;
char buf[255] ,*str = buf
NODE *d = NULL
NODE *mackTree( ) /*由列表生成M叉树*/
{ int k; NODE *s ;
s = __(1)__
s -> val = *str++ ;
for ( k = 0 ; k < M ; k++ ) s-> subTree[k] = NULL ;
if(*str='( '){
k = 0;
do { str++;
s -> subTree[k] = __(2)__ ;
if ( *str == ')' ) { str++; break ; }
k = k+l ;
} while ( __(3)__ );
}
return s ;
}
void walkTree( NODE *t ) /*由 M 叉树输出列表*/
{ int i ;
if( t != NULL ) {
__(4)__
if ( t -> subTree[0] == NULL ) return ;
putchar ( '( ' ) ;
for ( i = 0 ; i < m ; i++) {
__(5)__
if ( i! = M - l && t -> subTree[i+l] != NULL )
putchar ( ', ' ) ;
}
putchar ( ') ' ) ;
}
}
 
void main( )
{ printf( "Enter exp:" ) ;
scanf( "%S" , str ) ;
d = makeTree() ;
walkTree( d ) ; putchar( '\n') ;
}
 
 
有两个集合   
集合A{17192155100。。。}   
集合B{722100。。。}   
两个集合都是10万个数据(已排序),要求写一个算法,判断B是不是A的子集,算法时间复杂度为QN

wangyi

1、10个人分成4组 有几种分法?

2、如图:
   7      8      9      10
   6      1      2      11
   5      4      3      12
   16 15 14 13
  设“1”的坐标为(0,0) “7”的坐标为(-1,-1) 编写一个小程序,使程序做到输入坐标(X,Y)之后显示出相应的数字。

3、#include<stdio.h>
  //example input and output
  //in 1 2 3 out 1 3 1
  //in 123456789 2 100 out 123456789 100 21
  long mex(long a,long b,long c)
  { long d;
   if(b==0) return 0;
   if(b==1) return a%c;
   d=mex(a,b/2,c); d*=d;这里忘了;d*=mex(a,b%2,c);d%=c;
   return d;
  }
  int main(void)
  { long x,y,z;
   while(1)
   { if(scanf(%d %d %d,&x,&y,&z)>3) return 0;
   if(x<0) { printf("too small ");continue;}
   if(y<0) { printf("too small ");continue;}
   if(z<1) { printf("too small ");continue;}
   if(y>z) { printf("too big ");continue;}
   if(z>1000000010) {printf("too big ");continue}
   printf(%d %d %d,x,z,mex(x,y,z);
  }}
  根据这个程序,当已知一个输入,算出输出,如:输入 1 3

7. 希尔 冒泡 快速 插入 哪个平均速度最快?
答案:快速排序
快速排序、归并排序和基数排序在不同情况下都是最快最有用的。

8. enum的声明方式
答案:enum 枚举类型名 {
               枚举常量1,
               枚举常量2,
               ...
               枚举常量n
              };
For example:
enum weekday { sunday, monday, tuesday, wednesday, thursday, friday, saturday};
enum weekday week_day;//week_day 就是一个枚举类型变量

9. 频繁的插入删除操作使用什么结构比较合适,链表还是数组?
答案:链表

10. *p=NULL *p=new char[100] sizeof(p)各为多少?
答案:都为4。因为都是指针类型,所占存储空间必然为4。

11. 顺序查找的平均时间
答案:(1+2+3+...+n)/n = (n+1)/2

12. for(i=0,sum=0; i<10; ++i,sum+=i);的运行结果
答案:sum = 55

13. 不能做switch()的参数类型是:
答案:switch的参数不能为浮点型。

14.不使用其他变量,交换两个整型a,b的值
答案:x = x+y; y = x-y; x = x-y

15. 写出float x 与“零值”比较的if语句。
if(x>=0.000001 && x<=-0.000001)(x不为0的比较)
float: 6位精度
double: 16位精度

16.

两个数相乘,小数点后位数没有限制,请写一个高精度算法


*************************************************************************************
数据库
*************************************************************************************
1. 有个表tableQQ,有整型的ID项和字符类型的Nickname项,这两个项都不允许为空
  (1)写出建立该表的SQL语句
  (2)找出Nickname为QQ的用户,按ID降序排列的SQL语句
  (3)写出删除ID为1234用户记录的SQL语句
  (4)写出添加ID为5555,Nickname为'1234'的SQL语句
答案:
  (1) CREATE TABLE tableQQ
      (
       ID NUMBER(12) NOT NULL,
       Nickname Varchar2(30) NOT NULL
       );
      
  (2) select * from tableQQ where Nickname = 'QQ' order by ID desc;
 
  (3) delete from tableQQ where > 
  (4) insert into tableQQ values(5555,'1234');
 
  //删除表
  (5)drop table tableQQ;
 
2. 有关系 s(sno,sname) c(cno,cname) sc(sno,cno,grade)
  1 问上课程 "db"的学生
  2 成绩最高的学生号
  3 每科大于90分的人数
答案:
    (1)select a.sno, a.cno, b.cno, b.cname from sc a, c b where a.cno = b.cno and b.cname = 'db'; 
   
    (2)select sno, max(grade)from sc group by sno;
   
    (3)select cno, count(sno) from sc where grade > 90 group by cno;
   
*****************************************************************************************
===========================================================================================

操作系统 网络

===========================================================================================
1. 描述实时系统的基本特性
答案:在特定时间内完成特定的任务,实时性与可靠性。

2. Internet采用哪种网络协议?该协议的主要层次结构?
答案:TCP/IP协议。应用层、传输层、网络层、数据链路层和物理层。

3. Internet物理地址和IP地址转换采用什么协议?
答案:地址解析协议ARP address resolution protocol

4. IP地址的编码分为哪俩部分?
答案:网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。

Read More...