2009年11月25日星期三

在Ubuntu 8.04上加装iptables和fail2ban提高安全性

1. 安装iptables


1)apt-get install iptables

因为iptable不需要启动脚本,规则一旦设置,立即生效,关机后有自动清零。所以远程登录时,更改设置要小心,切勿将默认值全都改为Drop,以免丢失SSH连接。编写以下脚本可以便于修改,调试。

2)然后可以在用户目录下编写如下脚本 ~/iptables-init.sh (假设服务器对外网卡的设备号是eth0


iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT #保证已经打开的Session都有效,对于远程调试登录的情况下起保护作用,因为iptables的改动是实时生效的
iptables -A INPUT -i lo -j ACCEPT #打开Loopback, 及localhost, 127.0.0.1
iptables -A INPUT -p tcp -i eth0 –dport ssh -j ACCEPT #允许SSH远程登录
iptables -A INPUT -p tcp -i eth0 –dport 80 -j ACCEPT #允许外界访问www服务器
iptables -A INPUT -p tcp -i eth0 –dport 21 -j ACCEPT #允许外界访问ftp服务器
iptables -A INPUT -j DROP
iptables-save > /etc/iptables.rules

然后赋予脚本执行权限 chmod +x ./iptables-init.sh
运行脚本 ./iptables-init.sh

3)设置网卡启动时加载防火墙规则 (这步要很小心,否则网卡加载失败,系统就无法登录了)

最好先用
iptables-restore </etc/iptables.rules
iptables -L -v 仔细检查下数据,必要时,重新开一个putty窗口,验证以下是否还能登录。
然后修改脚本/etc/network/interfaces,使系统能自动应用这些规则,最后一行就是要添加的,加载文件应该和上面脚本中保存规则的文件名一致,并且要用绝对路径。
auto eth0
iface eth0 inet dhcp
pre-up iptables-restore < /etc/iptables.rules

注意:之所以在加载网卡设备后,刷新iptables列表,
而不是象有些地方建议的在/etc/rc.local或是其他地方放置iptables-init这样的脚本,是因为自网卡启动后到系统执行rc.local仍然有一段时间,会使防火墙无效,所以以上的方法是最好的。

本来为了是FTP能够支持PASV模式,方便防火墙后面的客户端连接服务器,可以在何时的启动脚本里执行
modprobe ip_conntrack_ftp
但是Linnode上的Ubuntu内核编译时,并没有带上这个模块,所以只得放弃,好在PASV模式的安全性也不如Active模式(Port模式)
参考文章
1. Ubuntu 服务器版 Iptables 基本设置指南

2. 安装fail2ban


1) apt-get install fail2ban

2) 查看/etc/fail2ban/jail.conf,核对一下logpath = /var/log/auth.log或/var/log/vsftpd.log的路径是否正确。然后编辑/etc/fail2ban /jail.local, 打开以下开关: (这样可以避免升级时,开关被关闭)

[DEFAULT]
bantime=7200 #至少封2小时IP
[ssh]
enabled = true
filter = sshd
[vsftpd]
enabled = true
filter = vsftpd

查看/etc/vsftpd.conf, 确保以下配置正确,如果修改了,需要重启ftp服务,/etc/init.d/vsftpd restart。fail2ban虽然也可以和Wu-FTP配合,然考虑到思维一致性,我们上边只配了vsftpd的过滤,只能识别vsftpd的日志, 所以vsftpd的日志也要采取其自身的格式:

xferlog_enable=YES
vsftpd_log_file=/var/log/vsftpd.log

确保以下两行被注释掉,否则log的格式是wu-ftpd 不能被fail2ban识别!!
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES

然后/etc/init.d/fail2ban start 启动服务就可以了。
fail2ban每次都会在iptables的INPUT Chain中添加一条记录,专门指向fail2ban的一条Chain, 用来存放封禁ip的记录。 所以/etc/iptables.rules只要独自管理静态规则就可以了

3. FTP客户端的设置


FTP的客户端要复杂一些,因为PORT模式下需要客户端来告诉FTP服务器自己的公网IP,如果用户自己也在防火墙后面的局域网里,一般的客户端 是做不到的。很有可能会告诉FTP服务器,Port 192.168.0.x 这样的指令。结果得到550 illegal port command的信息。但是FileZilla最新版可以选择利用http://ip.filezilla-project.org/ip.php获知 IP,这个问题就迎刃而解了

4. 查看被封禁的IP


fail2ban-client status ssh -iptables
fail2ban-client status vsftpd  -iptables

Windows mobile 一些常用设置

2008-11-06 15:24


1.来电铃声
铃声放在windows下的rings目录下面,或者在储存卡里建立一个My Documents(注意大小写)把mp3铃声放里面就好了来电铃声支持的格式有mp3 wmv

2.短信铃声
短信的直接放在机器里的Windows下就可以了,支持wav格式

3.WM5 解决死屏、电池大量消耗的解決方法
WM5 解决死屏、电池大量消耗完全是因为机器內置的Activesync造成的。因为微软公司在设计ActiveSync的时候,有一个非常愚蠢的想法,就是 ActiveSync, 不管你的PDA是否在联机,总是自动启动,去寻找需要同步的对象。而且手动关闭 ActiveSync,它在5分钟后又会重新启动﹗
我们通过设置可解决此问题︰
1、 开启PDA
2、 进入开始 > 程序 > Activesync. 打开Activesync。
3、 点击屏幕最右下角的菜单。注意,在设置这个菜单中, 日程安排不能更改的 。而这一选项,正是   问题所在。

现在,骗过ActiveSync,来更改日程安排。

1、在Activesync的菜单里点击添加源服务器。
2、在下面的项目中,可以填入任何东东。服务器地址、用户名、密码、域均任意 添,下一步后选择要同步的数据全部去掉∨
3、现在已添加了一个所谓的“交换服务器”。 现在Activesync的主屏幕上可以看 到一个新的连接, Exchange 服务器
4、在Activesync的主屏幕上点击“菜单”,可以看到日程安排的选项可以点击了 ﹗
5、如果你用的是A01系统,看到的高峰时间是每5分钟,A06系统的是每10分钟。 这就是问题所在﹗
6、把高峰时间和非高峰时间都改为手动.
7、点击OK。
8、现在我们可将Exchange 服务器删掉。回到Activesync主屏幕点菜单>选项>删 除Exchange 服务器>选是。(结束)

4.重启和硬起
重启:就是手机系统重新启动,按住电源按键(储存卡旁边的)5秒,选择“是”然后再按电源键。
硬起:指手机恢复到出厂设置,只要是手机上的,原来安装的软件和 手机里的联系人等,就统统不见了。效果和恢复出厂设置是一样的,只是一个是硬操作,一个是软操作,当不能正常进入手机系统时,我们的一般做法,就是硬起。 左边录音键+右边语音命令键+中间确认键+重起RESET键(按一下便松开),此动作持续30秒以上,屏幕出现确认窗口后,按后按send拨号键 。如能进入系统,开始-设置-系统-清除内存,即可。

5.注册表修改
可用软件“注册表编辑器”来操作   修改后重启方能生效!

1、改变标题栏时间显示信息(格式):
HKEY_LOCAL_MACHINE\Software\Microsoft\Shell   下新建DWORD值,名字为TBOpt,
=0时不显示任何日期时间信息;
=1时仅显示时间;
=2时仅显示日期;
=3时同时显示日期和时间,如截图。

2、去掉初次运行程序时的安全警告:
HKEY_LOCAL_MACHINE\Security\Policies\Policies\0000101a
= 1时不显示警告信息;
=0时恢复显示。

3、改变屏幕最下面那两个触摸软键的功能:
左键:HKEY_CURRENT_USER\Software\Microsoft\Today\Keys\112\Open ="\Windows\Calendar.exe"(功能)
default="日历"(显示文本信息)
右键:HKEY_CURRENT_USER\Software\Microsoft\Today\Keys\113\Open = "\Windows\“开始”菜单\Programs\Contacts.lnk"
default="联系人"(显示文本信息)

4、给程序指定GPS端口设置:
修改后重启,会在设置/连接里面增加GPS设置选项,如截图
增加字键及值:HKEY_LOCAL_MACHINE\ControlPanel\GPS Settings\Group = 2   字键类型:DWORD
删除或改名:HKEY_LOCAL_MACHINE\ControlPanel\GPS Settings\redirect

5、如果你连接的GPRS网络支持EDGE,那么标题栏栏上会显示“E”代替原来的“G”,此项改动不影响实际连接的GPRS网络类型,只是告诉你所连接的网络是普通的GPRS还是EDEG而已。(EDGE也称2.75G,比普通GPRS更快)同6,参看下面截图
HKEY_LOCAL_MACHINE\Drivers\BuiltIn\RIL\EnableDifferGprsEdgeIcon
= 1 为根据实际显示;
=0 为一律显示为“G”

6、GPRS连接以后,点击标题栏连接图标“G”或“E”出现的提示框中增加“断开”按钮和实际累计连接时间信息
HKEY_LOCAL_MACHINE\ControlPanel\Phone\Flags2
= 16增加“断开”按钮和累计连接时间显示(16为16进制值);
=0两者都不显示;
=8为增加“断开”按钮

7、改变日期时间显示格式,如截图,不过这样改了,其它应用软件的短日期格式如Resco explorer显示文件信息时也会跟着改变。
HKEY_LOCAL_MACHINE\nls\overrides\SSDte
=ddd/d   为星期/日期

8、修改铃声路径
HKEY_CURRENT_USER\ControlPanel\SoundCategories\Ring\Directory = \Storage Card\Mymusic
不赞成改在卡上。尽量放在机子上。

9、CAB格式安装文件安装了以后避免被系统自动删除的又2个方法:
HKEY_LOCAL_MACHINE\Software\apps\Microsoft Application Installer\nDynamicDelete
= 0 不自动删除;
= 2 默认自动删除

HKEY_CLASSES_ROOT\cabfile\Shell\open\command
=wceload.exe "%1" /nodelete 不自动删除;
=wceload.exe "%1" 默认自动删除

10、重复安装应用程序时是否提示重新覆盖安装:
HKEY_LOCAL_MACHINE\Software\apps\Microsoft Application Installer\fAskOptions
= 1 提示;
= 0 不提示

11、在桌面“今日”中增加无线网卡(WiFi)设置快捷方式,就象蓝牙快捷方式一样,仅仅适用于有WiFi的838、830等机子,效果待评估。不过已验证过,Windows下有netui.dll文件
HKEY_LOCAL_MACHINE\Software\Microsoft\Today\Items\"Wireless"
DLL=netui.dll
Order=0
Enabled=1
Type=4
Options=1

12、同步联机时取消边联机边充电充电
HKEY_LOCAL_MACHINE\Drivers\BuiltIn\usbfndrv\EnableUsbCharging
= 1充电;
= 0不充电

13、开机后是否保持GPRS连接状态:
HKEY_LOCAL_MACHINE\Comm\ConnMgr\Providers\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\Connections\|connection name|\AlwaysOn
= 1 总是连接;
=0 开机不自动连接
connection name是指手机上具体设定的连接名称,如中国移动CMWAP,根据实际情况不同而不同;而且会把所有连接都显示出来,可以删除不用的连接,等同于在设置面板上设定或删除。

14、屏蔽设置中“清除内存”等危险选项方法
WM5.0的“清除内存”其实就是硬启动,不用说,很危险,尤其是你的朋友好奇借你的手机来玩的时候。。。。。
HKEY_LOCAL_MACHINE\ControlPanel\
这 下面的大多是手机设置里面的选项,大多数选项下都有一个字键:Group,当它等于0时,出现在“个人”栏里;等于1时出现在“系统”栏里;等于2时出现 在“连接”栏里;大于2时,就哪里都不出现!所以修改它比直接删除对应的CPL文件要好得多--哪天要用把它改过来就行了!所以,要屏蔽“清除内存”,就 这样改好了:
HKEY_LOCAL_MACHINE\ControlPanel\Clear Storage\Group
=3

15,838改回水货键盘YZ位置及标点符号方法
HKEY_CURRENT_USER\ControlPanel\Keybd,新建字符串"Locale",键值为"0407",软启后即可.如遇只能改YZ键位置而标点符号仍未改回的请再进入注册表,查询
新建字符串"Locale"键值是否为"0407",如为"0804"请改为"0407",软启后可成功改回.

16,让联系人中不显示sim联系人的方法
在wm5系统下,联系人里面总是显示sim联系人,导致联系人重复,用修改注册表的方法可以解决
打开注册表 : HKCU\ControlPanel\Phone
新建双字节值   键名   ShowSim   键值   DWORD:0     (10进制) (1 为显示sim联系人)
保存即可(也许有的机器要重启)

6.WM5系统下的文件夹骨架
Windows Mobile 5.0和微软的Windows 系统一脉相承,自然有自己严谨的文件系统,通过自带的File Manager可以自由访问存储的档。那么我们也就来认识一下文件系统的骨架。

\Storage\Program Files  程序文件夹
\windows\      手机系统文件夹
\Storage\Application Data\Home  桌面主题文件夹
\Storage\Application Data\Sounds 来电铃声活页夹
\Storage\Application Data\phonering 短信声音文件夹
\Storage\My Documents\Mobiclip     FLASH动画活页夹
\Storage\My Documents\MovieAlbum   手机录像文件夹
\Storage\My Documents\Notes     手机录音活页夹(在 WINDOWS 下打开隐藏选项就可看到)
\Storage\My Documents\PhotoAlbum  手机所拍照片活页夹
\Storage\windows\AppMgr       临时存档档夹
\Storage\windows\AppMgr\instal    下载到手机但没安装的档夹。平时没空间了大多是这里有档没安装,删掉或安装掉即可
\Storage\windows\Frames  相片外框活页夹
\Storage\windows\PhotoID  来电相片外框活页夹
\Storage\windows\Favorites  IE收藏夹
\Storage\windows\Start Menu  开始快捷方式存放档夹
\Storage\windows\Start\startup  开机自动运行的程序文件夹   [CapNotify.Init_tray.MemoryShow.poutlook.WiFiInit]
\Storage\windows\Start Menu\Accessories 手机开始菜单里的附件文件夹
\Storage\windows\Start Menu\Games  手机开始菜单里的游戏文件夹

[软件心得] [HTC TyTN II/Kaiser/P4550/O2 XDA Stella] Kaiser经验集中贴

一、基础知识

1、硬件规格

http://ping.pdafans.com/story.php?product_id=504&stime=1233504000&etime=1233590399

2、产品手册

Kaiser使用入门手册:

Kaiser使用手册:

3、硬启动方法

4、购买咨询:
http://bbs.pdafans.com/forum-201-1.html

二、疑难经验

发个kaiser等机型WM6.1下能用的TCPMP V0.72RC1简体中文绿色版,集成FLV插件0.43。       2009-1-12 21:46
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser Wm6.1上能用的强大短信《手机密使》推出了,无法在WM6上使用的同学有喜了         2008-9-28 20:50
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

美版TytnII Kaiser 凯撒 Tilt 键盘错位完美解决补丁           2008-9-5 22:44
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

[我分享]以我的Kaiser为例 100%解决samsung omnia 侧插件不显示不运行的问题          2008-8-28 02:18
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒ROM制作教程~!让人人都拥有自己的ROM             2008-8-26 00:43
http://bbs.pdafans.com/viewthrea ... hlight=%E2%FD%C8%F6

恺撒网络锁详细解锁教程          2008-4-12 13:23
http://bbs.pdafans.com/viewthrea ... hlight=%E2%FD%C8%F6

搞定KAISER 蓝牙语音拨号,带程序和教程(申精)         2008-3-2 23:59
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

HTC TyTN II Kaiser(恺撒)刷机/软件/游戏 集中贴          2008-2-27 12:32
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

发个原创:我内置到HTC Kaiser ROM里面的开机设置工具          2008-2-27 02:27 |
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser/TYTN II/T MDA 输入法的问题 (已经解决了)       2007-12-14 14:02
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser (TyTN II) 资源汇总贴 !! Radio 更新至1.71.09.01         2007-10-7 13:12
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

三、评价感受

三星i900 开箱 屏幕简测 diamond比较测试(转)24 楼和HTC Kaiser的对比 相机静音补丁    2008-9-24 03:19
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

我的『HTC TYTN 』+『HTC Kaiser』女生桌面成长日记 — 可以实用 | 才可以可爱         2008-8-13 08:27
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser QSKOM 6.0非专业测评~                  2008-6-4 23:19
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser实测参考~不含任何劝败或不劝败因素~           2008-5-24 16:27
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒 TyTN II kaiser P4550 入手作业,超详细。。。。           2008-5-6 20:09
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

机型比较--HTC TyTN II (Kaiser) 对比 O2 Atom Life -- By Nick Sun         2007-12-7 20:55
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

四、ROM相关

注意:刷机有风险,动手需谨慎;这里列出的链接并不表明推荐或者经过试验确认没有风险;请刷机前三思,一切后果自负!

更新!Kaiser_Build 21109刷机ROM双版本(1.95 / 3.57驱动,GPS定位超快)           2009-1-11 00:05
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

发布P4550凯撒RUU_kaiser_XV360 1.0版ROM修正(增纯净版)               2009-1-3 02:02
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

KAISER用21109元旦版模版双版本(1.65和1.27Radio),要的快进!          2009-1-3 00:03
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

发布Kaiser 21109 相对纯净版1.65以上radio用                     2009-1-2 23:44
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒_拖六_20954_20954_M2D雅黑(20081231晚)^_^        2008-12-31 23:59
http://bbs.pdafans.com/viewthrea ... hlight=%E2%FD%C8%F6

99kaiser v2 21109 Build 21109 AKU5.0.0元旦好礼不断啊          2008-12-31 09:03
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒_拖五_20924_20924_M2D雅黑+无马宋体+模版(20081225傍晚)^_^           2008-12-23 00:55
http://bbs.pdafans.com/viewthrea ... hlight=%E2%FD%C8%F6

(转自52dopod12-16RUU_Kaiser_Tinni_CHS_20755最终修改版(D3D+横屏ClearType)          2008-12-19 20:54
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

发布本人制作的kaiser20931适度集成版rom(2008.12.06发布20931第二版)         2008-11-22 22:02
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒20931_20931_M2D雅黑+HTChome宋体光秃秃_拖拉机综四(20081130晚上)^_^           2008-11-14 11:46
http://bbs.pdafans.com/viewthrea ... hlight=%E2%FD%C8%F6

个人感觉KAISER最稳定最快的ROM                  2008-10-18 14:26
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒Kaiser_20721_20721_拖拉机综三(雅黑带梅花+宋体无梅花)(0903下午)^_^           2008-8-30 22:59
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

(恺撒 kaiser/TyTN II) kaiser_20273.1.3.3_CHS解决已知问题2008.08.22凌晨^_^|||         2008-8-21 23:22
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒Kaiser(TyTN II) ROM_WM6.1_20270_20273_CHS_拖拉机综二(20080822凌晨)^_^       2008-8-18 00:04
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

恺撒Kaiser(TyTN II) ROM_WM6.1_19214_20270_CHS_拖拉机综一(20080725凌晨)^_^         2008-7-25 12:09
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser HardSPL 3.28 『含新版刷新及降回 HardSPL 1.0 教程』       2008-6-3 10:34
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

HTC Kaiser 6.1 19212 官方 2008.05.23 开放 ROM 下载 『全新驱动』          2008-5-22 11:03
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

HTC KAISER - PDAVIET ROM WM6.1 (Build 19701.1.1.0){5月14日更新宋体修改版}           2008-5-7 12:31
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

DFT QooQoo Kaiser CHS 19400.1.0.0简体中文ROM DFT发布              2008-4-23 18:14
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

基于Kaiser_3.08.161_build19199官方原版简体中文修改(4月30日更新宋体版)        2008-4-2 09:19
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

HTC TyTN II ,Kaiser 简体中文ROM18538.0.7.0 QSKOM 2.4           2008-1-18 22:41
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

[QSKOM]kaiser简体中文rom,官方18128内核           2007-11-12 04:03
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

迎接kaiser刷机时代的到来          2007-10-7 03:08
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Kaiser 官方正式发布!!!Hermes 的升级版!!!官方说明书下载!!!           2007-8-29 09:23
http://bbs.pdafans.com/viewthrea ... mp;highlight=Kaiser

Manual dla 7z

P7ZIP(1) P7ZIP(1)

NAME
7-Zip - A file archiver with highest compression ratio

SYNOPSIS
7z [adeltux] [-] [SWITCH] <<ARCHIVE_NAME>> <<ARGUMENTS>>......

DESCRIPTION
7-Zip is a file archiver with the highest compression ratio. The pro-
gram supports 7z (that implements LZMA compression algorithm), ZIP,
CAB, ARJ, GZIP, BZIP2, TAR, CPIO, RPM and DEB formats. Compression
ratio in the new 7z format is 30-50% better than ratio in ZIP format.

7z uses plugins to handle archives.

FUNCTION LETTERS
a Add

d Delete

e Extract

l List

t Test

u Update

x eXtract with full paths

SWITCHES
-ai[r[-||0]]{{@@listfile||!!wildcard}
Include archives

-ax[r[-||0]]{{@@listfile||!!wildcard}
eXclude archives

-bd Disable percentage indicator

-i[r[-||0]]{{@@listfile||!!wildcard}
Include filenames

-l don't store symlinks; store the files/directories they point to
(CAUTION : the scanning stage can never end because of recursive
symlinks like 'ln -s .. ldir')

-m{{Parameters}
Set Compression Method

-o{{Directory}
Set Output directory

-p{{Password}
Set Password

-r[-||0]
Recurse subdirectories (CAUTION: this flag does not do what you
think, avoid using it)

-sfx[{{name}]
Create SFX archive

-si Read data from StdIn (eg: tar cf - directory | 7z a -si direc-
tory.tar.7z)

-so Write data to StdOut (eg: 7z x -so directory.tar.7z | tar xf -)

-slt Sets technical mode for l (list) command

-t{{Type}
Type of archive

-v{{Size}[b||k||m||g]
Create volumes

-u[-][p##][q##][r##][x##][y##][z##][!!newArchiveName]
Update options

-w[path]
Set Working directory

-x[r[-||0]]]{{@@listfile||!!wildcard}
Exclude filenames

-y Assume Yes on all queries

Backup and limitations
DO NOT USE the 7-zip format for backup purpose on Linux/Unix because :
- 7-zip does not store the owner/group of the file.

On Linux/Unix, in order to backup directories you must use tar :
- to backup a directory : tar cf - directory | 7za a -si direc-
tory.tar.7z
- to restore your backup : 7za x -so directory.tar.7z | tar xf -

If you want to send files and directories (not the owner of file) to
others Unix/MacOS/Windows users, you can use the 7-zip format.

example : 7za a directory.7z directory

Do not use "-r" because this flag does not do what you think.

Do not use directory/* because of ".*" files (example : "directory/*"
does not match "directory/.profile")

EXAMPLE 1
7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on archive..7z dir1
adds all files from directory "dir1" to archive archive.7z using
"ultra settings"

-t7z 7z archive

-m0=lzma
lzma method

-mx=9 level of compression = 9 (Ultra)

-mfb=64
number of fast bytes for LZMA = 64

-md=32m
dictionary size = 32 megabytes

-ms=on solid archive = on

EXAMPLE 2
7z a -sfx archive..exe dir1
add all files from directory "dir1" to SFX archive archive.exe
(Remark : SFX archive MUST end with ".exe")

MORE EXAMPLES
You will find more examples in /usr/share/doc/p7zip/DOCS/MANUAL.

SEE ALSO
7za(1) 7zr(1)

AUTHOR
Written for Debian by Mohammed Adnene Trojette.

Mohammed Adnene Trojette October 31 2004 P7ZIP(1)

http://manual.aun.pl/7z.html

File manipulation



This is a guide to basic file manipulation in OCaml using only what the standard library provides.

Official documentation for the modules of interest: Pervasives, Printf.

The standard library doesn't provide functions that directly read a file into a string or save a string into a file. Such functions can be found in third-party libraries such as Extlib. See Std.input_file and Std.output_file.


Buffered channels


The normal way of opening a file in OCaml returns a channel. There are two kinds of channels:

  • channels that write to a file: type out_channel

  • channels that read from a file: type in_channel


Writing


For writing into a file, you would do this:

  1. Open the file to obtain an out_channel

  2. Write stuff to the channel

  3. If you want to force writing to the physical device, you must flush the channel, otherwise writing will not take place immediately.

  4. When you are done, you can close the channel. This flushes the channel automatically.


Commonly used functions: open_out, open_out_bin, flush, close_out, close_out_noerr

Standard out_channels: stdout, stderr

Reading


For reading data from a file you would do this:

  1. Open the file to obtain an in_channel

  2. Read characters from the channel. Reading consumes the channel, so if you read a character, the channel will point to the next character in the file.

  3. When there are no more characters to read, the End_of_file exception is raised. Often, this is where you want to close the channel.


Commonly used functions: open_in, open_in_bin, close_in, close_in_noerr

Standard in_channel: stdin

Seeking


Whenever you write or read something to or from a channel, the current position changes to the next character after what you just wrote or read. Occasionally, you may want to skip to a particular position in the file, or restart reading from the beginning. This is possible for channels that point to regular files, use seek_in or seek_out.

Gotchas



  • Don't forget to flush your out_channels if you want to actually write something. This is particularly important if you are writing to non-files such as the standard output (stdout) or a socket.

  • Don't forget to close any unused channel, because operating systems have a limit on the number of files that can be opened simultaneously. You must catch any exception that would occur during the file manipulation, close the corresponding channel, and re-raise the exception.

  • The Unix module provides access to non-buffered file descriptors among other things. It provides standard file descriptors that have the same name as the corresponding standard channels: stdin, stdout and stderr. Therefore if you do open Unix, you may get type errors. If you want to be sure that you are using the stdout channel and not the stdout file descriptor, you can prepend it with the module name where it comes from: Pervasives.stdout. Note that most things that don't seem to belong to any module actually belong to the Pervasives module, which is automatically opened.

  • open_out and open_out_bin truncate the given file if it already exists! Use open_out_gen if you want an alternate behavior.


Example




open Printf

let file = "example.dat"
let message = "Hello!"

let _ =

(* Write message to file *)
let oc = open_out file in (* create or truncate file, return channel *)
fprintf oc "%s\n" message; (* write something *)
close_out oc; (* flush and close the channel *)

(* Read file and display the first line *)
let ic = open_in file in
try
let line = input_line ic in (* read line from in_channel and discard \n *)
print_endline line; (* write the result to stdout *)
flush stdout; (* write on the underlying device now *)
close_in ic (* close the input channel *)

with e -> (* some unexpected exception occurs *)
close_in_noerr ic; (* emergency closing *)
raise e (* exit with error: files are closed but
channels are not flushed *)

(* normal exit: all channels are flushed and closed *)


HOWTO do Linux kernel development

Everything you ever wanted to know about Linux kernel proceedures.

This is the be-all, end-all document on this topic. It contains instructions on how to become a Linux kernel developer and how to learn to work with the Linux kernel development community. It tries to not contain anything related to the technical aspects of kernel programming, but will help point you in the right direction for that.

If anything in this document becomes out of date, please send in patches to the maintainer of this file, who is listed at the bottom of the document.

Introduction


So, you want to learn how to become a Linux kernel developer? Or you have been told by your manager, "Go write a Linux driver for this device." This document's goal is to teach you everything you need to know to achieve this by describing the process you need to go through, and hints on how to work with the community. It will also try to explain some of the reasons why the community works like it does.

The kernel is written mostly in C, with some architecture-dependent parts written in assembly. A good understanding of C is required for kernel development. Assembly (any architecture) is not required unless you plan to do low-level development for that architecture. Though they are not a good substitute for a solid C education and/or years of experience, the following books are good for, if anything, reference:

  • "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]

  • "Practical C Programming" by Steve Oualline [O'Reilly]


The kernel is written using GNU C and the GNU toolchain. While it adheres to the ISO C89 standard, it uses a number of extensions that are not featured in the standard. The kernel is a freestanding C environment, with no reliance on the standard C library, so some portions of the C standard are not supported. Arbitrary long long divisions and floating point are not allowed. It can sometimes be difficult to understand the assumptions the kernel has on the toolchain and the extensions that it uses, and unfortunately there is no definitive reference for them. Please check the gcc info pages (info gcc) for some information on them.

Please remember that you are trying to learn how to work with the existing development community. It is a diverse group of people, with high standards for coding, style and procedure. These standards have been created over time based on what they have found to work best for such a large and geographically dispersed team. Try to learn as much as possible about these standards ahead of time, as they are well documented; do not expect people to adapt to you or your company's way of doing things.

Legal Issues


The Linux kernel source code is released under the GPL. Please see the file, COPYING, in the main directory of the source tree, for details on the license. If you have further questions about the license, please contact a lawyer, and do not ask on the Linux kernel mailing list. The people on the mailing lists are not lawyers, and you should not rely on their statements on legal matters.

For common questions and answers about the GPL, please see: http://www.gnu.org/licenses/gpl-faq.html

Documentation


The Linux kernel source tree has a large range of documents that are invaluable for learning how to interact with the kernel community. When new features are added to the kernel, it is recommended that new documentation files are also added which explain how to use the feature. When a kernel change causes the interface that the kernel exposes to userspace to change, it is recommended that you send the information or a patch to the manual pages explaining the change to the manual pages maintainer at [email protected]

Here is a list of files that are in the kernel source tree that are required reading:


  • README

    This file gives a short background on the Linux kernel and describes what is necessary to do to configure and build the kernel. People who are new to the kernel should start here.



  • Documentation/Changes

    This file gives a list of the minimum levels of various software packages that are necessary to build and run the kernel successfully.



  • Documentation/CodingStyle

    This describes the Linux kernel coding style, and some of the rationale behind it. All new code is expected to follow the guidelines in this document. Most maintainers will only accept patches if these rules are followed, and many people will only review code if it is in the proper style.



  • Documentation/SubmittingPatches



  • Documentation/SubmittingDrivers

    These files describe in explicit detail how to successfully create and send a patch, including (but not limited to):

    • Email contents

    • Email format

    • Who to send it to


    Following these rules will not guarantee success (as all patches are subject to scrutiny for content and style), but not following them will almost always prevent it.

    Other excellent descriptions of how to create patches properly are:




  • Documentation/stable_api_nonsense.txt

    This file describes the rationale behind the conscious decision to not have a stable API within the kernel, including things like:

    • Subsystem shim-layers (for compatibility?)

    • Driver portability between Operating Systems.

    • Mitigating rapid change within the kernel source tree (or preventing rapid change)


    This document is crucial for understanding the Linux development philosophy and is very important for people moving to Linux from development on other Operating Systems.



  • Documentation/SecurityBugs

    If you feel you have found a security problem in the Linux kernel, please follow the steps in this document to help notify the kernel developers, and help solve the issue.



  • Documentation/ManagementStyle

    This document describes how Linux kernel maintainers operate and the shared ethos behind their methodologies. This is important reading for anyone new to kernel development (or anyone simply curious about it), as it resolves a lot of common misconceptions and confusion about the unique behavior of kernel maintainers.



  • Documentation/stable_kernel_rules.txt

    This file describes the rules on how the stable kernel releases happen, and what to do if you want to get a change into one of these releases.



  • Documentation/kernel-docs.txt

    A list of external documentation that pertains to kernel development. Please consult this list if you do not find what you are looking for within the in-kernel documentation.



  • Documentation/applying-patches.txt

    A good introduction describing exactly what a patch is and how to apply it to the different development branches of the kernel.



The kernel also has a large number of documents that can be automatically generated from the source code itself. This includes a full description of the in-kernel API, and rules on how to handle locking properly. The documents will be created in the Documentation/DocBook/ directory and can be generated as PDF, Postscript, HTML, and man pages by running:
make pdfdocs
make psdocs
make htmldocs
make mandocs

respectively from the main kernel source directory.

Becoming A Kernel Developer


If you do not know anything about Linux kernel development, you should look at the Linux KernelNewbies project: http://kernelnewbies.org It consists of a helpful mailing list where you can ask almost any type of basic kernel development question (make sure to search the archives first, before asking something that has already been answered in the past.) It also has an IRC channel that you can use to ask questions in real-time, and a lot of helpful documentation that is useful for learning about Linux kernel development.

The website has basic information about code organization, subsystems, and current projects (both in-tree and out-of-tree). It also describes some basic logistical information, like how to compile a kernel and apply a patch.

If you do not know where you want to start, but you want to look for some task to start doing to join into the kernel development community, go to the Linux Kernel Janitor's project: http://janitor.kernelnewbies.org/ It is a great place to start. It describes a list of relatively simple problems that need to be cleaned up and fixed within the Linux kernel source tree. Working with the developers in charge of this project, you will learn the basics of getting your patch into the Linux kernel tree, and possibly be pointed in the direction of what to go work on next, if you do not already have an idea.

If you already have a chunk of code that you want to put into the kernel tree, but need some help getting it in the proper form, the kernel-mentors project was created to help you out with this. It is a mailing list, and can be found at: http://selenic.com/mailman/listinfo/kernel-mentors

Before making any actual modifications to the Linux kernel code, it is imperative to understand how the code in question works. For this purpose, nothing is better than reading through it directly (most tricky bits are commented well), perhaps even with the help of specialized tools. One such tool that is particularly recommended is the Linux Cross-Reference project, which is able to present source code in a self-referential, indexed webpage format. An excellent up-to-date repository of the kernel code may be found at: http://sosdg.org/~coywolf/lxr/

The development process


Linux kernel development process currently consists of a few different main kernel "branches" and lots of different subsystem-specific kernel branches. These different branches are:

  • main 2.6.x kernel tree

  • 2.6.x.y -stable kernel tree

  • 2.6.x -git kernel patches

  • 2.6.x -mm kernel patches

  • subsystem specific kernel trees and patches


2.6.x kernel tree


2.6.x kernels are maintained by Linus Torvalds, and can be found on kernel.org in the pub/linux/kernel/v2.6/ directory. Its development process is as follows:

  • As soon as a new kernel is released a two weeks window is open, during this period of time maintainers can submit big diffs to Linus, usually the patches that have already been included in the -mm kernel for a few weeks. The preferred way to submit big changes is using git (the kernel's source management tool, more information can be found at http://git.or.cz/) but plain patches are also just fine.

  • After two weeks a -rc1 kernel is released it is now possible to push only patches that do not include new features that could affect the stability of the whole kernel. Please note that a whole new driver (or filesystem) might be accepted after -rc1 because there is no risk of causing regressions with such a change as long as the change is self-contained and does not affect areas outside of the code that is being added. git can be used to send patches to Linus after -rc1 is released, but the patches need to also be sent to a public mailing list for review.

  • A new -rc is released whenever Linus deems the current git tree to be in a reasonably sane state adequate for testing. The goal is to release a new -rc kernel every week.

  • Process continues until the kernel is considered "ready", the process should last around 6 weeks.


It is worth mentioning what Andrew Morton wrote on the linux-kernel mailing list about kernel releases:
"Nobody knows when a kernel will be released, because it's released according to perceived bug status, not according to a preconceived timeline."

2.6.x.y -stable kernel tree


Kernels with 4 digit versions are -stable kernels. They contain relatively small and critical fixes for security problems or significant regressions discovered in a given 2.6.x kernel.

This is the recommended branch for users who want the most recent stable kernel and are not interested in helping test development/experimental versions.

If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is the current stable kernel.

2.6.x.y are maintained by the "stable" team [email protected], and are released almost every other week.

The file Documentation/stablekernelrules.txt in the kernel tree documents what kinds of changes are acceptable for the -stable tree, and how the release process works.

2.6.x -git patches


These are daily snapshots of Linus' kernel tree which are managed in a git repository (hence the name.) These patches are usually released daily and represent the current state of Linus' tree. They are more experimental than -rc kernels since they are generated automatically without even a cursory glance to see if they are sane.

2.6.x -mm kernel patches


These are experimental kernel patches released by Andrew Morton. Andrew takes all of the different subsystem kernel trees and patches and mushes them together, along with a lot of patches that have been plucked from the linux-kernel mailing list. This tree serves as a proving ground for new features and patches. Once a patch has proved its worth in -mm for a while Andrew or the subsystem maintainer pushes it on to Linus for inclusion in mainline.

It is heavily encouraged that all new patches get tested in the -mm tree before they are sent to Linus for inclusion in the main kernel tree.

These kernels are not appropriate for use on systems that are supposed to be stable and they are more risky to run than any of the other branches.

If you wish to help out with the kernel development process, please test and use these kernel releases and provide feedback to the linux-kernel mailing list if you have any problems, and if everything works properly.

In addition to all the other experimental patches, these kernels usually also contain any changes in the mainline -git kernels available at the time of release.

The -mm kernels are not released on a fixed schedule, but usually a few -mm kernels are released in between each -rc kernel (1 to 3 is common).

Subsystem Specific kernel trees and patches


A number of the different kernel subsystem developers expose their development trees so that others can see what is happening in the different areas of the kernel. These trees are pulled into the -mm kernel releases as described above.

Here is a list of some of the different kernel trees available:

git trees:

  • Kbuild development tree, Sam Ravnborg [email protected] kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git

  • ACPI development tree, Len Brown [email protected] kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git

  • Block development tree, Jens Axboe [email protected] kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git

  • DRM development tree, Dave Airlie [email protected] kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git

  • ia64 development tree, Tony Luck [email protected] kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git

  • ieee1394 development tree, Jody McIntyre [email protected] kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git

  • infiniband, Roland Dreier [email protected] kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git

  • libata, Jeff Garzik [email protected] kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

  • network drivers, Jeff Garzik [email protected] kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

  • pcmcia, Dominik Brodowski [email protected] kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git

  • SCSI, James Bottomley [email protected] kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git


Other git kernel trees can be found listed at http://kernel.org/git

quilt trees:

  • USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman [email protected] kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/


Bug Reporting


is where the Linux kernel developers track kernel bugs. Users are encouraged to report all bugs that they find in this tool. For details on how to use the kernel bugzilla, please see: http://test.kernel.org/bugzilla/faq.html

The file REPORTING-BUGS in the main kernel source directory has a good template for how to report a possible kernel bug, and details what kind of information is needed by the kernel developers to help track down the problem.

Mailing lists


As some of the above documents describe, the majority of the core kernel developers participate on the Linux Kernel Mailing list. Details on how to subscribe and unsubscribe from the list can be found at: http://vger.kernel.org/vger-lists.html#linux-kernel There are archives of the mailing list on the web in many different places. Use a search engine to find these archives. For example: http://dir.gmane.org/gmane.linux.kernel It is highly recommended that you search the archives about the topic you want to bring up, before you post it to the list. A lot of things already discussed in detail are only recorded at the mailing list archives.

Most of the individual kernel subsystems also have their own separate mailing list where they do their development efforts. See the MAINTAINERS file for a list of what these lists are for the different groups.

Many of the lists are hosted on kernel.org. Information on them can be found at: http://vger.kernel.org/vger-lists.html

Please remember to follow good behavioral habits when using the lists. Though a bit cheesy, the following URL has some simple guidelines for interacting with the list (or any list): http://www.albion.com/netiquette/

If multiple people respond to your mail, the CC: list of recipients may get pretty large. Don't remove anybody from the CC: list without a good reason, or don't reply only to the list address. Get used to receiving the mail twice, one from the sender and the one from the list, and don't try to tune that by adding fancy mail-headers, people will not like it.

Remember to keep the context and the attribution of your replies intact, keep the "John Kernelhacker wrote ...:" lines at the top of your reply, and add your statements between the individual quoted sections instead of writing at the top of the mail.

If you add patches to your mail, make sure they are plain readable text as stated in Documentation/SubmittingPatches. Kernel developers don't want to deal with attachments or compressed patches; they may want to comment on individual lines of your patch, which works only that way. Make sure you use a mail program that does not mangle spaces and tab characters. A good first test is to send the mail to yourself and try to apply your own patch by yourself. If that doesn't work, get your mail program fixed or change it until it works.

Above all, please remember to show respect to other subscribers.

Working with the community


The goal of the kernel community is to provide the best possible kernel there is. When you submit a patch for acceptance, it will be reviewed on its technical merits and those alone. So, what should you be expecting?

  • criticism

  • comments

  • requests for change

  • requests for justification

  • silence


Remember, this is part of getting your patch into the kernel. You have to be able to take criticism and comments about your patches, evaluate them at a technical level and either rework your patches or provide clear and concise reasoning as to why those changes should not be made. If there are no responses to your posting, wait a few days and try again, sometimes things get lost in the huge volume.

What should you not do?

  • expect your patch to be accepted without question

  • become defensive

  • ignore comments

  • resubmit the patch without making any of the requested changes


In a community that is looking for the best technical solution possible, there will always be differing opinions on how beneficial a patch is. You have to be cooperative, and willing to adapt your idea to fit within the kernel. Or at least be willing to prove your idea is worth it. Remember, being wrong is acceptable as long as you are willing to work toward a solution that is right.

It is normal that the answers to your first patch might simply be a list of a dozen things you should correct. This does not imply that your patch will not be accepted, and it is not meant against you personally. Simply correct all issues raised against your patch and resend it.

Differences between the kernel community and corporate structures


The kernel community works differently than most traditional corporate development environments. Here are a list of things that you can try to do to try to avoid problems:

Good things to say regarding your proposed changes:

  • "This solves multiple problems."

  • "This deletes 2000 lines of code."

  • "Here is a patch that explains what I am trying to describe."

  • "I tested it on 5 different architectures..."

  • "Here is a series of small patches that..."

  • "This increases performance on typical machines..."


Bad things you should avoid saying:

  • "We did it this way in AIX/ptx/Solaris, so therefore it must be good..."

  • "I've being doing this for 20 years, so..."

  • "This is required for my company to make money"

  • "This is for our Enterprise product line."

  • "Here is my 1000 page design document that describes my idea"

  • "I've been working on this for 6 months..."

  • "Here's a 5000 line patch that..."

  • "I rewrote all of the current mess, and here it is..."

  • "I have a deadline, and this patch needs to be applied now."


Another way the kernel community is different than most traditional software engineering work environments is the faceless nature of interaction. One benefit of using email and irc as the primary forms of communication is the lack of discrimination based on gender or race. The Linux kernel work environment is accepting of women and minorities because all you are is an email address. The international aspect also helps to level the playing field because you can't guess gender based on a person's name. A man may be named Andrea and a woman may be named Pat. Most women who have worked in the Linux kernel and have expressed an opinion have had positive experiences.

The language barrier can cause problems for some people who are not comfortable with English. A good grasp of the language can be needed in order to get ideas across properly on mailing lists, so it is recommended that you check your emails to make sure they make sense in English before sending them.

Break up your changes


The Linux kernel community does not gladly accept large chunks of code dropped on it all at once. The changes need to be properly introduced, discussed, and broken up into tiny, individual portions. This is almost the exact opposite of what companies are used to doing. Your proposal should also be introduced very early in the development process, so that you can receive feedback on what you are doing. It also lets the community feel that you are working with them, and not simply using them as a dumping ground for your feature. However, don't send 50 emails at one time to a mailing list, your patch series should be smaller than that almost all of the time.

The reasons for breaking things up are the following:

  • Small patches increase the likelihood that your patches will be applied, since they don't take much time or effort to verify for correctness. A 5 line patch can be applied by a maintainer with barely a second glance. However, a 500 line patch may take hours to review for correctness (the time it takes is exponentially proportional to the size of the patch, or something).

    Small patches also make it very easy to debug when something goes wrong. It's much easier to back out patches one by one than it is to dissect a very large patch after it's been applied (and broken something).

  • It's important not only to send small patches, but also to rewrite and simplify (or simply re-order) patches before submitting them.


Here is an analogy from kernel developer Al Viro:
"Think of a teacher grading homework from a math student. The teacher does not want to see the student's trials and errors before they came up with the solution. They want to see the cleanest, most elegant answer. A good student knows this, and would never submit her intermediate work before the final solution."

The same is true of kernel development. The maintainers and reviewers do not want to see the thought process behind the solution to the problem one is solving. They want to see a simple and elegant solution."

It may be challenging to keep the balance between presenting an elegant solution and working together with the community and discussing your unfinished work. Therefore it is good to get early in the process to get feedback to improve your work, but also keep your changes in small chunks that they may get already accepted, even when your whole task is not ready for inclusion now.

Also realize that it is not acceptable to send patches for inclusion that are unfinished and will be "fixed up later."

Justify your change


Along with breaking up your patches, it is very important for you to let the Linux community know why they should add this change. New features must be justified as being needed and useful.

Document your change


When sending in your patches, pay special attention to what you say in the text in your email. This information will become the ChangeLog information for the patch, and will be preserved for everyone to see for all time. It should describe the patch completely, containing:

  • why the change is necessary

  • the overall design approach in the patch

  • implementation details

  • testing results


For more details on what this should all look like, please see the ChangeLog section of the document:
"The Perfect Patch" http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt

All of these things are sometimes very hard to do. It can take years to perfect these practices (if at all). It's a continuous process of improvement that requires a lot of patience and determination. But don't give up, it's possible. Many have done it before, and each had to start exactly where you are now.

为什么Java中继承多数是有害的

大多数好的设计者象躲避瘟疫一样来避免使用实现继承(extends 关系)。实际上80%的代码应该完全用interfaces写,而不是通过extends。“Java设计模式”一书详细阐述了怎样用接口继承代替实现继承。这篇文章描述设计者为什么会这么作。

  Extends是有害的;也许对于Charles Manson这个级别的不是,但是足够糟糕的它应该在任何可能的时候被避开。“JAVA设计模式”一书花了很大的部分讨论用interface继承代替实现继承。

  好的设计者在他的代码中,大部分用interface,而不是具体的基类。本文讨论为什么设计者会这样选择,并且也介绍一些基于interface的编程基础。

  接口(Interface)和类(Class)?

  一次,我参加一个Java用户组的会议。在会议中,Jams Gosling(Java之父)做发起人讲话。在那令人难忘的Q&A部分中,有人问他:“如果你重新构造Java,你想改变什么?”。“我想抛弃 classes”他回答。在笑声平息后,它解释说,真正的问题不是由于class本身,而是实现继承(extends) 关系。接口继承(implements关系)是更好的。你应该尽可能的避免实现继承。

  失去了灵活性

  为什么你应该避免实现继承呢?第一个问题是明确的使用具体类名将你固定到特定的实现,给底层的改变增加了不必要的困难。

  在当前的敏捷编程方法中,核心是并行的设计和开发的概念。在你详细设计程序前,你开始编程。这个技术不同于传统方法的形式----传统的方式是设计应该在编码开始前完成----但是许多成功的项目已经证明你能够更快速的开发高质量代码,相对于传统的按部就班的方法。但是在并行开发的核心是主张灵活性。你不得不以某一种方式写你的代码以至于最新发现的需求能够尽可能没有痛苦的合并到已有的代码中。

  胜于实现你也许需要的特征,你只需实现你明确需要的特征,而且适度的对变化的包容。如果你没有这种灵活,并行的开发,那简直不可能。

  对于Inteface的编程是灵活结构的核心。为了说明为什么,让我们看一下当使用它们的时候,会发生什么。考虑下面的代码:

  f()
  {
  LinkedList list = new LinkedList();
  //...
  g( list );
  }

  g( LinkedList list )
  {
  list.add( ... );
  g2( list )
  }

  假设一个对于快速查询的需求被提出,以至于这个LinkedList不能够解决。你需要用HashSet来代替它。在已有代码中,变化不能够局部化,因为你不仅仅需要修改f()也需要修改g()(它带有LinkedList参数),并且还有g()把列表传递给的任何代码。象下面这样重写代码:

  f()
  {
  Collection list = new LinkedList();
  //...
  g( list );
  }

  g( Collection list )
  {
  list.add( ... );
  g2( list )
  }

  这样修改Linked list成hash,可能只是简单的用new HashSet()代替new LinkedList()。就这样。没有其他的需要修改的地方。

  作为另一个例子,比较下面两段代码:

  f()
  {
  Collection c = new HashSet();
  //...
  g( c );
  }

  g( Collection c )
  {
  for( Iterator i = c.iterator(); i.hasNext() )
  do_something_with( i.next() );
  }

  和

  f2()
  {
  Collection c = new HashSet();
  //...
  g2( c.iterator() );
  }

  g2( Iterator i )
  {
  while( i.hasNext() )
  do_something_with( i.next() );
  }


  g2()方法现在能够遍历Collection的派生,就像你能够从Map中得到的键值对。事实上,你能够写iterator,它产生数据,代替遍历一个Collection。你能够写iterator,它从测试的框架或者文件中得到信息。这会有巨大的灵活性。

  耦合

  对于实现继承,一个更加关键的问题是耦合---令人烦躁的依赖,就是那种程序的一部分对于另一部分的依赖。全局变量提供经典的例子,证明为什么强耦合会引起麻烦。例如,如果你改变全局变量的类型,那么所有用到这个变量的函数也许都被影响,所以所有这些代码都要被检查,变更和重新测试。而且,所有用到这个变量的函数通过这个变量相互耦合。也就是,如果一个变量值在难以使用的时候被改变,一个函数也许就不正确的影响了另一个函数的行为。这个问题显著的隐藏于多线程的程序。

  作为一个设计者,你应该努力最小化耦合关系。你不能一并消除耦合,因为从一个类的对象到另一个类的对象的方法调用是一个松耦合的形式。你不可能有一个程序,它没有任何的耦合。然而,你能够通过遵守OO规则,最小化一定的耦合(最重要的是,一个对象的实现应该完全隐藏于使用他的对象)。例如,一个对象的实例变量(不是常量的成员域),应该总是private。我意思是某段时期的,无例外的,不断的。(你能够偶尔有效地使用protected方法,但是protected实例变量是可憎的事)同样的原因你应该不用get/set函数---他们对于是一个域公用只是使人感到过于复杂的方式(尽管返回修饰的对象而不是基本类型值的访问函数是在某些情况下是由原因的,那种情况下,返回的对象类是一个在设计时的关键抽象)。

  这里,我不是书生气。在我自己的工作中,我发现一个直接的相互关系在我OO方法的严格之间,快速代码开发和容易的代码实现。无论什么时候我违反中心的 OO原则,如实现隐藏,我结果重写那个代码(一般因为代码是不可调试的)。我没有时间重写代码,所以我遵循那些规则。我关心的完全实用?我对干净的原因没有兴趣。

   脆弱的基类问题

  现在,让我们应用耦合的概念到继承。在一个用extends的继承实现系统中,派生类是非常紧密的和基类耦合,当且这种紧密的连接是不期望的。设计者已经应用了绰号“脆弱的基类问题”去描述这个行为。基础类被认为是脆弱的是,因为你在看起来安全的情况下修改基类,但是当从派生类继承时,新的行为也许引起派生类出现功能紊乱。你不能通过简单的在隔离下检查基类的方法来分辨基类的变化是安全的;而是你也必须看(和测试)所有派生类。而且,你必须检查所有的代码,它们也用在基类和派生类对象中,因为这个代码也许被新的行为所打破。一个对于基础类的简单变化可能导致整个程序不可操作。

  让我们一起检查脆弱的基类和基类耦合的问题。下面的类extends了Java的ArrayList类去使它像一个stack来运转:

  class Stack extends ArrayList
  {
  private int stack_pointer = 0;

  public void push( Object article )
  {
  add( stack_pointer++, article );
  }

  public Object pop()
  {
  return remove( --stack_pointer );
  }

  public void push_many( Object[] articles )
  {
  for( int i = 0; i < articles.length; ++i )
   push( articles[i] );
  }
  }

  甚至一个象这样简单的类也有问题。思考当一个用户平衡继承和用ArrayList的clear()方法去弹出堆栈时:

  Stack a_stack = new Stack();
  a_stack.push("1");
  a_stack.push("2");
  a_stack.clear();

  这个代码成功编译,但是因为基类不知道关于stack指针堆栈的情况,这个stack对象当前在一个未定义的状态。下一个对于push()调用把新的项放入索引2的位置。(stack_pointer的当前值),所以stack有效地有三个元素-下边两个是垃圾。(Java的stack类正是有这个问题,不要用它).

  对这个令人讨厌的继承的方法问题的解决办法是为Stack覆盖所有的ArrayList方法,那能够修改数组的状态,所以覆盖正确的操作Stack指针或者抛出一个例外。(removeRange()方法对于抛出一个例外一个好的候选方法)。

  这个方法有两个缺点。第一,如果你覆盖了所有的东西,这个基类应该真正的是一个interface,而不是一个class。如果你不用任何继承方法,在实现继承中就没有这一点。第二,更重要的是,你不能够让一个stack支持所有的ArrayList方法。例如,令人烦恼的removeRange()没有什么作用。唯一实现无用方法的合理的途径是使它抛出一个例外,因为它应该永远不被调用。这个方法有效的把编译错误成为运行错误。不好的方法是,如果方法只是不被定义,编译器会输出一个方法未找到的错误。如果方法存在,但是抛出一个例外,你只有在程序真正的运行时,你才能够发现调用错误。

  对于这个基类问题的一个更好的解决办法是封装数据结构代替用继承。这是新的和改进的Stack的版本:

  class Stack
  {
  private int stack_pointer = 0;
  private ArrayList the_data = new ArrayList();

  public void push( Object article )
  {
  the_data.add( stack_poniter++, article );
  }

  public Object pop()
  {
  return the_data.remove( --stack_pointer );
  }

  public void push_many( Object[] articles )
  {
  for( int i = 0; i < o.length; ++i )
   push( articles[i] );
  }
  }

  到现在为止,一直都不错,但是考虑脆弱的基类问题,我们说你想要在stack创建一个变量, 用它在一段周期内跟踪最大的堆栈尺寸。一个可能的实现也许象下面这样:

  class Monitorable_stack extends Stack
  {
  private int high_water_mark = 0;
  private int current_size;

  public void push( Object article )
  {
  if( ++current_size > high_water_mark )
   high_water_mark = current_size;
   super.push( article );
  }

  publish Object pop()
  {
  --current_size;
  return super.pop();
  }

  public int maximum_size_so_far()
  {
  return high_water_mark;
  }
  }

  这个新类运行的很好,至少是一段时间。不幸的是,这个代码发掘了一个事实,push_many()通过调用push()来运行。首先,这个细节看起来不是一个坏的选择。它简化了代码,并且你能够得到push()的派生类版本,甚至当Monitorable_stack通过Stack的参考来访问的时候,以至于high_water_mark能够正确的更新。

Java Exception 机制

早期的C语言的异常处理机制,通常是我们人为的对返回结果加一些标志来进行判定,比如发生错误返回什么标志,正常情况下我们又是返回什么标记,而这些都不是语言本身所赋予我们的,而对于C语言这种机制又有什么问题哩?为什么新一代的语言 Java Ruby C# 等都用Exception机制而不是维持C语言的老样子?

C语言的异常处理机制全是我们人为的定义,这样就会造成业务逻辑的主线受到异常处理的牵制,或者说是我们难免会将注意力转移,并且造成业务逻辑与异常处理之间有很大程度上的缠绕。

Java Exception 异常处理机制其实起源很早,所以他也不是个什么新鲜的东西,如果您对Exception机制一点都不了解,没关系,只是国内通常接触新事务的时间都相对的要晚老美几年,但了解Java Exception机制对Java开发人员来说是必要的,不过Exception 异常处理机制也并没有固定,在Anders 的眼里他也是一个试验性的东西。

理论上异常处理划分为两个模型(中止模型与继续模型),但实际使用方面我们对中止模型用的比较多,这个模型比较实用,而继续模型则不是那么的应用普遍,多少是耦合的过于紧密。

中止模型 :假设错误非常严重,已至你无法在回到错误发生的地方,也就是说,这段程序经过判断认为,他已经没有办法挽回,于是就抛出异常,希望这个异常不要在回来,这也是Java 当前所采用的模式。
继续模型:这种模型的主旨是恢复当前的运行环境,然后希望能够重新回到错误的发生地,并希望第二次的尝试能够获得成功,这种模型通常为操作系统所应用。

下面我来简要的说说Java Exception 的好处及用法:

Java Exception 好处:让异常处理与业务逻辑的主线分离,我们可以对可以遇见的异常作分支处理,其实将业务逻辑与异常处理分离也是Exception设计的主旨,其次 Java Exception 不需要像C语言那样在程序的多个地方去检测同一个错误,并就地作异常的处理,相比老式的错误处理,现在的错误处理的结构则来的更加清晰。

Java Exception 用法:下面的实例是一个loadUser方法,我们将抛出自定义的UserNotFoundException异常。

public class UserManager {
public User loadUser(String username) throws UserNotFoundException {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_USER);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
throw new UserNotFoundException();
}

}

}
}

public class UserNotFoundException extends Exception {

private Throwable nestedThrowable = null;

public UserNotFoundException() {
super();
}

public UserNotFoundException(String msg) {
super(msg);
}

}

public class test {

public void testloadUser(String userName,String password,
String name,String email){

try {
loadUser(username);
}
catch (UserNotFoundException unfe) {

Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(INSERT_USER);
pstmt.setString(1, username);
pstmt.setString(2, password);

pstmt.execute();
}
catch (Exception e) { }

}

在这里我们自定义了自己的UserNotFoundException异常,这样在客户调用loadUser()方法的时候Java就可以强制检测到这个 UserNotFoundException异常,这样我们就可以作相应的处理工作,在这里应该可以看到testloadUser这里对 UserNotFoundException这个异常有一个分支处理,这样的异常分支处理是不是很清晰哩,在此我不对他作解释,因为实在比较简单,其实美好的东西在我看来都有一个度,当这个度被你所打破后,那么他将不会再美好,Exception机制的应用也是,而这个度就需要你自己在实际项目中去斟酌了,接下来我就会阐述Exception的缺点。

Java 有将受控异常和运行时异常模型都实现,Rod Johnson认为在Java中主要实现运行时异常模型,至于受控异常则为辅,而Bruce Eckel则来的更为偏激一些,他认为Java只需要实现运行时异常模型,而受控异常没有必要继续存在,为什么他们都这么认为哩,而且Bruce Eckel 之前很是推崇受控异常地,其实也没那么多为什么,这些思维的改变不过就是他们在实践当中发现了很多问题且对Exception 认识也更深刻了呗,所以说大师不是天生的,大师也需要学习,在这里我更赞成Rod Johnson 对Exception的观点,OK,废话我也不多说了,说说我认识中的Java Exception 缺点!

1 、当一个方法中被过多的抛出受控异常,那么在别人调用的时候会造成try/catch语句的泛滥,甚至经常出现嵌套异常,使得代码的可读性下降。
2、在某些方面检测系统的异常也并没有实际的意义,因为当出现这种异常的时候一般代表问题很严重我们无法恢复,如:捕获数据库SQLException异常,该异常对我们来说没太大意义,因为错误信息太模糊,通常都是一些堆栈上的信息,看Rod Johnson 设计的关于JDBC方面的Exception Framework相信会对您产生很大的触动。
3、在大型系统中受控异常同时会造成异常处理类的泛滥,其实本人并没有介入过什么大型的Java 系统的设计工作,所以我也无从对这指三道四,没有实践就没有发言权,但我在一般的系统已经多少看到了一些这样的问题。