8/13/2008

C# 获取路径

string str1 =Process.GetCurrentProcess().MainModule.FileName;//可获得当前执行的exe的文件名。
string str2=Environment.CurrentDirectory;//获取和设置当前目录(即该进程从中启动的目录)的完全限定路径。
//备注 按照定义,如果该进程在本地或网络驱动器的根目录中启动,则此属性的值为驱动器名称后跟一个尾部反斜杠(如“C:\”)。如果该进程在子目录中启动,则此属性的值为不带尾部反斜杠的驱动器和子目录路径(如“C:\mySubDirectory”)。
string str3=Directory.GetCurrentDirectory();//获取应用程序的当前工作目录。
string str4=AppDomain.CurrentDomain.BaseDirectory;//获取基目录,它由程序集冲突解决程序用来探测程序集。
string str5=Application.StartupPath;//获取启动了应用程序的可执行文件的路径,不包括可执行文件的名称。(如:D:\project\集团客户短信服务端\bin\Debug)
string str6=Application.ExecutablePath;//获取启动了应用程序的可执行文件的路径,包括可执行文件的名称。
string str7=AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获取或设置包含该应用程序的目录的名称。

5/28/2008

虚拟机

1. VMware workstation vs virtual PC vs Bochs
(1) Bochs : emulates the x86 hardware and some of its peripherals
+ easily portable among a number of platforms & architectures
+ better choice for kernel or complier development
+ runs under all the platforms supported by VMware and Virtual PC and many additional platforms, including *BSD and BeOS.
- the slowest of the three due to emulation
+ only 2 MB
(2) Virtual PC : Some large parts of VirtualPC 4.03 for x86 are emulated, while other parts are virtualized. VirtualPC 5 under Macintosh is 100% emulator.
* In the middle of the others.
+ better choice for application targetting the end-user and the larger corporations
* runs on Windows 9x/ME and with different binaries also runs under NT/2k/XP, OS/2 and MacOS 9/X
- about 20MB
(3) VMware workstation : only emulates certain I/O functions,the rest is all executed through its x86 runtime engine via virtulization.
+ fast speed
+ better choice for application targetting the enterprise and large software houses
- poor portablity
* run on Windows 2000/XP and on Linux
- about 20MB

2. Virtual box
3. qemu
4. 。。

5/24/2008

.Net_linux

http://www.35dx.com/html/dotNet/2/net2934.html

ubuntu 下运行照样可以原生的迅雷

具体过程如下:
一、安装wine
wine 是Linux 下运行windows 程序的必需工具,Windows的程序都是在Wine 提供的环境中运行的。有两种方法安装:1) 通过网络安装 2) 下载安装包离线安装
1、网络安装
打开终端,运行如下命令,取得密钥:
wget -q http://wine.budgetdedicated.com/apt/387EE263.gpg -O- | sudo apt-key add -
后再输入以下指令,获得Wine的apt列表for Gutsy,其它发行版的请见这里:
sudo wget http://wine.budgetdedicated.com/apt/sources.list.d/gutsy.list -O /etc/apt/sources.list.d/winehq.list
安装包有10.8M,得等一阵子。这些都做完以后,再输入下面指令进行更新和升级:
sudo apt-get update
sudo apt-get dist-upgrade
2、下载安装包离线安装
访问:http://wine.budgetdedicated.com/,然后把相应的deb包下载下来(wine_0.9.57~winehq0~ubuntu~7.10-1_i386.deb),下载下来后。可以有三种方法安装:

1) 终端下执行 suod dpkg -i wine_0.9.57~winehq0~ubuntu~7.10-1_i386.deb
2)将deb 文件放进/var/cache/apt/archives 里,然后执行sudo apt-get dist-upgrade
3) 如果你闲麻烦直接把下载来的包双击安装也可以。
二、配置wine
终端下,执行
sudo winecfg
打开配置界面,先看看Application页:

在Windows Version 处选择要模拟的版本。选择相应的版本后,还需要把Windows 下的几个动态库手工copy到~/.wine/drive_c/windows/system32目录下。
sudo mkdir /mnt/c
sudo mount /dev/sda1 /mnt/c
sudo cp /mnt/c/windows/system32/mfc42.dll ~/.wine/drive_c/windows/system32
sudo cp /mnt/c/windows/system32/msvcp60.dll ~/.wine/drive_c/windows/system32
sudo cp /mnt/c/windows/system32/msvcrt.dll ~/.wine/drive_c/windows/system32
sudo cp /mnt/c/windows/system32/msvcirt.dll ~/.wine/drive_c/windows/system32

再看看Drivers页:

虚拟了两个盘:c盘和Z盘,但z盘链接到根/上。还可以自己增加盘符。
再看看Desktop Integration页:

可以安装主题,也可以修改我的文档对应的路径。修改后,按确定。
wine 的工作环境在~/.wine/目录下,这是个隐藏目录,见下图:

driver_c 就相当于Windows下的C盘,下面有windows 和program files 子目录。*.reg 文件就是注册表。dosdevices 目录下有两个链接:一个指向drive_c, 一个指向/,就是在winecfg 的Drivers 页看到的两个盘符。

配置wine 支持中文:
在终端中,执行如下命令:
cd ~/.wine
sudo gedit system.reg
在system.reg 中查找FontSubstitutes,找到

[Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes] 1205592459
"Arial"="simsun"
"Arial CE,238"="simsun"
......
"Tms Rmn"="simsun"

将这个部分下的内容替换为:
"Arial"="simsun"
"Arial CE,238"="simsun"
"Arial CYR,204"="simsun"
"Arial Greek,161"="simsun"
"Arial TUR,162"="simsun"
"Courier New"="simsun"
"Courier New CE,238"="simsun"
"Courier New CYR,204"="simsun"
"Courier New Greek,161"="simsun"
"Courier New TUR,162"="simsun"
"FixedSys"="simsun"
"Helv"="simsun"
"Helvetica"="simsun"
"MS Sans Serif"="simsun"
"MS Shell Dlg"="simsun"
"MS Shell Dlg 2"="simsun"
"System"="simsun"
"Tahoma"="simsun"
"Times"="simsun"
"Times New Roman CE,238"="simsun"
"Times New Roman CYR,204"="simsun"
"Times New Roman Greek,161"="simsun"
"Times New Roman TUR,162"="simsun"
"Tms Rmn"="simsun"

保存退出即可。

三、安装迅雷
我试过迅雷最新版 Thunder5.7.7.441,未成功,安装到最后,报异常崩溃。
又试过迅雷 Thunder5.6.8.329,同样报异常崩溃。最后试迅雷 Thunder5.5.6.274,成功。
迅雷 Thunder5.5.6.274,是最后一个不支持BT的版本,后续新版本增加了BT,EMule下载的支持。难道是BT惹的祸?!!
具体安装如下:
下载Thunder5.5.6.274.exe ,然后在终端中切换到下载目录下,执行:
sudo wine Thunder5.5.6.274.exe
出现迅雷5的安装界面,和Windows 下一样,一路装下去。
装完后,在屏幕最上面的工具条中,选择Application->其他->启动迅雷5,看,出现了迅雷5的界面了吧。
如果没有找到菜单,或者启动没有成功,可以通过命令行方式启动:
sudo cd ~/.wine/drive_c/Program\ Files/Thunder\ Network/Thunder
sudo wine Thunder.exe


然后,选择工具->配置,设置下载目录等各种参数。
这种方式安装后,迅雷是不能和FireFox 集成的。因此,在FireFox中复制URL, 在迅雷中,点新建按钮,将URL 粘贴进去,即可享受高速下载的乐趣。
网上已经有很多文章介绍在Linux下如何用wine 来运行迅雷,但是,这些讲的都是迅雷国际版,这个版本没有使用盗链技术,当下载的URL失效时,就无法再下载。这和Windows 下原生的迅雷,差了一大截。因此本文就是介绍在Linux 下如何运行原生的迅雷程序。

Ubuntu Start 安装

http://hi.baidu.com/zlovez/blog/item/3d99ff1fac127ff1e0fe0bd3.html

5/21/2008

iptables 介绍

iptables 中的指令,均需区分大小写。

ipchains 和 iptables 在语法上的主要的差异,注意如下∶
1. 在 ipchains 中,诸如 input 链,是使用小写的 chains 名,在 iptables 中,要改用大写 INPUT。
2. 在 iptables 中,要指定规则是欲作用在那一个规则表上(使用 -t 来指定,如 -t nat),若不指定,则预设是作用在 filter 这个表。
3. 在 ipchains 中, -i 是指介面(interface),但在 iptables 中,-i 则是指进入的方向,且多了 -o,代表出去的方向。
4. 在 iptables 中,来源 port 要使用关键字 --sport 或 --source-port
5. 在 iptables 中,目的 port 要使用关键字 --dport 或 --destination-port
6. 在 iptables 中,"丢弃" 的处置动作,不再使用 DENY 这个 target,改用 DROP。
7. 在 ipchains 的记录档功能 -l,已改为目标 -j LOG,并可指定记录档的标题。
8. 在 ipchains 中的旗标 -y,在 iptables 中可用 --syn 或 --tcp-flag SYN,ACK,FIN SYN
9. 在 iptables 中,imcp messages 型态,要加上关键字 --icmp-type,如∶
iptables -A OUTPUT -o eth0 -p icmp -s $FW_IP --icmp-type 8 -d any/0 -j ACCEPT




iptables 使用时的样板
在设定 iptables 的封包过滤规则时,有几个样板的动作,若先熟悉它们,往后就可自行套用,依此类推,很快地,您就可以进入这个天地之中。

观察目前的设定
作法如下∶

iptables -L -n
iptablse -t nat -L -n





定义变数
FW_IP="163.26.197.8"



打开核心 forward 功能
作法如下∶

###-----------------------------------------------------###
# 打开 forward 功能
###-----------------------------------------------------###

echo "1" > /proc/sys/net/ipv4/ip_forward




清除所有的规则
一开始要先清除所有的规则,重新开始,以免旧有的规则影响新的设定。作法如下∶

###-----------------------------------------------------###
# 清除先前的设定
###-----------------------------------------------------###
# 清除预设表 filter 中,所有规则链中的规则
iptables -F
# 清除预设表 filter 中,使用者自订链中的规则
iptables -X

# 清除mangle表中,所有规则链中的规则
iptables -F -t mangle
# 清除mangle表中,使用者自订链中的规则
iptables -t mangle -X

# 清除nat表中,所有规则链中的规则
iptables -F -t nat
# 清除nat表中,使用者自订链中的规则
iptables -t nat -X




选定预设的政策
接着,要选定各个不同的规则链,预设的政策为何。作法如下∶

预设全部丢弃∶

###-----------------------------------------------------###
# 设定 filter table 的预设政策
###-----------------------------------------------------###
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP




或者预设全部接受∶

###-----------------------------------------------------###
# 设定 filter table 的预设政策
###-----------------------------------------------------###
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT




各个规则链的预设政策可独立自主的设定,不必受其它链的影响。

以下练习,若目标为 DROP,则 policy 请设为 ACCEPT;若目标为 ACCEPT,则 policy 请设为 DROP,如此方可看出效果。

开放某一个介面
作法如下∶

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

注∶IPFW 或 Netfilter 的封包流向,local process 不会经过 FORWARD Chain,
因此 lo 只在 INPUT 及 OUTPUT 二个 chain 作用。

iptables -A INPUT -i eth1 -j ACCEPT
iptables -A OUTPUT -o eth1 -j ACCEPT
iptables -A FORWARD -i eth1 -j ACCEPT
iptables -A FORWARD -o eth1 -j ACCEPT




IP 伪装
使内部网路的封包经过伪装之后,使用对外的 eth0 网卡当作代表号,对外连线。作法如下∶

###-----------------------------------------------------###
# 启动内部对外转址
###-----------------------------------------------------###

iptables -t nat -A POSTROUTING -o eth0 -s 172.16.0.0/16 -j SNAT --to-source $FW_IP




上述指令意指∶把 172.16.0.0/16 这个网段,伪装成 $FW_IP 出去。

虚拟主机
利用转址、转 port 的方式,使外部网路的封包,可以到达内部网路中的伺服主机,俗称虚拟主机。这种方式可保护伺服主机大部份的 port 不被外界存取,只开放公开服务的通道(如 Web Server port 80),因此安全性甚高。

作法如下∶

###-----------------------------------------------------###
# 启动外部对内部转址
###-----------------------------------------------------###
# 凡对 $FW_IP:80 连线者, 则转址至 172.16.255.2:80
iptables -t nat -A PREROUTING -i eth0 -p tcp -d $FW_IP --dport 80 -j DNAT --to-destination 172.16.255.2:80




开放内部主机可以 telnet 至外部的主机
开放内部网路,可以 telnet 至外部主机。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open 外部主机 telnet port 23
###-----------------------------------------------------###

iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 23 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 23 -d $FW_IP --dport 1024:65535 -j ACCEPT




开放邮包转递通道
开放任意的邮件主机送信包给你的 Mail Server,而你的 Mail Server 也可以送信包过去。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open SMTP port 25
###-----------------------------------------------------###

# 以下是∶别人可以送信给你
iptables -A INPUT -i eth0 -p tcp -s any/0 --sport 1024:65535 -d $FW_IP --dport 25 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp ! --syn -s $FW_IP --sport 25 -d any/0 --dport 1024:65535 -j ACCEPT

# 以下是∶你可以送信给别人
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 25 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 25 -d $FW_IP --dport 1024:65525 -j ACCEPT




开放对外离线下载信件的通道
开放内部网路可以对外部网路的 POP3 server 取信件。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open 对外部主机的 POP3 port 110
###-----------------------------------------------------###

iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 110 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 110 -d $FW_IP --dport 1024:65535 -j ACCEPT




开放观看网页的通道
开放内部网路可以观看外部网路的网站。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open 对外部主机的 HTTP port 80
###-----------------------------------------------------###

iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 80 -d $FW_IP --dport 1024:65535 -j ACCEPT




开放查询外部网路的 DNS 主机
开放内部网路,可以查询外部网路任何一台 DNS 主机。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open DNS port 53
###-----------------------------------------------------###

# 第一次会用 udp 封包来查询
iptables -A OUTPUT -o eth0 -p udp -s $FW_IP --sport 1024:65535 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p udp -s any/0 --sport 53 -d $FW_IP --dport 1024:65535 -j ACCEPT

# 若有错误,会改用 tcp 封包来查询
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 53 -d $FW_IP --dport 1024:65535 -j ACCEPT

# 开放这台主机上的 DNS 和外部的 DNS 主机互动查询∶使用 udp
iptables -A OUTPUT -o eth0 -p udp -s $FW_IP --sport 53 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p udp -s any/0 --sport 53 -d $FW_IP --dport 53 -j ACCEPT
# 开放这台主机上的 DNS 和外部的 DNS 主机互动查询∶使用 tcp
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 53 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! -y -s any/0 --sport 53 -d $FW_IP --dport 53 -j ACCEPT





开放内部主机可以 ssh 至外部的主机
开放内部网路,可以 ssh 至外部主机。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open 外部主机 ssh port 22
###-----------------------------------------------------###

iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 22 -d $FW_IP --dport 1024:65535 -j ACCEPT

# 以下是 ssh protocol 比较不同的地方
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1020:1023 -d any/0 --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 22 -d $FW_IP --dport 1020:1023 -j ACCEPT




开放内部主机可以 ftp 至外部的主机
开放内部网路,可以 ftp 至外部主机。

作法如下∶(预设 policy 为 DROP)

###-----------------------------------------------------###
# open 对外部主机 ftp port 21
###-----------------------------------------------------###

# 以下是打开命令 channel 21
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 21 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 21 -d $FW_IP --dport 1024:65535 -j ACCEPT

# 以下是打开资料 channel 20
iptables -A INPUT -i eth0 -p tcp -s any/0 --sport 20 -d $FW_IP --dport 1024:65535 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp ! --syn -s $FW_IP --sport 1024:65535 -d any/0 --dport 20 -j ACCEPT

# 以下是打开 passive mode FTP 资料通道
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 1024:65535 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 1024:65535 -d $FW_IP --dport 1024:65535 -j ACCEPT

开放 ping
可以对外 ping 任何一台主机。

作法如下∶(预设 policy 为 DROP)

iptables -A OUTPUT -o eth0 -p icmp -s $FW_IP --icmp-type 8 -d any/0 -j ACCEPT
iptables -A INPUT -i eth0 -p icm -s any/0 --icmp-type 0 -d $FW_IP -j ACCEPT

5/17/2008

为你的程序创建一个控制台

经常看到一些程序在运行的时候有一个WINDOWS控制台,感觉非常COOL。实际上有的时候帮助你监视系统运行是很方便的,那么怎么样创建一个控制台呢?

实际上WINDOWS为你提供了一系列的API来完成这个功能,例如:ReadConsole,WriteConsole等,具体参见MSDN。

下面我们用一段代码来说明如何创建Console.

1。首先调用AllocConsole函数来为你进程创建一个Console,该API是将当前进程Attache到一个新创建的Console上。你还可以通过调用SetConsoleTitle(tstrName);来设置Console的Title.

2。使用WriteConsoleOutput来将信息输出到Console上;在输出之前,先要得到Console的HANDLE,这通过GetStdHandle(STD_OUTPUT_HANDLE)来得到,然后将信息组织成Console的格式,然后输出。

3。关闭CONSOLE。当不需要这个CONSOLE的时候,调用FreeConsole来将当前进程从Console中Detach中。

4。通过创建一个进程来为监视你的CONSOLE输入和输出;你可以创建一个线程然后来,在线程中取得标准输入和输出CONSOLE的HANDLE,然后循环监视其事件,再对不同的事件进行处理。

详细代码参见:http://blog.csdn.net/windcsn/archive/2005/11/27/537737.aspx

----------------------------------------------------
你说的是在GUI程序中使用控制台吧, 对于VC, 其实有一个简单的方法:
在选项 Post-builder step 里新建command, 输入:
editbin /SUBSYSTEM:CONSOLE $(OUTDIR)\filename.exe
(其中 filename 为可执行文件名)

在 Project | Setting...中设置, 如果你的可执行文件名为 HelloWorld.exe,
则你新建的 command 就为

editbin   /SUBSYSTEM:CONSOLE   $(OUTDIR)\HelloWorld.exe

C++ links

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}
http://www.cppblog.com/mzty/category/249.html

5/15/2008

public,private,protected继承

对于一个父类(基类),
如果声明一个成员为private,就说明这个东东使我的,不能让其他人用,包括子孙。
如果是protected,我就会告诉我的子孙,你们要小心的用,但绝对不能让外人使用。
如果说是public,那就是说,这个东东大家随便用吧。

对于一个子类(从基类继承而来的),
private是一个吝啬的继承者,他将从祖辈继承下来的东西统统藏起来,不让别人碰触(包括自己的子孙)。(当然他也只能使用祖辈授予其的权力,即只能使用祖辈中的protected和public)。
protected是一个有保护意识的继承者,他将从祖辈继承下来的东西,只允许自己的子孙使用(即使以前祖辈的东西是公众都可以使用的public)。
public是一个循规守据,他不关心祖辈的东西,原来是什么规矩就是什么

5/14/2008

位段

C语言中的结构是有实现位段的能力的,噢!你问它到底是什么形式是吧?这个问题呆会给你答案。让我们先看看位段的作用:位段是在字段的声明后面加一个冒号以及一个表示字段位长的整数来实现的。这种用法又被就叫作“深入逻辑元件的编程”,如果你对系统编程感兴趣,那么这篇文章你就不应该错过!
  我把使用位段的几个理由告诉大家:1、它能把长度为奇数的数据包装在一起,从而节省存储的空间;2、它可以很方便地访问一个整型值的部分内容。
  首先我要提醒大家注意几点:1、位段成员只有三种类型:int ,unsigned int 和signed int这三种(当然了,int型位段是不是可以取负数不是我说了算的,因为这是和你的编译器来决定的。位段,位段,它是用来表示字段位长(bit)的,它只有整型值,不会有7.2这种float类型的,如果你说有,那你就等于承认了有7.2个人这个概念,当然也没有char这个类型的);2、成员名后面的一个冒号和一个整数,这个整数指定该位段的位长(bit);3、许多编译器把位段成员的字长限制在一个int的长度范围之内;4、位段成员在内存的实现是从左到右还是从右到左是由编译器来决定的,但二者皆对。
  下面我们就来看看,它到底是什么东西(我先假定大家的机器字长为32位):
  Struct WORD
  {
unsigned int chara: 6:
unsigned int font : 7;
unsigned int maxsize : 19;
  };
  Struct WORD chone;
  这一段是从我编写的一个文字格式化软件摘下来的,它最多可以容纳64(既我说的unsigned int chara :6; 它总共是6位)个不同的字符值,可以处理128(既unsigned int font : 7 ;既2的7次方)种不同的字体,和2的19次方的单位长度的字。大家都可以看到maxsize是19位,它是无法被一个short int 类型的值所容纳的,我们又可以看到其余的成员的长度比char还小,这就让我们想起让他们共享32位机器字长,这就避免用一个32位的整数来表示maxsize的位段。怎么样?还要注意的是刚才的那一段代码在16位字长的机器上是无法实现的,为什么?提醒你一下,看看上面提醒的第3点,你会明白的!
你是不是发现这个东西没有用啊?如果你点头了,那你就错了!这么伟大的创造怎么会没有用呢(你对系统编程不感兴趣,相信你会改变这么一个观点的)?磁盘控制器大家应该知道吧?软驱与它的通信我们来看看是怎么实现的下面是一个磁盘控制器的寄存器:
│←5→│←5→│←9→│←8→│←1→│←1→∣←1→∣←1→∣←1→∣
  上面位段从左到右依次代表的含义为:5位的命令,5位的扇区,9位的磁道,8位的错误代码,1位的HEAD LOADED,1位的写保护,1位的DISK SPINNING,1位的错误判断符,还有1位的READY位。它要怎么来实现呢?你先自己写写看:
  struct DISK_FORMAT
  {
   unsigned int command : 5;
     unsigned sector : 5;
   unsigned track : 9 ;
   unsigned err_code : 8;
   unsigned ishead_loaded : 1;
   unsigned iswrit_protect : 1;
   unsigned isdisk_spinning : 1;
   unsigned iserr_ocur : 1;
   undigned isready :1 ;
  };
  注:代码中除了第一行使用了unsigned int 来声明位段后就省去了int ,这是可行的,详见ANCI C标准。
  如果我们要对044c18bfH的地址进行访问的话,那就这样:
  #define DISK ((struct DISK_FORMAT *)0x044c18bf)
  DISK->sector=fst_sector;
  DISK->track=fst_track;
  DISK->command=WRITE;
  当然那些都是要宏定义的哦!
  我们用位段来实现这一目的是很方便的,其实这也可以用移位或屏蔽来实现,你尝试过就知道哪个更方便了!

C++位操作

[ 转 ] http://phil2360.spaces.live.com/blog/cns!71CD456F35382A94!132.entry
C++位操作包括两种:传统的C语言方式的位操作和C++中利用bitset容器的位操作

一、传统的C方式位操作:
1.基本操作:
使用一个unsigned int变量来作为位容器。
2.操作符:
| 按位或操作符:result=exp1|exp2;当exp1和exp2中对应位中至少有一个为1时,result中对应位为1,否则为0。
& 按位与操作符::result=exp1&exp2;当exp1和exp2中对应位全为1时,result中对应位为1,否则为0。
^ 按位异或或操作符:result=exp1^exp2;当exp1和exp2中对应位不相同时,result中对应位为1,否则为0。
~ 反转操作符:将位容器中的所有位都反转,1变为0,0变为1。
<< 按位左移操作符:exp<>> 按位右移操作符:exp>>n,将容器中所有的位向右移n位,空出的位用0填充。
|=,&=,^= 分别对应|&^三种操作符的复合操作符。
3.常用操作
这里我们假设有一个result的unsigned int变量用来储存32个学生的成绩(通过和不通过分别用0和1),这样result就有33位(result从右至左,从0开始计算位数,在这个例子中0位被浪费)。
(a) 将第27位设置为及格(设作1)其他位不变:
result|=(1<<27) //任意的位值与1作按位或操作其值为1,而与0作按位与操作其值不变
(b) 将第27位设置成不及格(设为0)。
result&=~(1<<27) //任意的位值与0作按位与操作其值为0,而与1作按位与操作其值不变
(c) 反转第27位的值。
result^=(1<<27) //任意的位值与1作按位异或操作其值为1,而与0作按位异与操作其值不变

二、C++中的bitset容器
1.头文件:
#include
2.声明一个容器:
(a)声明一个指定位数的空容器(所有位设为0): bitset bits;
(b)声明一个指定位数并将指定的几个位初始化为相应值的容器: bitset bits(int);
bitdet bits(string&)
总结:bitset模板类中类型参数传递容器的位数,而构造函数参数通过一个int或一个string&值来从右至左初始化容器中的相应值。
3.bitset的基本用法:

4.bitset与传统C位操作及字符串的转换
可以通过to_string()成员将容器转输出为一个string字符串,另外还可以用to_long()成员将容器输出到传统的用于C风格的位容器中。如:
unsigned long bits = bits.to_long();
sting str(bits.to_string());
5.bitset支持所有的位操作符。

effective c++

[ 转 ] http://www.cppblog.com/apollo/articles/8127.html
面向过程的编程风格 Procedural Programming
1. C++ 不允许改变改变 reference 所代表的对象,对 reference 的所有操作与对“ reference 所代表的对象”所进行的操作相同。

2. 以 by reference 方式传递对象当作函数参数时,复制的将是对象的地址,函数中对该对象的所有操作都相当是对传入的对象进行间接操作。

3. pointer 和 reference 的最重要差异是, pointer 可以为空,使用前一定要确保其值非 0 ,而 reference 必定代表某个对象,不必作此检查。

4. 编译器无法根据函数返回值型别来区分两个具有相同名称的函数,因为返回值型别无法保证提供我们一个足以区分不同重载函数的情境。

5. 由函数指针寻址出来的函数,其调用方式和一般函数相同。

6. 可以给函数指针赋予初值,函数名称即代表了函数的地址。

7. 标准的或项目专属的头文件应用尖括号扩住;用户自行提供的头文件则使用引号。



泛型编程风格 Generic Programming
1. Standard Template Library (STL) 主要由两种组件构成:容器 container 和泛型算法 generic algorithm < 通过 function template 技术,实现与容器及数值类型无关之功能 > 。

2. 容器分类: < 切记: vector 可以是空的,数组则否 >

序列式容器 sequential container : vector, list, deque……

关联式容器 associative container : map, set, ……

3. iterator 及 const_iterator 实际上是各个容器定义式内的嵌套 nested 型别。

4. 使用泛型算法须 #include < algorithm > ,使用 function object 须 #include < functional > 。

5. function object 是某种 class 的实体对象,该 class 对 function call 运算符进行了重载操作从而可使 function object 被当作一般函数来使用。令 function call 运算符成为 inline ,从而消除“通过函数指针来调用函数“时需付出的额外代价。

6. function object adapter 会对 function object 进行修改操作。

7. 绑定配接器 binder adapter < bind1nd, bind2nd > 会使 bineary function object 变成 unary function object ; negator adaper < not1, not2 > 会逆转 function object 的真伪值;另外一种有用的 adapter 叫做 instertion adapter 。 #include < iterator >

8. map 被定义为一对数值,其中 key 通常是个字符串,扮演索引角色,另一个数值是 value 。

9. 任何一个 key 值在 map 或 set 内最多只有一份,若要多份相同 key 值,使用 multimap 或 multiset 。



基于对象的编程风格 Object-Based Programming
1 .在 class 内部定义的 member 函数被自动视为 inline 函数。对 inline 函数而言,声明在 class 内部或外部并无区别,同 non-member inline 函数一样,它应于头文件中定义。

2 . Triangular t(); 被编译器视为一个函数定义!并不是声明或定义一个 Triangular 对象!

3 .以某个 class object 作为另一个 object 的初值时,会发生 default memberwise initialization < 实际上是自动产生一个 copy constructor> ,可以为该 class 提供一个 copy constructor 来改变这一默认行为模式。

4 .若有必要为 class 撰写 copy constructor ,则同样有必要为它撰写 copy assignment operator ,除非撰写 copy constructor 的目的仅仅是为了激活编译器实施 NRV 优化。

5 .凡是在 class 主体以外定义的 const member function ,必须同时在声明与定义时都提供 const 关键字, const 紧接于函数参数表之后。

6 . member function 返回一个指向 member data 的 non-const reference ,实际上等于将该 member data 开放出去,允许程序在其它地方加以修改。由于函数可以根据参数 const 与否 而重载,故可以提供两份定义,一份为 const 版本,一份为 non-const 版本。

8. 设计 class 时,鉴定其 const member function 是一件很重要的事情!

9. 将 member data 声明为 mutable 表明:对该 member data 的修改不会破坏 class object 的常数性。

10. 欲以一个对象复制出另一个对象,先确定两个对象是否相同是个好习惯。

11. 运算符的重载规则:不可以引入新的运算符,除了 ., .*, ::, ?: 4个运算符,其它运算符皆可被重载;运算符的操作数 operand 不可改变;运算符的优先级不可改变;运算符函数的参数列中必须至少有一个参数为 class 型别。

12 . increment 和 decrement 运算符的前置及后置版本都可直接施行于 class object 其之上,编译器会自动为后置版产生一个 int 引数,其值必为 0 。

13 .所谓 friend ,具备了与 class member function 相同的存取权限,可以存取 class 的 private member 。

14 .只要 class 设计者显示提供了 copy assignment operator ,它就会被用来取代 default memberwise copy 行为。

15 .当编译器在编译过程中遇到函数调用,例如 lt(ival) , lt 可能是函数名称,可能是函数指针,也可能是一个提供了 function call 的 function object 。如果 lt 是个 function object ,编译器会在内部将此语句转化为: lt.operator(ival) ;

16 . function call 可以接受多个运算符,通常将 function object 当作参数传给泛型算法。

17 .为了取得某个 member function 的地址,只需对函数名称施以取址 address-of 运算符,同时,函数名称之前必须先以 class object 运算符加以修饰,而返回型别及参数表皆不需指明,如: void (classname::*mfptr) (int) = &classname::mfname;

18 .注意所谓的 maximal munch 编译规则,如: static vector< vector< int > > seq; 两个 ”>” 号之间必须加有空格,否则无法成功编译!

19 . pointer to member function 和 pointer to function 的一个不同点是:前者必须通过同类的对象加以调用。 .* 符号是针对 class object 的 pointer to member selection 运算符, ->* 符号是针对 pointer to class object 的 pointer to member selection 。使用它们时注意必须加上外围小括号!如: (classobject.*mfptr)(par);





面向对象编程风格 Object-Oriented Programming
1. 面向对象编程的两项最主要的特性是继承 inheritance 和多态 polymorphism 。

2. 动态绑定 Dynamic binding 是面向对象编程风格的第三个独特概念,即找出实际被调用的究竟是哪一个派生类的函数。而静态绑定 Static binding 则在程序运行之前就决议出应该调用哪一个函数。

3. 多态和动态绑定的特性只有在使用 pointer 或 reference 时才能发挥。

4. staitic member function 无法被声明为虚拟函数。

5. 任何一个类只要有纯虚拟函数,程序就会因其接口的不完整而无法为它产生任何对象,这种类只能作为派生类的子对象 subobject 之用,而且派生类必须为所有纯虚拟函数提供确切的定义。

6. 根据一般规则,凡基类定义有虚拟函数,其 destructor 应声明为 virtual 。但 Stanley B.Lippman 并不建议在这个基类中将其 destructor 声明为 pure virtual ,而是提供空白定义: inline baseclass::~baseclass(){};

7. 对于 public inheritance ,继承而来的 public 成员和 protected 成员,无论在继承体系中的深度如何,都可视为派生类自身拥有的成员。

8. 每当派生类有某个 member 与其基类的 member 同名时,便会遮蔽住基类的那份 member ,若要在派生类中使用继承而来的那份 member ,必须使用 class scope 运算符加以修饰。

9. 不可为抽象基类定义任何对象,它们扮演的角色是每个派生类的 subobject ,基于此点,一般将抽象基类的 constructor 声明为 protected 而非 public 。

10. 派生类之 constructor ,不仅必须为派生类之 data members 进行初始化操作,还需为其基类之 data members 提供适当的值。 copy constructor 和 copy assignment operator 的情形也一样,唯一棘手的是,必须明白调用基类的 copy assignment operator : base::operator = (rhs);

11. 改写基类提供的虚拟函数,派生类提供的定义其函数型别必须完全符合基类所声明的函数原型,包括参数列、返回型别、常量型 const-ness 。但是,对于“返回型别”有个例外:当基类的虚拟函数返回某个基类形式(通常是 pointer 或 reference )时,派生类中的同名函数可以返回该基类所派生出来的型别。

12. 在两种情况下,虚拟函数机制不会出现预期行为: 1 )在基类的 constructor 和 destructor 内; 2 )使用基类的对象而非对象的 pointer 或 reference 。

13. typeid 运算符是 RTTI 的一部分,可以用它来查询多态化的 class pointer 或 class reference ,获得其所指对象的实际型别。 typeid 运算符会返回一个 type_info 对象,其中存储着与型别相关的种种信息。 #include



异常处理 Exception Handling
1. 初学者常犯的错误:将 C++ 异常和 segmentation fault 或是 bus error 这类硬件异常混淆在一起。

2. 在异常处理机制终结某个函数之前, C++ 保证函数中的所有局部对象的 destructor 都会被调用。

3. auto_ptr 是标准程序库提供的 class template ,它会自动 delete 通过 new 表达式配置的对象。 auto_ptr 将 dereference 运算符和 arrow 运算符予以重载,使得我们可以像使用一般指针一样使用 auto_ptr 对象。 #include

4. 如果 new 表达式无法从程序的自由空间 free store 配置到足够的内存,它会抛出 bad_alloc 异常对象。如果要压抑不让 bad_alloc 异常被抛出,可以这么写: somepointer = new (nothrow) someclass; 这样,如果 new 动作失败,返回值为 0 。

5. 标准程序库定义了一套异常类体系 exception class hierarchy ,其最根部是名为 exception 的抽象基类。 exception 声明有一个 what() 虚拟函数,会返回一个 const char* ,用以表示被抛出异常的文字描述。 #include

6. ostringstream class 提供“内存内的输出操作”,输出到一个 string 对象上。当需要将多笔不同型别的数据格式转化为字符串表现式时,它尤其有用。 ostringstream 提供的 str() 可以返回对应的那个 string 对象。 #include

7. iostream 库也对应提供了 istringstream class ,如果需要将非字符串数据的字符串表现式转化为其实际型别, istringstream 可派上用场。

8. string class 的转换函数 c_str() 会返回 const char* !

5/11/2008

C++ reference

FILE -> http://www.cplusplus.com/reference/clibrary/cstdio/FILE.html

c++ file I/O

[origin:]http://simeon.blog.51cto.com/18680/4454
c++ file i/o with binary files using fstream class is a simple task. fstream class has the capability to do both input as well as output operati i.e., read and write. all types of operati like reading/ writing of characters, strings, lines and not to mention buffered i/o are supported by fstream.
operating systems store the files in binary file format. computers can deal with binary numbers. but binary files are not readable by humans. our level of comfort lies with proper ascii or unicode characters. this article deals with how c++ file i/o class fstream can be used for reading and writing binary files. for ascii file operati in c++, refer to c++ text file i/o article.
for our c++ file i/o binary file examples, we assume a struct websites with two members as follows.
// struct for c++ file i/o binary file sample
struct websites
{
char sitename[100];
int rank;
};
write operati in c++ binary file i/o:
there are some important points to be noted while doing a write operation.
• the file has to be opened in output and binary mode using the flags ios::out (output mode) and ios::binary( binary mode)
• the function write takes two parameters. the first parameter is of type char * for the data to be written and the sec is of type int asking for the size of data to be written to the binary file.
• file has to be closed at the end.
// sample for c++ file i/o binary file write
void write_to_binary_file(websites p_data)
{
fstream binary_file("c:test.dat",ios::out|ios::binary|ios::app);
binary_file.write(reinterpret_cast(&p_data),sizeof(websites));
binary_file.close();
}
the above c++ file i/o binary sample function writes some data to the function. the file is opened in output and binary mode with ios::out and ios::binary. there is more specifier ios::app, which tells the operating system that the file is also opened in append mode. this means any new set of data will be appended to the end of file.
also the write function used above, needs the parameter as a character pointer type. so we use a type c reinterpret_cast to typecast the structure into char* type.

read operati in c++ binary file i/o:
this also has a similar flow of operati as above. the difference is to open the file using ios::in, which opens the file in read mode.
// sample for c++ file i/o binary file read
void read_from_binary_file()
{
websites p_data;
fstream binary_file("c:test.dat",ios::binary|ios::in);
binary_file.read(reinterpret_cast(&p_data),sizeof(websites));
binary_file.close();

cout< cout<<"rank :"<< p_data.rank<
}
most of the programs will usually go for ascii text mode files only. but there will be some occasi where the c++ file i/o with binary files will be very useful.
this " c++ file i/o using binary files" article gives some very basic samples for read and write. advanced c++ file i/o operati like seek, checking the file pointer validity etc., are also needed to be learnt while writing bigger programs.
cfile is the class used for handling files in mfc. this class can be used for creating, reading, writing and modifying files. it directly provides unbuffered, binary disk input/output services, and it indirectly supports text files and memory files through its derived classes.
cfile - creating a file:
there are two ways of creating files. one way is to instantiate the cfile object with the file path. this creates the file. the sec way is to call the open function. this also creates the file.
cfile cfile_object( "c:testcodersource_cfile_example.txt", cfile::modecreate|cfile:: modereadwrite);

cfile cfile_object;
cfile_object.open( "c:testcodersource_cfile_example.txt", cfile::modecreate|cfile:: modereadwrite);

the first parameter to both the functi (cfile() c and open()) is the physical path of the file in the disk. the sec parameter is an enumerated constant. this specifies the mode of opening the file object. the above c modecreate implies "create a new file" and modereadwrite means "open the file for both reading and writing".
if the file is opened without specifying the mode c sharedenyn this file can be opened in read mode by other programs. this feature will be necessary for text files, logs created by programs. for creating text files we use cfile::typetext and for binary files cfile::typebinary.
cfile - writing to a file:
the function write is used to write data to the files. the sample code is as follows.

cfile cfile_object;
cfile_object.open( "c:testcodersource_cfile_example.txt", cfile::modecreate|cfile::modewrite);

char szsampletext[100];
strcpy(szsampletext, "sample text for cfile write function example");
cfile_object.write (szsampletext,100);
if there is any need to write text line by line, it is better to use the class cstdiofile.
cfile - reading from a file:
the function read is used to read data from files. the sample code is,

cfile cfile_object;
cfile_object.open( "c:testcodersource_cfile_example.txt", cfile::modecreate|cfile::modewrite);

char szsampletext[100];
uint lbytesread = cfile_object.read (szsampletext,100);
the function returns the number of bytes read from the file. the maximum number of characters read will be the sec parameter of the read function.
cfile - closing the file:
the close function is used to close the file. but the close function need not be called, as the destructor will automatically call it if the file is open. so when the object goes out of scope, the destructor calls close function.
file handling is an important part of all programs. most of the applicati will have their own features to save some data to the local disk and read data from the disk again. c++ file i/o classes simplify such file read/write operati for the programmer by providing easier to use classes.
c++ file i/o classes and functi
there are 3 file i/o classes in c++ which are used for file read/write operations. they are
• ifstream - can be used for file read/input operati
• ofstream - can be used for file write/output operati
• fstream - can be used for both read/write c++ file i/o operati
the most important methods which will be used for any file operati are:
1. fstream::open method - to open the file
2. fstream::operator >> and fstream::operator << - for reading from or writing to the file.
3. fstream::close - flushes all buffer and close the file
reading a text file using fstream class:
there are several ways of reading the text from a file. but all of them have a common approach as follows.
1. open the file
2. read the data
3. close the file
this sample code snippet explains how to use the c++ file i/o stream operators to read data from a file. in all cases the header file fstream.h must be included.
________________________________________
#include
int main()
{
char str[2000];
fstream file_op("c:test_file.txt",ios::in);
while(file_op >> str)
cout < < str ;

file_op.close();

return 0;
}
________________________________________
the class fstream, which is used above is the which is comm used for c++ file i/o manipulations. the c of fstream takes 2 parameters. one is the file path and the sec is the file open mode. there are several open modes, each of them with a different purpose. some of them are ios::in for reading, ios::out for writing, ios::app for appending to the end of file, ios::binary for opening in binary mode etc.,
now for the purpose of this article, as the data is read from the file, the flag ios::in is used. after this, the read operation is c till the end of the file. the while loop ensures a c read till the end of the file or it encounters any abnormal break. if the program is built and run , it displays all the data read from the file. the c++ file i/o read job is done.
but if we look at the output closely, there is a draw back in using this stream operator read. the output misses the white spaces and the end of line characters. in order not to miss these characters we can either use fstream::get() or fstream::getline() methods. here is the example for using fstream getline method.
________________________________________
#include
int main()
{
char str[2000];
fstream file_op("c:test_file.txt",ios::in);
while(!file_op.eof())
{
file_op.getline(str,2000);
cout < } file_op.close();
cout <
return 0;
}

________________________________________
writing to a text file using fstream class:
writing to a text file can also be achieved with the stream operators. this also follows the same order of operati though with a slight difference.
1. open a file - in write mode
2. write to a file
3. close the file
look at the following sample code to see the difference.
________________________________________
#include
int main()
{
fstream file_op("c:codersource_file.txt",ios::out);

file_op<<"test write to file";
file_op.close();
return 0;
}
________________________________________
to modify the data or to seek to a different position inside the file, the c++ file i/o class fstream provides member functi like seekg() etc., these functi can be used to relocate the record insert position to the desired locations.
after all the c++ file i/o operati we do a fstream::close(), to close the file pointer. this is not mandatory. even if this function is not called by the applicati the destructor of the fstream class will close the file when the object goes out of scope.

5/10/2008

Do you raelly know Engilsh?

Do you raelly know Engilsh?
At laest in Egnlish, wehn pepole raed, tehy
usaully wlil not noitce taht the charcatres bewteen
the frist ltteer and the lsat leettr are not in a
corrcet oredr. In fcat, hmuan brian does recongize
wrods by seeknig the fsirt ltteer and the lsat leettr,
and tehn fnidnig whcih charatcers are insdie of tehm.
See! All the wrods hree wtih mroe tahn 3 leettrs are
all wirtten in a worng way! Do you niotice taht?

error summary

+fatal   error   C1075   :     配对符号不匹配
Visual C++ Concepts: Building a C/C++ Program
C/C++ Build Errors[http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.71).aspx]

Common C++ Errors

These error statements were generated by g++ (Version?) on an HP workstation (Model?).

转自 : http://www2.hawaii.edu/~pautler/How-to/c++-compiler-errors.html

Compiler links

Compile errors

Run-time errors

Style tips

Compiler errors mention line numbers in a file. If you are using an emacs editor, a quick way to access line N is to go to the top of the file (Esc plus <) and then jump down (Ctrl-u, then N-1, then Ctrl-n).
Emacs documentation
Emacs links


Compile errors

table.C:7: parse error before '<'

If table.h declares a template class, then you're probably including table.cc in your compile command by mistake. Alternatively, you might be defining a template method with an unnecessary <...> after the :: and before the parameter list.

course.cc:26: parse error before '>'

If course.cc declares or instantiates a nested template object
(e.g., Table >; ), then make sure that there is a space between the two >s or the compiler will interpret it as either the insertion or binary shift operator >> !

table.C:65: parse error before '&'

This explanation actually applies to any special character in a parse error, not just &. (The character used appears to be the first special character following the return type of the template function that appears on the line mentioned by the error).

If you have template functions in table.h, and you force all instantiations at once in one file (say, instan.cc), then you might try moving the table.h include statement closer to the end of all the includes. This change should allow the types stored in Table collections to be loaded before the collection itself is.


stu-views.cc:18: warning: implicit declaration of function `int setw(...)'

You haven't included the library that setw is in. (The compiler assumes all undefined functions return int and take (...) as parameters, so don't take these as clues.)


table.C:41: no matching function for call to `TableIterator<...>::TableIterator<...> (const Table<...> *, int)'

If you are passing 'this', or any other const variable, as an argument to a function that doesn't declare that parameter as const, then you could get this error. In this particular case, the TableIterator constructor was written to expect a regular Table*, not a const Table*, and that was fixed just by changing its parameter list.

foo.h:25: no matching function for call to
`Table >::
Table > (int, Ascending, bool (*)(const int *const int *))'
table.C:10: candidates are:
Table >:: Table(int, Ascending, bool (*)(int *const &, int *const &))

You may be having trouble with your collection constructor because you declare it incorrectly. If your declaration here is:

    Table<> > data;

You need to make it:

    Table< color="#0000FF">const int*> > data;


collect2: ld returned 1 exit status
/bin/ld: Unsatisfied symbols:
DynArray::DynArray(int, int const &)(code)

Unsatisfied symbols mean that the linker can't find the definition of these operations. Possible reasons:

  • the .o containing them wasn't in the list of files you compiled,
  • the class they belong to is a template and wasn't instantiated (for the usual g++ reasons),
  • the operations are defined as inline in some source file rather than in a header file,
  • the method simply wasn't defined (don't trust the header file prototype).
    check that the method name is preceded by MyClass::
  • Tip: Make the method private and see who is trying to use it. According to Alex, "G++ has some problems with how templates mix with defaults, so it might be that you have to define some methods for classes for which you might not think you have to." For example, if class Barney contains a collection, its default op== might go undefined and you'll have to define it yourself.


charts.cc: In method `class ChartData * ScoresChart::generateData()':
charts.cc:84: cannot lookup method in incomplete type `Student'

You've put a forward declaration for Student somewhere but not #included "student.h" in the .cc file where Student methods are used. In this particular case, "charts.h" does not have a forward declaration, but it does include "course.h" which has such a forward, so "charts.cc" must still do the include.

Alternatively, you might have put the forward declaration for Student inside Course, rather than outside and just before it, where it probably belongs.


foo.h:25: no matching function for call to
`Table::Table (int, bool (*)(const int *, const int *))'
table.C:10: candidates are: Table::Table(int, bool (*)(int *, int *))

The mismatch here is that the collection constructor expects const parameters to its boolean fn and it's not getting them. The fix is to change the template declaration of the collection -- Table. This assumes that the fn you're passing to the constructor already declares its parameters correctly.


course.cc: In function `static class Singleton* Singleton::Instance()': 
course.cc:36: cannot call member function `Singleton::instanceExists() const' without object

If Instance() is a static member function, then 'this' is not available inside and you can't call other member functions of Singleton. You have to access data fields of the object directly.


stu-views.cc:140: bad argument 1 for function `Barney::Barney(int)' (type was class Barney)

You're missing a copy constructor for Barney.

charts.cc: In method `void Fred::findAndTally(class Label *)': 
charts.cc:39: bad argument 2 for function Barney::FindIf(blahfunc, ...) (type was {unknown type})

You might be passing FindIf a pointer to a template function, and you are hoping it will instantiate it with the appropriate type information. But the compiler is unable to infer how to instantiate the passed func. Add a forced-instantiation statement; alternatively, some compilers allow you to parameterize template fns when you call them.


charts.cc: In method `ScoreData::ScoreData()':
charts.cc:53: cannot allocate an object of type `ScoreLabel'
charts.cc:53: since the following virtual functions are abstract:
charts.cc:53: bool ChartLabel::operator ==(const class ChartLabel &) const

You probably defined subclass ScoreLabel's op== to take another ScoreLabel as its argument. Unfortunately, the parameter types of virtualized fns must all match -- so change the type of the argument to ChartLabel, the base class. (Hopefully, ScoreLabel doesn't have any special data fields that need to be included in op== comparisons.)


g++ note on template function instantiation

If you've defined a template function, and there is one template parameter that only appears as the return type of the function, then g++ will fail to instantiate the function using that parameter even though you mention it as part of your explicit instantiation. One fix is to add a dummy argument to the function of the same type as the return value.



Run-time errors

Pid 10571 received a SIGSEGV for stack growth failure. 
Possible causes: insufficient memory or swap space, or stack size exceeded maxssiz.

You're invoking an infinite regress of fn calls. If you're using the Singleton pattern, one way this can happen is by deleting the static member data inside a destructor; the proper way of freeing the static data is to write a static removeInstance() method that deletes the static data and which is called once, say at the end of main().


segmentation fault

There are many possible causes for this, but a subtle one occurs when you have container class B with overloaded ops such as +=. If one of your variables V is a B* and you apply += to it, be sure you're doing 
((*V) += foo) and not (V += foo), otherwise pointer arithmetic will probably cause a segmentation fault.

Another likely cause is if you have any code like, elements = new T[len], where len could be 0, then you should replace it with this code,

    if (len > 0)

      elements = new T[len];

    else

      elements = 0;

because new[0] doesn't return 0.

Still another possible cause is that you seta string to 0 rather than "" as in, const char* name = 0, and then call a string method on it, for example,strlen(name).

In general, segmentation faults occur when you follow bad pointers, typically when something is deleted that wasn't allocated with new.


Floating exception (core dumped)

You probably tried to divide by zero.


Style tips

Don't use NULL in a C++ program. It's not officially defined as part of C++ and there is no reason to use it. An iterator is often a better choice than a pointer most places where you pass in or return a pointer (e.g., the result of a Find method).

5/02/2008

留住转瞬即逝的相遇

我们素不相识而能够在相同的时间相同的地点相遇,只能说明我们几乎是在相同的时间相同的地点具有相同的想法、激情、思想和冲动,所以,才会有这穿越时间与空间的相遇。
邂逅,不是什么偶然,而是一连串相同的偶然中的必然,是一种心灵穿越时空的交流,就比如我们,正因为有相同的心境、想法和冲动,甚至是相同的思维和认识方式才会邂逅。
  虽然我们每天每时每地都会碰到许许多多形形色色的人,但那不是邂逅,邂逅是一种相互吸引相互碰撞的相遇,我们彼此吸引一见如故。

你我在不同的时间思念着对方,但在相同的时间与对方形同陌路;机缘巧合让彼此相遇、相识、相知、相恋,却因时间空间的交错失去了彼此。 

身边一个个陌生人和自己擦肩而过,也许有一个人天天都在相同的时间以相同的姿势与你在相同的地方相遇,但你们却依然陌生,一直陌生。

在相同的时间、投缘的人、相投的脾气和秉性相遇,这是很小的机率,能做的唯有真诚、珍惜!

嵌入式平台的发展

UMPC - 超便携移动个人电脑 (Ultra Mobile PC)
微软叫它做Origami计划、intel则称它为UMPC 事实上,在微软和intel的计划里,它就是定位于PDA和NB间(更严格说应该是之前微软力图推广的平板电脑)间的新类型产品:Origami计划实际透露出原本平板电脑的发展方向发生了变化:更小! 
http://nb.zol.com.cn/29/296730.html
据国外媒体的报道,微软正计划推出下代超级移动笔记本电脑产品,代号为Haiku。虽然微软倡导的UMPC(超级移动电脑)计划现在已经得到了众多厂商的支持,大家可以看到三星Q1便携移动电脑的屏幕只有7英寸,在六月份将正式推出,国内的电脑厂商方正也推出了相应的产品,但是,令人遗憾的是,这款产品的价格令人望而却步,三星Q1的配置虽然不是特别突出,但售价却超过了10000元。另一方面,操作的便携性,电池的续航能力都是超级移动电脑的弊端。
  微软倡导的UMPC计划并没有像预先所期待的那样在市场上引起巨大的震动,根据YAHOO的消息称,微软将继续开发更为优秀的超级移动电脑,代号为Haiku的移动电脑有望在明年推出。
微软公司在2002年便开始了超级移动电脑计划,第一款超级移动电脑的代号为“Go”,采用了4.5英寸的显示屏,目前一些厂商推出的移动电脑代号为Origami,屏幕为7英寸,微软希望用户在7英寸的屏幕上也可尽情地享受游戏,欣赏影片,当然有些用户还是很难习惯在如此小的屏幕上来观看视频。
 它们在性能上的部分特点: 

  使用Windows XP Tablet PC Edition 2005 操作系统 ; 
  采用7寸(或者更小的屏幕)800 x 480 分辨率; 
  提供WLAN及蓝牙方式连接;   如果计划目标真能实现,便携类产品里这玩意的优势就很明显了——不会通吃,但你会发现它是很多产品的终极: 
  MP4在它面前算啥?想想一台mini PC能播放啥格式的视频?可以说只要通过软件,啥格式都支持了、然后再加上无线连接的配合; 
  GPS在它面前算啥?只要配合接收的头,它天然就是一个GPS设备——这在性能比它弱的PDA上都已经产生了。假如UMPC再推出标准选配附件(瞄准GPS去的); 
  车载多媒体系统算啥?前面两项功能加起来,不就是个车载多媒体、导航设备吗? 
  更甚至,结合无线环境+类SKYPE网络通话软件,它的更小版,甚至可以作为无线语音通讯的终端产品了; 

天极ChinaByte 5月20日消息(他山石 编译)据国外媒体报道,消息灵通人士透露,微软公司已经准备就绪,将发布最新的基于Vista 操作系统的超移动‘Origami’规格。

  消息称,这一规格可能提倡的笔记本重量将低于1.5英镑,配备了5英寸或7英寸显示器。同时需要一个完整的QWERTY键盘,一个触摸屏,1GB内存,电池寿命在三至四小时之间。

  去年微软公布了Origami 项目,韩国三星电子也推出了预装有Windows XP操作系统的超移动计算机。目前该公司已经发布了运行Vista软件的Q1P超移动计算机。

  微软开发经理Vikram Madan在一份声明中说:“英特尔开发了一款专门用于超移动计算机的平台,随后笔记本发展的趋势是许多计算机制造商是否将采用英特尔的这一平台,如果计算机制造商需要英特尔的移动平台,它们产品的运行速度将更快。
http://news.chinabyte.com/102/3342102.shtml

对于移动市场来说,2006年最引人的是Intel Napa平台的问世与普及。其实除了Napa之外,市面上不少超Mini的UMPC产品也是消费者关注的焦点。目前,国内的方正、华硕以及韩国的三星、日本的索尼都推出了相应产品,现在我们从国外某网站得到消息,苹果电脑也将推出旗下的UMPC产品。
-------------------------------------------------------
Apple:
苹果今年首次推出Intel核心的MacBook,比起之前的产品在性价比方面已经大幅提高;而本次MacBook Tablt PC相关图片的透露,再次表明苹果今后将进步提升旗下产品在移动市场的占有率。据悉,这款MacBook Tablt PC的售价将为2499美元。
http://www.umpc.org.cn/Article/UMPCnews/200609/116.html

--------------------------------------------------------
网络推动手持设备市场 英特尔看好UMPC市场

在过去的10年中互联网呈现这样几个阶段:1996-2000年属于拨号时代,2000年至今是宽带时代,2006年后将会是酷睿和个人互联网时代。而在这个一个时代中,一个介于手机和PC之间的手持终端设备将会开创一个时代,打造一个新的并且是巨大的市场。UMPC就是其中之一。“现在我们主要研发的是7寸屏,今后还会有5寸屏的产品。”杨旭精心勾画UMPC的未来。 
http://www.umpc.org.cn/Article/UMPCnews/200609/104.html

--------------
google:
2007年11月5日,谷歌宣布发起成立开放手机联盟,这一联盟将会支持Google可能发布的手机操作系统或者应用软件,共同开发名为Android的开放源代码的移动系统,争取把手机打造成功能强大的移动计算机。这是自传言Google研发手机后,Google公司首次向外界公布其手机战略。 

    目前参加开放手机联盟的企业已经达到了34家,包括手机制造商、手机芯片厂商和移动运营商,如高通、博通、宏达、英特尔、三星电子、摩托罗拉、德州仪器,中国移动、美国第三大移动运营商SprintNextel公司、日本移动通信巨头KDDI和NTTDoCoMo、意大利电信、西班牙电信等。由于在智能手机上采用了Symbian操作系统,手机霸主诺基亚并未出现在联盟中。 

http://news.xinhuanet.com/newmedia/2007-11/16/content_7085703.htm

--------------------------------------
Nokia Internet Tablet发布

诺基亚已经在欧洲的12个城市开始发售770 Internet Tablet,售价从349-369欧元不等。 770采用Linux作为操作系统,而且正如他的名字一样770的主要功能均围绕Internet,并不提供电话功能。 
Google Phone这么热门的话题,本站已经讨论了不少。就在Google释放SDK(软件开发套件: Software Development Kit)之前,让我们再谈一谈最近如火如荼的Linux智能型手机市场吧。

原本Linux智能型手机市场里面有几个主要玩家,如Trolltech的Qtopia Phone Edition, OpenMoko的Neo1973, Motorola的EZX平台(基于Trolltech的QT), 韩国Mizi Research的PRIZM以及Nokia的Maemo(虽然有点不太算...),Palm自有的Linux平台以及Access Linux Platform,如果加上Symbian将有可能移植到Linux的传闻,那么Linux智能型手机市场还真热闹...

接下来,我们把重点放到自称开放平台的Android吧。

Openhands的Poky Linux是一个为移动平台开发的基于Gnome的linux发行版,现在他们发行了有重大意义的Poky Linux 3.0,也就是Blinky.Blinky基于X11,GTK+和Matchbox窗口管理器,并包含了一个全新的应用程序架构和主题界面Sato0.1.


Blinky和Nokia赞助的Maemo.org计划非常相似,但是和它的Hilton图形用户界面不同的是,它使用了全新的Sato1.0组件.

Heroes S1

第一集:
Where does it come from?
它从何而来
This quest, this need to solve life's mysteries when the simplest of quetions can never be answered.
这种渴望 这种需求 想去揭开生命奥秘却从未有过答案
Why are we here?
我们为什么在这
What is the soul?
灵魂是什么
Why do we dream?
我们为什么做梦
Perheps we'd better of not looking at all.
漠不关心也许更好
Not delving, not yearning.
不钻研 不渴求知晓
That's not human nature.'
这不是人类的本性
Not the human heart.
也不是人类的心意
That is not why we are here.
更不是我们存在的目的

第二集:
We all imagine ourselves the agents of our destiny capable of determing our own fate
所有人都幻想着做命运的代理人 能够决定我们自己的命运
But have we truly any choice in when we rise? Or when we fall?
但是我们真的能够掌握人生的起起伏伏吗
Or does a force larger than ourselves bid us our direction?
亦或有另一种更加强大的力量操纵着我们前进的方向
Is it evolution that takes us by hand?
是进化将我们玩弄于鼓掌之中吗
Does science point our way?
还是科学帮我们指点迷津
Or is it god who intervenes, keeping us safe.
还是说是上帝让我们平平安安

For all his bluster, it is the sad province of man that he cannot choose his triumph.
无论他如何自大 人的可悲之处在于不能选择自己的成功
He can only choose how he will stand when the call of destiny comes.
他只能选择如何回应命运的召唤
Hoping that he'll have the courage to answer.
希望他有回应的勇气


第三集:
Suddenly, the change in your life that should have been wonderful, comes as a betray.
突然你生命中原本美丽的变化会反过来出卖你
It may seem cruel, but the goal is nothing short of self-preservation.
这也许很残酷 但是没有比自我保护更重要的了
Survival.
一切都为了生存

This force, evolution, is not sentimental.
这种力量 进化 是没有感情的
Like the earth itself, it know only the hard facts of life's struggle with death.
就象地球本身 它只知道生命与死亡斗争的残酷现实
All you can do is hope and trust that when you've served its needs faithfully,
你只能希望并且相信当你忠实的满足它的需要
there may still remain some glimmer of the life you once knew.
也许还留下一点你曾经了解的生命的火光

第四集:
Sometimes questions are more powerful than answers.
有时候问题的力量比它的答案能强大
How are these happening? What are they?
怎么会这样 是什么问题
Why them , not others?
为什么是它们而不是别的
Why now?
为什么是现在
What does it all mean?
它们到底有什么意义


第五集:
When a change comes, some species feel the urge to migrate.
当变化来临时 某些物种便感到迁移的冲动
They call it zugunruhe
人们把这叫做迁移兴奋
The pull of the soul to a far-off place.
将灵魂牵往远方
Following a scent in the wind, star in the sky.
跟随着风中的一缕气息 天空中的一点星光
The ancient message comes, calling the kindred to take flight and to gater together.
来自远古的讯息 召唤着整个家族启程 团聚
Only then can they hope to survive the cruel season to come.
只有这时 他们才能希望在残酷的季节到来时幸存下来

第六集:
Evolution is an imperfect and often violent process.
进化是一个不完美且常常伴随这个暴力的过程
A battle between what exists and what is yet to be born.
一场已存在的和还未出现事物之间的战斗
In the midst of these birth pains, morality loses its meaning.
在伴随出世的阵痛中 道德失去了意义
The question of good and evil reduced to one simple choice:survive or perish.
正义与邪恶的问题简化为一个选择:生存 还是灭亡

第七集:
They cannot fathom how much you stand to lose in failure.
他们不会明白你会在失败中失去多少东西
But you are the instrument of a flawless design.
但是你是一件没有瑕疵的作品
And all of life may hang in the balance.
世间的一切生命在平衡中命悬一线
A hero learns quickly who can comprehend and who merely stands in your way.
英雄能很快发现谁成为帮手而谁只会碍事

第八集:
The earth is large.
世界之大
Large enough that you think you can hide from anything.
大到你认为你可以躲过任何东西
From fate. From god.
躲过命运 躲过上帝
If only you found a place far enough away.
只要你能找到一个够遥远的地方
So you run.
所以 你逃跑了

You can run far.
你可以逃的很远
You can take your small precautions.
你也可以小心谨慎
But have you really gotten away?
但是你真的能一走了之吗
Can you ever escape?
你逃的掉吗
Or is the truth that you do not have the strength or cunning to hide from destiny.
或者事实是你根本没有力量和才智去逃避命运
But the world is not small, you are.
但是世界并不渺小 而你却是
And fate can find you anywhere.
不管到哪 命运都能找到你

第九集:
We are, if anything, creatures of habit drawn to the safety and comfort of the familiar.
我们 如果有什么不同的话是有习性的动物被所熟悉的事物的安全和舒适所吸引
But what happens when the familiar becomes unsafe,
但如果所熟悉的事物变的不安全了 那会发生什么呢
when the fear that we have been desperately trying to avoid finds us where we live?
当我们一直拼命避免的恐惧找上门来呢 

FMscanner spec

Function:

+fmscan: by default scans from 87.9 to 107.9 MHz in 0.2 MHz increments in v4l, looking for stations that have an average signal strength of 50% or greater.

目前FM收音机的可收频率范围在87.5-108MHz之间,但这不是底线,你可以把他修改为76.0MHz-108MHz,

全球的FM频率范围:
美国和欧洲是87.5MHz~108Mz,日本是76MHz~90MHz等等

美国FM:87.5~107.9MHz 步长 200K,
  AM:520--1720KHz,步长 10K,

+FM立体声音频发射功能,按键选择FM发射频率
两种步进频率50KHZ或100KHZ可绑定选择,频率范围:87.5KHZ~108.5KHZ。
两种频率调整范围选择,包括欧美地区(87.5MHZ——108.5MHZ)和日本地区(76MHZ——96MHZ)。 

This is only really useful if your driver uses VIDEO_TUNER_LOW for 1/16000 MHz increments. 

嵌入式LINUX操作系统的特点

浅谈嵌入式LINUX操作系统的概念和特点  

 
引言 

以应用为中心,以计算机技术为基础,软件、硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗要求严格的专用计算机系统,称为嵌入式系统。一个最小的嵌入式系统的基本组成为:一个用作引导的可用设施(工具);一个具备内存管理,进程管理和定时器服务的LINUX微内核;一个初始进程 硬件的驱动程序;一个或几个应用进程以提供必要的应用功效。

嵌入式LINUX操作系统的特点

•  比较

有人认为LINUX由于太大而不宜用作嵌入式系统,这种观点不正确。面向PC机的LINUX型发布版有很多,功能根本用不上,甚至超出了一个PC用户的需求。因此,对LINUX进行合理的裁减,可以形成一个很具有实用性的嵌入式操作系统。下面对嵌入式LINUX操作系统与专用嵌入式实时操作系统的比 较如下。

•  嵌入式LINUX的内存使用

    在一个简单的系统中,当系统启动后,内核和各种应用进程均驻留在内存中,这是大多数传统嵌入式系统的工作方式,当然也包括LINUX。但它还可以使用另外 一种方式:LINUX有装载和卸载程序的能力,所有应用程序以文件的形式被存放在闪存文件系统中并在必要的时候被装载到内存中,以节省RAM

•  开发嵌入式LINUX的调试方法

当为一个新硬件开发相应的嵌入式LINUX系统时,要用到的典型调试工具的序列和步骤是:

①  修改代码使之能读写串口,并使用gdb运行该程序。这将允许它向另一台正运行着gdb程序的LINUX主机通信gdb通过串口与测试计算机上的gdb目标码会话并给出全部C源码级的调试信息;

②  借助gdb执行余下的,直到LINUX内核开始接管之前的所有硬件和软件的初始化代码;

③  一旦LINUX内核启动后,上述的串口就成为LINUX控制台端口,可以利用它的便利来进行后继开发过程,并可以使用gdb的内核调试版本kgdb

•  嵌入式LINUX的可移植性

LINUX移植到新的微处理器体系非常快捷,一般是将其移植到一种新型的目标板,其中包含有独特的外设。大部分的内核代码都是相同的,因为它们与微处理器无关,所以,移植的工作多集中在一些存储器管理及中断处理程序上。一旦完成,它们将非常稳定。

嵌入式LINUX的应用

嵌入式系统的涵盖面是非常广泛的,其中,家电市场包括机顶盒、数字电视、可视电话、家庭网络等信息家电;工业市场包括工业控制设备、仪器;商用市场包括掌上电脑、瘦客户机、POS终端等;通信市场包括WAP手机、无线PDA等。目前被广泛看好的是信息家电市场,国内有很多开发厂商正加大投入、开发和研制新的产品,嵌入式LINUX将是他们首选的操作系统。

基于Linux的嵌入式操作系统的研究

基于Linux的嵌入式操作系统的研究

引言

嵌入式系统被定义为:以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。嵌入式操作系统是支持嵌入式系统应用的操作系统软件,它是嵌入式系统极为重要的组成部分,通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。与通用操作系统相比较,嵌入式操作系统在系统实时高效性、硬件的依赖性、软件固态化以及应用的专用性等方面具有 较为突出的特点。嵌入式操作系统的出现,将大大提高嵌入式系统开发的效率,改变以往嵌入式软件设计只能针对具体的应用从头做起。在嵌入式操作系统之上开发嵌入系统将减少系统开发的工作量,增强嵌入式应用软件的可移植性,使嵌入式系统的开发方法更具科学性。近年来,随着电子技术的不断进步,嵌入式系统开发己成为热点,而Linux作为一个自由软件,也得到了极大的发展,嵌入式系统与Linux的结合,正日益被人们看好。Linux自身具备一整套工具链,容易 自行建立嵌入式系统的开发环境和交叉运行环境,并且可以跨越嵌入式系统开发中的仿真工具(ICE)的障碍。Linux具有内核小,效率高,源代码开放等优点。强大的网络支持使得可以利用Linux的网络协议栈将其开发成为嵌入式的TCP/IP网络协议栈。

1 系统的组成                                    

一个基本的嵌入式操作系统应包括:

引导程序。能实现系统的快速引导,提供瞬间开机功能。负责将Linux内核加载到内存,并将控制权交给内核初始化程序。具体工作包括:寻找或将指定的内核映像解压,解压文件系统。

②Linux内核。Linux是一个单一内核操作系统,但可以动态装入和卸载内核中的部分源代码,这与传统的单一内核操作系统全部静态编译内核代码是不同的。Linux内核由内存管理、进程管理、定时器中断管理、模块管理、虚拟文件系统、接口文件系统、设备驱动程序、进程间通信、网络管理、系统启动等构成。

初始化进程。系统在刚刚启动时,运行于内核方式,这时候只有一个初始化进程在运行,他首先做系统的初始化,然后执行初始化程序(一般是/sbin/init)。初始化进程是系统的第一个进程,以后所有的进程都是初始化进程的子进程。

硬件驱动程序。设备驱动程序是内核的一部分,它像内核中其它代码一样运行在内核模式。驱动程序如果出错将会使操作系统受到严重破坏,甚至能使系统崩溃并导致文件系统的破坏和数据丢失。Linux设备驱动程序的主要功能有:对设备进行初始化;使设备投入运行和退出服务;从设备接收数据并将它们送回内 核;将数据从内核送到设备;检测和处理设备出现的错误。

提供所需功能的一个或更多应用程序。

2 系统的小型化

Linux的一个通常观点是,它由于太大而不宜用作嵌入式系统,这种观点不一定是真实的。我们可以通过配置内核、裁剪shell和嵌入式c库对系统定制,使整个系统能够存放到容量较小的Flash中。Linux的动态模块加载使Linux的裁剪极为方便,高度模块化的部件使添加非常容易。一般说来,经过适当裁剪后的内核的启动部分的内核代码不到500KB。用户可以把内核和root文件同存放在一张软盘上。

Linux通常的运行环境包括大量的运行时需要的库。这些运行库相互依赖,大小不等。其中最基本的是C语言的运行库glibc。这个库主要完成基本的输入输出,内存访问,文件处理。一个标淮的glibc库大约要1200kB存储空间,考虑到linuxkernel往往小于500kB,这种运行库实在太大。我们做了一些精简的工作。方法无非两种:

1)用静态连接的方法,完全不使用运行库动态连接。

2)对这个库的函数进行了精简。 在一个桌面系统上,使用动态连接可以带来许多好处。使用动态连接库,可以让应用程序跟函数库的更新,升级分离,便于维护,可以让同时运行的多个程序共享一段代码。但是,在嵌入式系统中,很少有多个程序并行的可能,程序的维护,尤其是库函数的维护更新是不常见的。这时,使用静态连接的优势就极为明显。因为静态连接可以只将库中用到的部分连接进程序。在应用程序较少(小于5)的情况下,静态连接可以达到较好的结果。因为C语言运行库是一个最基本的运行库,可以认为是linux运行环境的一部分。为了便于将来扩充的需要,我们也采用第二种方法,针对我们的需要,对库函数的内容进行了一些精简,只保留了一些基本功能。精简后约需要200kB存储空间。但相当多的功能不支持了。

shell作为系统与用户打交道的最简单的方式,虽然它不是系统内核的一部分,但是它调用了内核的大部分功能来执行程序,建立文件。并以并行的方式协调各个程序的运行。可以认为它是linux中最基本也是最重要的一个应用程序。在嵌入式系统中使用μClibcBusyBox的组合,可以有效的减小系统的规模。用μClibc提供的M68K体系的工具来建立一个静态连接μClibc库的BusyBox 的实现的过程大致分为两大块:

1)建立的交叉编译环境。

2)用的交叉编译环境来编译

3 系统移植

Linux的移植。如果Linux不支持选用的平台,就需要把Linux内核中与硬件平台无关的部分改写,使之支持所选用的平台。为提高系统的可移植性,应尽量用可以执行好的高级语言开发系统,少用汇编语言;对不可移植的代码和汇编代码,可以通过宏定义和函数的形式分类集中在某几个特定的文件之中。

系统移植的步骤

1)建立交叉编译环境。这个编译环境就是指编译内核所需的工具ld,as,ar,ranlib,gcc以及相关的库文件。

2)内核移植。当交叉编译环境建好后,就可以用它来编译相关体系的内核了。要编译特定体系的内核,需要修改linux/目录下的Makefile文件。

4 嵌入式Linu操作系统的开发难点:

可定制的嵌入操作系统提供了高度模块化的构件方法。嵌入式操作系统也常常要求通用的功能,为了避免重复劳动,这些功能的实现运用了许多现成的程序和驱动程序,它们可以用于公共外设和应用。 然而,因为还在起步阶段,目前的嵌入式Linux版本还不是一套非常简洁的系统。如何优化系统至适合嵌入式应用成为最主要的目标。

许多Linux的应用程序都要用到虚拟内存,在许多嵌入式操作系统中,是没有价值的,所以不要以为一个没有磁盘的嵌入操作式系统可以运行任何Linux应用程序。

内核调试工具都不怎么好,特别是在较底层的。kgdb可以使错误定位非常容易,你只要重新启动。不幸的是,打印语句更麻烦。

④Linux非常的灵活。嵌入式系统总的来说却不灵活;而且它们完全是为最有效实现预定功能而严格设计的。现在的趋势是保持灵活性、保持总体目标功能、尽量少做修改。这个目标是崇高的,但是,所付出的代价将是针对具体的工作做出巨大的调整。

5 结束语

开发中国自主产权的嵌人式处理器和嵌人式操作系统,有十分重要的战略意义。由于Linux具有免费、源代码开放、支持多种CPU等优点,使用Liux作为底层操作系统,对它进行裁减和定制,并在其基础搭建嵌入式系统平台,成为日益流行的嵌入式操作系统的解决方案。