VPN常见客户端错误721以及其解决办法
VPN常见客户端错误721
1、该错误是由于客户端电脑在局域网中并通过路由器上网所致。
721错误原因:721错误是由于您的电脑处在内网造成的。什么是内网?内网是指:您的电脑的上网方式是通过局域网中的路由器上网的。普通连接方式PPTP是根据客户端IP地址进行认定为一个连接,而由于您的电脑是通过局域网中的路由器上网,在局域网中就可能存在多台电脑,服务器就无法正确判断具体是哪台电脑(由于内网所有电脑的IP地址都是一样的),所以连接时会提示错误721。
解决方案:使用L2TP的连接方式进行连接。L2TP是一种特殊的连接方式,这种连接方式是根据客户端电脑操作系统的相关项进行认定为一个连接,就不会被局域网中多台电脑相同公网IP所欺骗,即可全面解决无法连接的问题。
2、该错误是由于客户端电脑跟服务器使用不同宽带服务商之间的直接互访问题所致。
如果你是长城宽带、铁通宽带的话,那么只能遗憾的告诉你,你用的这些宽带可能是连不上PPTP协议VPN,原因是这些公司(和电信网通公司相比)到CNNIC拿到的IP段资源很少,以及出口带宽资源有限,一般不大可能给下面的宽带用户分配外网的IP,大都使用路由器的方式给下面的客户分配内网IP段使用,比如10.10.*.*;192.168.*.*等等;这些公司在路由器上是屏蔽PPTP协议的穿透的,所以你连接提示721错误,在此推荐大家还是多几十块钱使用电信或是网通的宽带;还有中国90%的校园网也是不能使用VPN的。
解决方案:使用铁通的宽带时,可以去ping一下服务器端的公网IP地址,看看是否可以ping通(当然服务器端不能禁止ping命令的前提下),如果电信不可以ping通铁通的公网IP地址, 基本可以确定是宽带服务商直接的互访出现问题(只能找客户端的宽带服务商解决)。
VPN 721错误解决方法
查看全文Windows XP SP3 纯净版原版迅雷下载地址
Windows XP SP3原版(MSDN)系统
Windows XP pro sp3 VOL 微软原版下载:
zh-hans_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-74070.iso
下载后请自行检查下列数值
大小: 630237184 字节
MD5: E74D72F3D90456003E9E02BA0FB7DA61
SHA1: D142469D0C3953D8E4A6A490A58052EF52837F0F
CRC32: FFFFFFFF
迅雷下载地址如下(复制以下地址,启动运行迅雷,新建任务):
查看全文邮递列表和实现清单的软件
邮递列表是一个巨大的别名,它把邮递给它的每则消息的副本发送给加入此列表的所有人。就像是通过电子邮件投递的一个Usenet新闻组。有些邮递列表拥有数以千计的收件人。
邮递列表通常在aliases文件中指定,但保存在某个外部文件中。sendmail和大多数邮递列表软件可以理解一些标准的命名约定。有经验的用户也已经开始依赖它们了。最常用的就是“-request”后缀和“owner-”前缀,用它们来联络邮递列表的维护者。下面这些别名举例说明了这些约定:
![]() |
在这个例子中,mylist是邮递列表的名字。邮递列表的成员则从文件/etc/mail/include/mylist中读取。对发到列表并被回复的邮件将发送给邮递列表的所有者evi,作为加入这个列表的申请。从“owner”到“request”再到“evi”的做法是有用的,因为owner的地址(在本例中是mylist-request)变成了发送给此列表的各个消息的Return-Path地址。用mylist-request比用这个领域实际维护者的名字要好一点。发送给别名owner-mylist(其实就是evi)的消息中的错误将被发给owner-owner。
消息不可投递的情况称为弹回(bounce)。发送有关弹回的出错信息时无法投递的情况称为二次弹回(double bounce)。于是在我们的例子中,二次弹回被发给owner-owner即postmaster。
如果使用整个站点的别名文件,则需要再多加一级迂回,把mylist指向myreallist@master,以使包含成员列表的数据文件只需要存在于一个地方。
查看全文majordomo邮件列表快速安装指南
rpm -i majordomo-1.94.4-6.i386.rpm
(注意RedHat5.2内附的perl5.004m4版有问题,要更新至5.005版)
执行完后/usr/lib/majordomo/为主程序所在目录.
/var/lib/majordomo/为mailing list 资料所在目录.
并且会产生majordomo这user及group
Step 2.
修改 /etc/majordomo.cf
$homedir = /usr/lib/majordomo/
$whereami = your FQDN
Step 3.
/etc/majordomo.aliases 档内容大致如下:
majordomo: "|/usr/lib/majordomo/wrapper majordomo"
owner-majordomo: majordomo-owner
majordomo-owner: root
test-list-approval: test-list-owner
owner-test-list: test-list-owner
test-list-owner: root
owner-test-list-archive: test-list-owner
test-list: "|/usr/lib/majordomo/wrapper resend
-A -a /var/lib/majordomo/lists/test-list.passwd
-l test-list
-h linpus test-list-announce"
test-list-announce: :include:/var/lib/majordomo/lists/test-list,
"| /usr/lib/majordomo/wrapper archive2.pl -a -m -f
/var/lib/majordomo/archives/test-list"
(resend是用来分析那些寄过来的文章,并作处理.
-A 表示此list为moderated list ,即任何寄到此list的文章都必须经过
test-list-owner的approve才会流到各订阅此list的信箱中.
-a filename 该文件记录moderator approve此信件password
-h hostname 为此mailing list server的hostname
-l listname 此list的名字
archive2.pl是把所有收到的信件存在/var/lib/majordomo/archives/listname里
Step 4:
加入 "OA/etc/majordomo.aliases" 于 /etc/sendmail.cf
Step 5:
执行newaliases
(若sendmail.cf设为O AutoRebuildAliases则不必做此步骤)
Step 6:
将 "majordomo" 加入sendmail.cf的 Trusted users list,如下:
#####################
# Trusted users #
#####################
# this is equivalent to setting class "t"
#Ft/etc/sendmail.ct
Troot
Tdaemon
Tuucp
Tmajordomo
Tnobody
Step 7:
Create a test-list (假设要建立的新mailing list 为test-list)
touch /var/lib/majordomo/lists/test-list
chown majordomo.majordomo /var/lib/majordomo/lists/test-list
Step 8:
在/var/lib/majordomo/lists/test-list.info档里写些关于此mailing list的一些说明
其它:/var/lib/majordomo/lists/test-list文件是记录哪些email addr订阅此list.
test-list.config为此list的configuration files,会自动产生.
若要关于此list,只须产生对于的listname.close于lists目录下即可.
若要自动使欲订阅者成功订阅而不必回复身份确认信,则只须产生listname.auto即可
Step 9:
Any article post to this mailing list must be approved by the owner of the list. The owner of the list can approve the article by resend it to the list, and add "Approved: password-of-approval" at the beginning of the message body.
Step 10:
为了测试majordomo是否成功运转,输入
echo 'lists'|mail majordomo
若寄回来的是majordomo发出的信则成功,若是mail daemon return
的信则是错误。
Step 11:
可能的错误,"sh: wrapper not available for sendmail programs"
你的系统使用了 smrsh (sendmail restricted shell). 你必须要使smrsh让你使用这个wrapper,可能的解法是ln -s /the/path/of/your/wrapper
/var/adm/sm.bin
域名解析不稳定诊断步骤
1、通过ping命令查看解析的IP地址,多ping几次看看是否指向多个IP。
2、通过nslookup命令查看解析的域名和IP地址,有时候一次命令就可以看到被解析到多个IP,有时候需要执行多次命令才能看到,这就类似ping的效果了。
3、通过以上两步确认被解析到多个不同IP后,就再找原因。根本原因一般是在域名解析管理后台上,可能有设置域名转向没有取消,也可能是DNS设置错误或DNS服务器失效
Linux下如何使CP命令不提示覆盖
[test@Server home]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
[test@Server home]# vi ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
fi
tar 解压缩命令
tar
-c: 建立压缩档案
-x:解压-t:查看内容
-r:向压缩归档文件末尾追加文件
-u:更新原压缩包中的文件
这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。
-z:有gzip属性的
-j:有bz2属性的
-Z:有compress属性的
-v:显示所有过程-O:将文件解开到标准输出
下面的参数-f是必须的
-f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。
# tar -cf all.tar *.jpg 这条命令是将所有.jpg的文件打成一个名为all.tar的包。-c是表示产生新的包,-f指定包的文件名。
# tar -rf all.tar *.gif
这条命令是将所有.gif的文件增加到all.tar的包里面去。-r是表示增加文件的意思。
# tar -uf all.tar logo.gif
这条命令是更新原来tar包all.tar中logo.gif文件,-u是表示更新文件的意思。
# tar -tf all.tar
这条命令是列出all.tar包中所有文件,-t是列出文件的意思
# tar -xf all.tar
这条命令是解出all.tar包中所有文件,-x是解开的意思
压缩
tar –cvf jpg.tar *.jpg //将目录里所有jpg文件打包成tar.jpg
tar –czf jpg.tar.gz *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz
tar –cjf jpg.tar.bz2 *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2
tar –cZf jpg.tar.Z *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z
rar a jpg.rar *.jpg //rar格式的压缩,需要先下载rar for linux
zip jpg.zip *.jpg //zip格式的压缩,需要先下载zip for linux
解压
tar –xvf file.tar //解压 tar包
tar -xzvf file.tar.gz //解压tar.gz
tar -xjvf file.tar.bz2 //解压 tar.bz2
tar –xZvf file.tar.Z //解压tar.Z
unrar e file.rar //解压rar
unzip file.zip //解压zip
总结
1、*.tar 用 tar –xvf 解压
2、*.gz 用 gzip -d或者gunzip 解压
3、*.tar.gz和*.tgz 用 tar –xzf 解压
4、*.bz2 用 bzip2 -d或者用bunzip2 解压
5、*.tar.bz2用tar –xjf 解压
6、*.Z 用 uncompress 解压
7、*.tar.Z 用tar –xZf 解压
8、*.rar 用 unrar e解压
9、*.zip 用 unzip 解压
SMTP服务器的构建 ( Postfix )
POP / IMAP 服务器的构建( Dovecot )
Dovecot 是一个开源的 IMAP 和 POP3 邮件服务器,支持 Linux/Unix 系统。
POP / IMAP 是 MUA 从邮件服务器中读取邮件时使用的协议。其中,与 POP3 是从邮件服务器中下载邮件比起来,IMAP4 则是将邮件留在服务器端直接对邮件进行管理、操作。而Dovecot 是一个比较新的软件,由 Timo Sirainen 开发,最初发布于 2002年7月。作者将安全性考虑在第一,所以 Dovecot 在安全性方面比较出众。另外,Dovecot 支持多种认证方式,所以在功能方面也比较符合一般的应用。
中文配置指南:http://www.centospub.com/make/dovecot_pop3.html
php5 编译支持imap
欲使用 IMAP 的电子邮件功能,要先到 ftp://ftp.cac.washington.edu/imap 下载 IMAP 的客户端程序。在编译完成之后将 c-client/c-client.a 复制到 /usr/local/lib 之中,并将 c-client/rfc822.h、mail.h 及 linkage.h 三个文件复制到 /usr/local/include 之下。之后编译 PHP 程序时要加入 --with-imap 的选项。
IIS使服务器支持openssl并成功配置ECSHOP支持gmail的SMTP
众所周知,IIS主机大都不支持OPENSSL,所以本篇讨论内容为自由主机或者可以对主机有操控权的用户,以下经验也是我在摸索ecshop期间所得,如果之前有了类似文章请直接跳过。
查看全文在Windows XP上安装SQL Server 2000
在默认的情况下,SQL2000企业版只适用于Server系统。
使用SQL2000光盘安装SQL2000的时候(直接点击光盘根目录下的autorun.exe),根据提示,自检系统不是SERVER版,SQL2000服务器不能安装,只提示安装客户端工具。
在SQL2000光盘中,找到MSDE目录,运行setup.exe。这就是SQL2000服务器的安装程序,进行安装。
查看全文告诉你一个简单、深刻的经商道理
读书整整读了十多年,才终于毕业走上了社会。在这期间,都不知道参加过了多少次的考试。所以,慢慢地对如何对付考试,以及如何考得一个好成绩,就琢磨出了一套行之有效的好方法。就好比现在做生意做得时间长了,都做成了精一样。
我仔细地对比了一下,其实,读书与创业还真是非常地类同。往往一个好的读书方法,在经过一番哲学升华之后,也能用到创业上来。而且,往往还都能行之有效,并且,都能带来非凡的效果。
八七年参加高考时,一个原来成绩一直比我好的同学却意外地掉队了。我也觉得很奇怪,按理来说,他的数学、物理成绩并不比我差,可我那次高考的数学和物理二门功课的成绩加起来就要超过他80分。我都觉得很不可思议,但后来就弄明白了:
原来,他为了一股子的“精英分子”气概,居然盯住很难的附加题不放了。他觉得凭他的本事,应该能够解得开这二道附加题。他一向来都是先做后面的难题,尔后再做前面容易得分的小题目的。对于那些常识性的“送分题”,他总是不屑一顾的。他一向来的习惯是等到做完后面的难题后,再回过头去快速地做这些小题目。凭他的老经验,这些小题目虽然数量多,可真正需要花费的时间并不多。所以,在以往的所有模拟考试中,他总是用70%的时间来解答难题,而只用30%的时间来快速地完成小题目的。而这一次,他整整花了80%的时间,都没能解出这道难题来。他越到后面越觉得放弃的话太可惜了,就越是盯住那道难题不放了。结果,他虽然是我们学校唯一完整地解开这道难题的学生,却终于因为没有充足的时间做其它“送分题”了,而落榜了。
那我又是怎么对付这类难题的呢?我一向来的办法是:先把这类排在后面的难题先描上一眼,把题目的大概意思先记在心里。然后,用大约40%的时间快速地去消灭前面的“送分题”,一边做“送分题”,就一边思考那道难题。因为概念是相通的,所以,原来毫无思路的脑袋,也没准会因为做“送分题”而触发了解答难题的灵感。等到把这些基本分都捞进口袋后,再安心地用50%的时间去对付难题。但如果到了离终场还有10%左右的时间时还没解答出来,那我就干脆放弃了。用最后余下的10%时间去快速地回头检查所有的答案是否正确。正因为这样的安排。所以,在平时,那个同学总是因为附加题解答得特别出色,而考得比我好。但那次高考时,他却没我考得好了。
现在做生意,我也经常按照这个指导方针做。我总是先把能够快速地挣到的钱先挣进来再说,不管它是大钱还是小钱;也总是先把能够做又容易做的项目先做起来,也不管它是高新技术项目还是低附加值的项目;在发展销售代理商时,我也总是先快速地把一些大家都容易抢的渠道先抢到手再说,也不管这渠道是大渠道还是小渠道;反正,只要有足够的精力,就先去占领市场,省得给其他人以进入的机会。在一边做容易做的事时,一边就考虑其它更好的发展方向。等到这些容易解决的事都解决得差不多了,销售基本稳定住了,我就会把这盘棋交给一个弟弟或妹妹去掌管,而自己则去一心一意地对付后面的大项目、大客户了。
但很多人却不是象我这样做的,他们往往就是象我那个落榜的同学那样,一头钻到大工程、大项目、大生意上去。这类人,成功了,就比我还成功;失败了,则就会象我那同学一样惨不忍睹。我也不是说我的方法绝对正确,但我觉得,对于一个创业者来说:
先拣容易做的做,然后,再抽时间解决难题—这应该不失为一种好的指导方针的。
如何让百度、google搜索到你的网站和博客
1、百度
要让百度搜索到的话,很简单,加入百度搜索联盟,上面承诺会在1个月内收录你的网站!
联盟地址:http://union.baidu.com
按照里面的要求操作就行了
登录/更新网站
Google 经常在网上漫游,搜寻新的资料。Google 也欢迎您提供新的网站信息。但 Google 会分析网站内容,以决定是否使用您提交的网站信息,而且所用时间也长短不一。
请输入完整的网址,包括前缀 http://。例如:http://www.google.com/。还可以加上网站简介,但这些说明仅供我们内部参考,并不影响 Google 对网页的编排。
请注意:登录网址时,只须提交最上层的网页,其它各页由 Googlebot 自行查找。重要说明:Google 更新网页不劳您费心,所以您无须自行更新网页信息。Google 会定期检索并更新所有网站;对于失效网页则将其删除。
网址:
说明:
从 Google 目录中删除网页记录
Google 会定期对其整个目录进行自动更新。在检索网页时,Google 会自动登录新的网页,删除失效链接。因此,您不必亲自删除失效的链接,Google 在下次检索时极有可能将其自动删除。
如果您想了解更多有关如何从 Google 目录中删除特定链接的信息,请单击此处。
man netstat(详细参数分析、输出结果参数分析)
from
NAME
netstat - Print network connections, routing tables, interface statistics, masquerade connections, and multicast memberships
SYNOPSIS
netstat [address_family_options] [--tcp|-t] [--udp|-u] [--raw|-w] [--listening|-l] [--all|-a] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--symbolic|-N] [--extend|-e[--extend|-e]] [--timers|-o] [--program|-p] [--verbose|-v] [--continuous|-c] [delay] netstat {--route|-r} [address_family_options] [--extend|-e[--extend|-e]] [--verbose|-v] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--interfaces|-i} [iface] [--all|-a] [--extend|-e[--extend|-e]] [--verbose|-v] [--program|-p] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--groups|-g} [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--masquerade|-M} [--extend|-e] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--statistics|-s} [--tcp|-t] [--udp|-u] [--raw|-w] [delay] netstat--version|-V} netstat {--help|-h} address_family_options: {
[--protocol={inet,unix,ipx,ax25, netrom,ddp}[,...]] [--unix|-x] [--inet|--ip] [--ax25] [--ipx] [--netrom] [--ddp]
DESCRIPTION
Netstat prints information about the Linux networking subsystem. The type of information printed is controlled by the first argument, as follows:(none)
By default, netstat displays a list of open sockets. If you don't specify any address families, then the active sockets of all configured address families will be printed.--route , -r
Display the kernel routing tables.--groups , -g
Display multicast group membership information for IPv4 and IPv6.--interface=iface , -i
Display a table of all network interfaces, or the specified iface).--masquerade , -M
Display a list of masqueraded connections.--statistics , -s
Display summary statistics for each protocol.OPTIONS
--verbose , -v
Tell the user what is going on by being verbose. Especially print some useful information about unconfigured address families.--numeric , -n
Show numerical addresses instead of trying to determine symbolic host, port or user names.--numeric-hosts
shows numerical host addresses but does not affect the resolution of port or user names.--numeric-ports
shows numerical port numbers but does not affect the resolution of host or user names.--numeric-users
shows numerical user IDs but does not affect the resolution of host or port names.--protocol=family , -A
Specifies the address families (perhaps better described as low level protocols) for which connections are to be shown. family is a comma (',') separated list of address family keywords like inet, unix, ipx, ax25, netrom, and ddp. This has the same effect as using the --inet, --unix (-x), --ipx, --ax25, --netrom, and --ddpinet includes raw, udp and tcp protocol sockets. options. The address family-c, --continuous
This will cause netstat to print the selected information every second continuously.-e, --extend
Display additional information. Use this option twice for maximum detail.-o, --timers
Include information related to networking timers.-p, --program
Show the PID and name of the program to which each socket belongs.-l, --listening
Show only listening sockets. (These are omitted by default.)-a, --all
Show both listening and non-listening sockets. With the --interfaces option, show interfaces that are not marked-F
Print routing information from the FIB. (This is the default.)-C
Print routing information from the route cache.delay
Netstat will cycle printing through statistics every delay seconds. UP.OUTPUT
Active Internet connections (TCP, UDP, raw)
Proto
The protocol (tcp, udp, raw) used by the socket.Recv-Q
The count of bytes not copied by the user program connected to this socket.Send-Q
The count of bytes not acknowledged by the remote host.Local Address
Address and port number of the local end of the socket. Unless the --numeric (-n) option is specified, the socket address is resolved to its canonical host name (FQDN), and the port number is translated into the corresponding service name.Foreign Address
Address and port number of the remote end of the socket. Analogous to "Local Address."State
The state of the socket. Since there are no states in raw mode and usually no states used in UDP, this column may be left blank. Normally this can be one of several values:- ESTABLISHED
- The socket has an established connection.
- SYN_SENT
- The socket is actively attempting to establish a connection.
- SYN_RECV
- A connection request has been received from the network.
- FIN_WAIT1
- The socket is closed, and the connection is shutting down.
- FIN_WAIT2
- Connection is closed, and the socket is waiting for a shutdown from the remote end.
- TIME_WAIT
- The socket is waiting after close to handle packets still in the network.
- CLOSED
- The socket is not being used.
- CLOSE_WAIT
- The remote end has shut down, waiting for the socket to close.
- LAST_ACK
- The remote end has shut down, and the socket is closed. Waiting for acknowledgement.
- LISTEN
- The socket is listening for incoming connections. Such sockets are not included in the output unless you specify the --listening (-l) or --all (-a) option.
- CLOSING
- Both sockets are shut down but we still don't have all our data sent.
- UNKNOWN
- The state of the socket is unknown.
User
The username or the user id (UID) of the owner of the socket.PID/Program name
Slash-separated pair of the process id (PID) and process name of the process that owns the socket. --programsuperuser privileges to see this information on sockets you don't own. This identification information is not yet available for IPX sockets. causes this column to be included. You will also needTimer
(this needs to be written)Active UNIX domain Sockets
Proto
The protocol (usually unix) used by the socket.RefCnt
The reference count (i.e. attached processes via this socket).Flags
The flags displayed is SO_ACCEPTON (displayed as ACC), SO_WAITDATA (W) or SO_NOSPACE (N). SO_ACCECPTON is used on unconnected sockets if their corresponding processes are waiting for a connect request. The other flags are not of normal interest.Type
There are several types of socket access:- SOCK_DGRAM
- The socket is used in Datagram (connectionless) mode.
- SOCK_STREAM
- This is a stream (connection) socket.
- SOCK_RAW
- The socket is used as a raw socket.
- SOCK_RDM
- This one serves reliably-delivered messages.
- SOCK_SEQPACKET
- This is a sequential packet socket.
- SOCK_PACKET
- Raw interface access socket.
- UNKNOWN
- Who ever knows what the future will bring us - just fill in here :-)
State
This field will contain one of the following Keywords:- FREE
- The socket is not allocated
- LISTENING
- The socket is listening for a connection request. Such sockets are only included in the output if you specify the --listening (-l) or --all (-a) option.
- CONNECTING
- The socket is about to establish a connection.
- CONNECTED
- The socket is connected.
- DISCONNECTING
- The socket is disconnecting.
- (empty)
- The socket is not connected to another one.
- UNKNOWN
- This state should never happen.
PID/Program name
Process ID (PID) and process name of the process that has the socket open. More info available in Active Internet connections section written above.Path
This is the path name as which the corresponding processes attached to the socket.Active IPX sockets
(this needs to be done by somebody who knows it)Active NET/ROM sockets
(this needs to be done by somebody who knows it)Active AX.25 sockets
(this needs to be done by somebody who knows it)
NOTES
Starting with Linux release 2.2 netstat -i does not show interface statistics for alias interfaces. To get per alias interface counters you need to setup explicit rules using the ipchains(8) command.
FILES
/etc/services -- The services translation file/proc -- Mount point for the proc filesystem, which gives access to kernel status information via the following files.
/proc/net/dev -- device information
/proc/net/raw -- raw socket information
/proc/net/tcp -- TCP socket information
/proc/net/udp -- UDP socket information
/proc/net/igmp -- IGMP multicast information
/proc/net/unix -- Unix domain socket information
/proc/net/ipx -- IPX socket information
/proc/net/ax25 -- AX25 socket information
/proc/net/appletalk -- DDP (appletalk) socket information
/proc/net/nr -- NET/ROM socket information
/proc/net/route -- IP routing information
/proc/net/ax25_route -- AX25 routing information
/proc/net/ipx_route -- IPX routing information
/proc/net/nr_nodes -- NET/ROM nodelist
/proc/net/nr_neigh -- NET/ROM neighbours
/proc/net/ip_masquerade -- masqueraded connections
/proc/net/snmp -- statistics
SEE ALSO
route(8), ifconfig(8), ipchains(8), iptables(8), proc(5)BUGS
Occasionally strange information may appear if a socket changes as it is viewed. This is unlikely to occur.AUTHORS
The netstat user interface was written by Fred Baumgarten <dc6iq@insu1.etec.uni-karlsruhe.de> the man page basically by Matt Welsh <mdw@tc.cornell.edu>. It was updated by Alan Cox <Alan.Cox@linux.org> but could do with a bit more work. It was updated again by Tuan Hoang <tqhoang@bigfoot.com>. The man page and the command included in the net-tools package is totally rewritten by Bernd Eckenfels <ecki@linux.de>.LINUX网络性能之管理工具三剑客
本文是介绍管理Linux系统网络性能技巧的文章,主要介绍了route、netstat、tcpdump三种网络管理测试工具的使用方法及其可实现的功能。
route
在配置网络时,要为机器指定接收数据包时该包要经过的路径。在Linux系统中,提供一个命令route,这个命令可以为ifconfig命令配置的网卡设置静态路由。这种设置工作通常在/etc/rc.d/rc.inet1中引入,在系统引导时进行。
我们通过几个例子来说明如何使用route命令:
route add -net 127.0.0.0
这个命令将向路由表中添加一个指定地址或者网络的路由。注意此时网络为A类地址,掩码被设置为255.0.0.0,这个新添加的条目被连接到lo设备上。
route add -net xxx.xxx.xxx.xxx netmask 255.255.255.0 dev eth0
这个命令为IP地址为xxx.xxx.xxx.xxx的主机增加一个路由,它的网络掩码被设置为255.255.255.0。
route del -net xxx.xxx.xxx.xxx
此命令将删除xxx.xxx.xxx.xxx这个网络的路由。
使用route命令还可以很方便地对整个网络的路由信息进行管理,其输出结果是网络的路由表。如下所示:
-----------------------------------------------------------------
[root@lee /root]#route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.10.8.224 * 255.255.255.255 UH 0 0 0 eth0
10.10.8.0 * 255.255.255.0 U 0 0 0 eth0
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default dgc8.njupt.edu 0.0.0.0 UG 0 0 0 eth0
default dgc8.njupt.edu 0.0.0.0 UG 1 0 0 eth0
[root@lee /root]#
-----------------------------------------------------------------
输出结果中各个字段的含义是:
·Destination表示路由的目标IP地址。
·Gateway表示网关使用的主机名或者是IP地址。上面输出的"*"表示没有网关。
·Genmask表示路由的网络掩码。在把它与路由的目标地址进行比较之前,内核通过Genmask和数据包的IP地址进行按位"与"操作来设置路由。
·Flags是表示路由的标志。可用的标志及其意义是:U表示路由在启动,H表示target是一台主机,G表示使用网关,R表示对动态路由进行复位设置;D表示动态安装路由,M表示修改路由,!表示拒绝路由。
·Metric表示路由的单位开销量。
·Ref表示依赖本路由现状的其它路由数目。
·Use表示路由表条目被使用的数目。
·Iface表示路由所发送的包的目的网络。
通过查看这些输出信息,我们就可以方便地管理网络的路由表了。
netstat
netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。在计算机上执行netstat后,其输出结果如下所示:
-----------------------------------------------------------------
[root@lee /root]#netstat
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags Types State I-Node Path
Unix 5 [ ] DGRAM 460 /dev/log
Unix 0 [ ] STREAM CONNECTED 173 @00000014
Unix 0 [ ] DGRAM 662
Unix 0 [ ] DGRAM 631
Unix 0 [ ] DGRAM 544
Unix 0 [ ] DGRAM 484
Unix 0 [ ] DGRAM 470
[root@lee /root]#
-----------------------------------------------------------------
从整体上看,netstat的输出结果可以分为两个部分:第一部分:是Active Internet connections,称为有源
TCP连接,在上面的输出结果中,这一部分没有内容,表示暂时还没有TCP连接。第二部分:是Active UNIX domain sockets,称为有源Unix域套接口。输出结果显示的是Unix域套接口的连接情况:
·Proto显示连接使用的协议。
·RefCnt表示连接到本套接口上的进程号。
·Types显示套接口的类型。
·State显示套接口当前的状态。
·Path表示连接到套接口的其它进程使用的路径名。
可以用netstat -a来查看所有套接字的状态,这在您调试网络程序的时候是非常有用的。netstat
-r将显示路由表的内容,一般还要同时指定"-n"选项,这样可以得到数字格式的地址,也可显示默认路由器的IP地址。使用netstat
-i则将显示所有的网络接口信息。使用netstat还可以获得当前的网络状态以及网络的拓扑结构,这在实际中是非常有用的。
tcpdump
tcpdump命令用于监视TCP/IP连接并直接读取数据链路层的数据包头。您可以指定哪些数据包被监视、哪些控制要显示格式。例如我们要监视所有Ethernet上来往的通信,执行下述命令:
tcpdump -i eth0
即使是在一个相对平静的网络上,也有很多的通信,所以我们可能只需要得到我们感兴趣的那些数据包的信息。在一般情况下,TCP/IP栈只为本地主机接
收入站的数据包绑定同时忽略网络上的其它计算机编址(除非您使用的是一台路由器)。当运行tcpdump命令时,它会将TCP/IP栈设置为
promiscuous模式。该模式可接收所有的数据包并使其有效显示。如果我们关心的只是我们本地主机的通信情况,一种方法是使用“-p”参数禁止
promiscuous模式,还有一种方法就是指定主机名:
tcpdump -i eth0 host hostname
此时,系统将只对名为hostname的主机的通信数据包进行监视。主机名可以是本地主机,也可以是网络上的任何一台计算机。下面的命令可以读取主机hostname发送的所有数据:
tcpdump -i eth0 src host hostname
下面的命令可以监视所有送到主机hostname的数据包:
tcpdump -i eth0 dst host hostname
我们还可以监视通过指定网关的数据包:
tcpdump -i eth0 gateway Gatewayname
如果你还想监视编址到指定端口的TCP或UDP数据包,那么执行以下命令:
tcpdump -i eth0 host hostname and port 80
该命令将显示从每个数据包传出的头和来自主机hostname对端口80的编址。端口80是系统默认的HTTP服务端口号。如果我们只需要列出送到80端口的数据包,用dst port;如果我们只希望看到返回80端口的数据包,用src port。
PL/SQL单行函数和组函数详解
函数是一种有零个或多个参数并且有一个返回值的程序。在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类:
单行函数
组函数
本文将讨论如何利用单行函数以及使用规则。
SQL中的单行函数
SQL和PL/SQL中自带很多类型的函数,有字符、数字、日期、转换、和混合型等多种函数用于处理单行数据,因此这些都可被统称为单行函数。这些函数
均可用于SELECT,WHERE、ORDER BY等子句中,例如下面的例子中就包含了TO_CHAR,UPPER,SOUNDEX等单行函数。
| SELECT ename,TO_CHAR(hiredate,'day,DD-Mon-YYYY') FROM emp Where UPPER(ename) Like 'AL%' ORDER BY SOUNDEX(ename) |
单行函数也可以在其他语句中使用,如update的SET子句,INSERT的VALUES子句,DELET的WHERE子句,认证考试特别注意在SELECT语句中使用这些函数,所以我们的注意力也集中在SELECT语句中。
NULL和单行函数
在如何理解NULL上开始是很困难的,就算是一个很有经验的人依然对此感到困惑。NULL值表示一个未知数据或者一个空值,算术操作符的任何一个操作数 为NULL值,结果均为提个NULL值,这个规则也适合很多函数,只有CONCAT,DECODE,DUMP,NVL,REPLACE在调用了NULL参 数时能够返回非NULL值。在这些中NVL函数时最重要的,因为他能直接处理NULL值,NVL有两个参数:NVL(x1,x2),x1和x2都式表达 式,当x1为null时返回X2,否则返回x1。
下面我们看看emp数据表它包含了薪水、奖金两项,需要计算总的补偿
| column name emp_id salary bonus key type pk nulls/unique nn,u nn fk table datatype number number number length 11.2 11.2 |
不是简单的将薪水和奖金加起来就可以了,如果某一行是null值那么结果就将是null,比如下面的例子:
| update emp set salary=(salary+bonus)*1.1 |
这个语句中,雇员的工资和奖金都将更新为一个新的值,但是如果没有奖金,即 salary + null,那么就会得出错误的结论,这个时候就要使用nvl函数来排除null值的影响。
所以正确的语句是:
| update emp set salary=(salary+nvl(bonus,0)*1.1 |
单行字符串函数
单行字符串函数用于操作字符串数据,他们大多数有一个或多个参数,其中绝大多数返回字符串
ASCII(
c1是一字符串,返回c1第一个字母的ASCII码,他的逆函数是CHR()
| SELECT ASCII('A') BIG_A,ASCII('z') BIG_z FROM emp BIG_A BIG_z 65 122 |
CHR(<i>)[NCHAR_CS]
i是一个数字,函数返回十进制表示的字符
| select CHR(65),CHR(122),CHR(223) FROM emp CHR65 CHR122 CHR223 A z B |
CONCAT(
c1,c2均为字符串,函数将c2连接到c1的后面,如果c1为null,将返回c2.如果c2为null,则返回c1,如果c1、c2都为null,则返回null。他和操作符||返回的结果相同
| select concat('slobo ','Svoboda') username from dual username slobo Syoboda |
INITCAP(
c1为一字符串。函数将每个单词的第一个字母大写其它字母小写返回。单词由空格,控制字符,标点符号限制。
| select INITCAP('veni,vedi,vici') Ceasar from dual Ceasar Veni,Vedi,Vici |
INSTR(
c1,c2均为字符串,i,j为整数。函数返回c2在c1中第j次出现的位置,搜索从c1的第i个字符开始。当没有发现需要的字符时返回0,如果i为负数,那么搜索将从右到左进行,但是位置的计算还是从左到右,i和j的缺省值为1.
| select INSTR('Mississippi','i',3,3) from dual INSTR('MISSISSIPPI','I',3,3) 11 select INSTR('Mississippi','i',-2,3) from dual INSTR('MISSISSIPPI','I',3,3) 2 |
INSTRB(
与INSTR()函数一样,只是他返回的是字节,对于单字节INSTRB()等于INSTR()
LENGTH(
c1为字符串,返回c1的长度,如果c1为null,那么将返回null值。
| select LENGTH('Ipso Facto') ergo from dual ergo 10 |
LENGTHb(
与LENGTH()一样,返回字节。
lower(
返回c的小写字符,经常出现在where子串中
| select LOWER(colorname) from itemdetail WHERE LOWER(colorname) LIKE '%white%' COLORNAME Winterwhite |
LPAD(
c1,c2均为字符串,i为整数。在c1的左侧用c2字符串补足致长度i,可多次重复,如果i小于c1的长度,那么只返回i那么长的c1字符,其他的将被截去。c2的缺省值为单空格,参见RPAD。
| select LPAD(answer,7,'') padded,answer unpadded from question; PADDED UNPADDED Yes Yes NO NO Maybe maybe |
LTRIM(
把c1中最左边的字符去掉,使其第一个字符不在c2中,如果没有c2,那么c1就不会改变。
| select LTRIM('Mississippi','Mis') from dual LTR ppi |
RPAD(
在c1的右侧用c2字符串补足致长度i,可多次重复,如果i小于c1的长度,那么只返回i那么长的c1字符,其他的将被截去。c2的缺省值为单空格,其他与LPAD相似
RTRIM(
把c1中最右边的字符去掉,使其第后一个字符不在c2中,如果没有c2,那么c1就不会改变。
REPLACE(
c1,c2,c3都是字符串,函数用c3代替出现在c1中的c2后返回。
| select REPLACE('uptown','up','down') from dual REPLACE downtown |
STBSTR(
c1为一字符串,i,j为整数,从c1的第i位开始返回长度为j的子字符串,如果j为空,则直到串的尾部。
| select SUBSTR('Message',1,4) from dual SUBS Mess |
SUBSTRB(
与SUBSTR大致相同,只是I,J是以字节计算。
SOUNDEX(
返回与c1发音相似的词
| select SOUNDEX('dawes') Dawes SOUNDEX('daws') Daws, SOUNDEX('dawson') from dual Dawes Daws Dawson D200 D200 D250 |
TRANSLATE(
将c1中与c2相同的字符以c3代替
| select TRANSLATE('fumble','uf','ar') test from dual TEXT ramble |
TRIM([[
将c3串中的第一个,最后一个,或者都删除。
| select TRIM(' space padded ') trim from dual TRIM space padded |
UPPER(
返回c1的大写,常出现where子串中
| select name from dual where UPPER(name) LIKE 'KI%' NAME KING |
单行数字函数
单行数字函数操作数字数据,执行数学和算术运算。所有函数都有数字参数并返回数字值。所有三角函数的操作数和值都是弧度而不是角度,oracle没有提供内建的弧度和角度的转换函数。
ABS(
返回n的绝对值
ACOS(
反余玄函数,返回-1到1之间的数。n表示弧度
| select ACOS(-1) pi,ACOS(1) ZERO FROM dual PI ZERO 3.14159265 0 |
ASIN(
反正玄函数,返回-1到1,n表示弧度
ATAN(
反正切函数,返回n的反正切值,n表示弧度。
CEIL(
返回大于或等于n的最小整数。
COS(
返回n的余玄值,n为弧度
COSH(
返回n的双曲余玄值,n 为数字。
| select COSH(<1.4>) FROM dual COSH(1.4) 2.15089847 |
EXP(
返回e的n次幂,e=2.71828183.
FLOOR(
返回小于等于N的最大整数。
LN(
返回N的自然对数,N必须大于0
LOG(
返回以n1为底n2的对数
MOD(
返回n1除以n2的余数,
POWER(
返回n1的n2次方
ROUND(
返回舍入小数点右边n2位的n1的值,n2的缺省值为0,这回将小数点最接近的整数,如果n2为负数就舍入到小数点左边相应的位上,n2必须是整数。
| select ROUND(12345,-2),ROUND(12345.54321,2) FROM dual ROUND(12345,-2) ROUND(12345.54321,2) 12300 12345.54 |
SIGN(
如果n为负数,返回-1,如果n为正数,返回1,如果n=0返回0.
SIN(
返回n的正玄值,n为弧度。
SINH(
返回n的双曲正玄值,n为弧度。
SQRT(
返回n的平方根,n为弧度
TAN(
返回n的正切值,n为弧度
TANH(
返回n的双曲正切值,n为弧度
TRUNC(
返回截尾到n2位小数的n1的值,n2缺省设置为0,当n2为缺省设置时会将n1截尾为整数,如果n2为负值,就截尾在小数点左边相应的位上。
单行日期函数
单行日期函数操作DATA数据类型,绝大多数都有DATA数据类型的参数,绝大多数返回的也是DATA数据类型的值。
ADD_MONTHS(
返回日期d加上i个月后的结果。i可以使任意整数。如果i是一个小数,那么数据库将隐式的他转换成整数,将会截去小数点后面的部分。
LAST_DAY(
函数返回包含日期d的月份的最后一天
MONTHS_BETWEEN(
返回d1和d2之间月的数目,如果d1和d2的日的日期都相同,或者都使该月的最后一天,那么将返回一个整数,否则会返回的结果将包含一个分数。
NEW_TIME(
d1是一个日期数据类型,当时区tz1中的日期和时间是d时,返回时区tz2中的日期和时间。tz1和tz2时字符串。
NEXT_DAY(
返回日期d后由dow给出的条件的第一天,dow使用当前会话中给出的语言指定了一周中的某一天,返回的时间分量与d的时间分量相同。
| select NEXT_DAY('01-Jan-2000','Monday') "1st Monday",NEXT_DAY('01-Nov-2004','Tuesday')+7 "2nd Tuesday") from dual; 1st Monday 2nd Tuesday 03-Jan-2000 09-Nov-2004 |
ROUND(
将日期d按照fmt指定的格式舍入,fmt为字符串。
SYADATE
函数没有参数,返回当前日期和时间。
TRUNC(
返回由fmt指定的单位的日期d.
单行转换函数
单行转换函数用于操作多数据类型,在数据类型之间进行转换。
CHARTORWID(
c 使一个字符串,函数将c转换为RWID数据类型。
| SELECT test_id from test_case where rowid=CHARTORWID('AAAA0SAACAAAALiAAA') |
CONVERT(
c尾字符串,dset、sset是两个字符集,函数将字符串c由sset字符集转换为dset字符集,sset的缺省设置为数据库的字符集。
HEXTORAW(
x为16进制的字符串,函数将16进制的x转换为RAW数据类型。
RAWTOHEX(
x是RAW数据类型字符串,函数将RAW数据类转换为16进制的数据类型。
ROWIDTOCHAR(
函数将ROWID数据类型转换为CHAR数据类型。
TO_CHAR(
x是一个data或number数据类型,函数将x转换成fmt指定格式的char数据类型,如果x为日期nlsparm= NLS_DATE_LANGUAGE 控制返回的月份和日份所使用的语言。如果x为数字nlsparm=NLS_NUMERIC_CHARACTERS 用来指定小数位和千分位的分隔符,以及货币符号。
| NLS_NUMERIC_CHARACTERS ="dg", NLS_CURRENCY="string" |
TO_DATE(
c表示字符串,fmt表示一种特殊格式的字符串。返回按照fmt格式显示的c,nlsparm表示使用的语言。函数将字符串c转换成date数据类型。
TO_MULTI_BYTE(
c表示一个字符串,函数将c的担子截字符转换成多字节字符。
TO_NUMBER(
c表示字符串,fmt表示一个特殊格式的字符串,函数返回值按照fmt指定的格式显示。nlsparm表示语言,函数将返回c代表的数字。
TO_SINGLE_BYTE(
将字符串c中得多字节字符转化成等价的单字节字符。该函数仅当数据库字符集同时包含单字节和多字节字符时才使用
其它单行函数
BFILENAME( ,
dir是一个directory类型的对象,file为一文件名。函数返回一个空的BFILE位置值指示符,函数用于初始化BFILE变量或者是BFILE列。
DECODE(
x是一个表达式,m1是一个匹配表达式,x与m1比较,如果m1等于x,那么返回r1,否则,x与m2比较,依次类推m3,m4,m5....直到有返回结果。
DUMP(
x是一个表达式或字符,fmt表示8进制、10进制、16进制、或则单字符。函数返回包含了有关x的内部表示信息的VARCHAR2类型的值。如果指定了n1,n2那么从n1开始的长度为n2的字节将被返回。
EMPTY_BLOB()
该函数没有参数,函数返回 一个空的BLOB位置指示符。函数用于初始化一个BLOB变量或BLOB列。
EMPTY_CLOB()
该函数没有参数,函数返回 一个空的CLOB位置指示符。函数用于初始化一个CLOB变量或CLOB列。
GREATEST(
exp_list是一列表达式,返回其中最大的表达式,每个表达式都被隐含的转换第一个表达式的数据类型,如果第一个表达式是字符串数据类型中的任何一个,那么返回的结果是varchar2数据类型, 同时使用的比较是非填充空格类型的比较。
LEAST(
exp_list是一列表达式,返回其中最小的表达式,每个表达式都被隐含的转换第一个表达式的数据类型,如果第一个表达式是字符串数据类型中的任何一个,将返回的结果是varchar2数据类型, 同时使用的比较是非填充空格类型的比较。
UID
该函数没有参数,返回唯一标示当前数据库用户的整数。
USER
返回当前用户的用户名
USERENV(
基于opt返回包含当前会话信息。opt的可选值为:
ISDBA 会话中SYSDBA脚色响应,返回TRUE
SESSIONID 返回审计会话标示符
ENTRYID 返回可用的审计项标示符
INSTANCE 在会话连接后,返回实例标示符。该值只用于运行Parallel 服务器并且有 多个实例的情况下使用。
LANGUAGE 返回语言、地域、数据库设置的字符集。
LANG 返回语言名称的ISO缩写。
TERMINAL 为当前会话使用的终端或计算机返回操作系统的标示符。
VSIZE(
x是一个表达式。返回x内部表示的字节数。
SQL中的组函数
组函数也叫集合函数,返回基于多个行的单一结果,行的准确数量无法确定,除非查询被执行并且所有的结果都被包含在内。与单行函数不同的是,在解析时所有的行都是已知的。由于这种差别使组函数与单行函数有在要求和行为上有微小的差异.
组(多行)函数
与单行函数相比,oracle提供了丰富的基于组的,多行的函数。这些函数可以在select或select的having子句中使用,当用于select子串时常常都和GROUP BY一起使用。
AVG([{DISYINCT|ALL}]
返回数值的平均值。缺省设置为ALL.
| SELECT AVG(sal),AVG(ALL sal),AVG(DISTINCT sal) FROM scott.emp AVG(SAL) AVG(ALL SAL) AVG(DISTINCT SAL) 1877.94118 1877.94118 1916.071413 |
COUNT({*|DISTINCT|ALL}
返回查询中行的数目,缺省设置是ALL,*表示返回所有的行。
MAX([{DISTINCT|ALL}]
返回选择列表项目的最大值,如果x是字符串数据类型,他返回一个VARCHAR2数据类型,如果X是一个DATA数据类型,返回一个日期,如果X是numeric数据类型,返回一个数字。注意distinct和all不起作用,应为最大值与这两种设置是相同的。
MIN([{DISTINCT|ALL}]
返回选择列表项目的最小值。
STDDEV([{DISTINCT|ALL}]
返回选者的列表项目的标准差,所谓标准差是方差的平方根。
SUM([{DISTINCT|ALL}]
返回选择列表项目的数值的总和。
VARIANCE([{DISTINCT|ALL}]
返回选择列表项目的统计方差。
用GROUP BY给数据分组
正如题目暗示的那样组函数就是操作那些已经分好组的数据,我们告诉数据库用GROUP BY怎样给数据分组或者分类,当我们在SELECT语句的SELECT子句中使用组函数时,我们必须把为分组或非常数列放置在GROUP BY子句中,如果没有用group by进行专门处理,那么缺省的分类是将整个结果设为一类。
| select stat,counter(*) zip_count from zip_codes GROUP BY state; ST ZIP_COUNT -- --------- AK 360 AL 1212 AR 1309 AZ 768 CA 3982 |
在这个例子中,我们用state字段分类;如果我们要将结果按照zip_codes排序,可以用ORDER BY语句,ORDER BY子句可以使用列或组函数。
| select stat,counter(*) zip_count from zip_codes GROUP BY state ORDER BY COUNT(*) DESC; ST COUNT(*) -- -------- NY 4312 PA 4297 TX 4123 CA 3982 |
用HAVING子句限制分组数据
现在你已经知道了在查询的SELECT语句和ORDER BY子句中使用主函数,组函数只能用于两个子串中,组函数不能用于WHERE子串中,例如下面的查询是错误的 :
|
错误 |
这个语句中数据库不知道SUM()是什么,当我们需要指示数据库对行分组,然后限制分组后的行的输出时,正确的方法是使用HAVING语句:
| SELECT sales_clerk,SUN(sale_amount) FROM gross_sales WHERE sales_dept='OUTSIDE' GROUP BY sales_clerk HAVING SUM(sale_amount)>10000; |
嵌套函数
函数可以嵌套。一个函数的输出可以是另一个函数的输入。操作数有一个可继承的执行过程。但函数的优先权只是基于位置,函数遵循由内到外,由左到右的原则。嵌套技术一般用于象DECODE这样的能被用于逻辑判断语句IF....THEN...ELSE的函数。
嵌套函数可以包括在组函数中嵌套单行函数,或者组函数嵌套入单行函数或组函数中。比如下面的例子:
SELECT deptno, GREATEST(COUNT(DISTINCT job),COUNT(DISTINCT mgr) cnt,
COUNT(DISTINCT job) jobs,
COUNT(DISTINCT mgr) mgrs
FROM emp
GROUP BY deptno;
DEPTNO CNT JOBS MGRS
------ --- ---- ----
10 4 4 2
20 4 3 4
30 3 3 2
使用crypt验证密码(DES)
Source code
/*
*Created by alexclark
*Modify time: 2005-09-07
*Filename: crypt.cpp
*
*compile by
*g++ -o mycrypt crypt.cpp -lcrypt
*/
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
int main()
{
string key = "FuMI6cXY";
string salt = "GB";
while(1){
#if 1
cout <<"Please input key and salt for crypt:nkey:";
cin >> key;
string exit = "exit";
if(exit == key)
break;
cout <<"salt:";
cin >> salt;
if(exit == salt)
break;
#endif
string passwd = crypt(key.c_str(), salt.c_str());
cout <<"Input Key:" <<key <<"nInput Salt:" << salt << "ncrypt Passwd:" << passwd <<endl;
}
}
Linux / Unix Command: crypt
NAME
crypt - password and data encryptionSYNOPSIS
#define _XOPEN_SOURCE#include <unistd.h>
char *crypt(const char *key, const char *salt);
DESCRIPTION
crypt is the password encryption function. It is based on the Data Encryption Standard algorithm with variations intended (among other things) to discourage use of hardware implementations of a key search.key is a user's typed password.
salt is a two-character string chosen from the set [a-zA-Z0-9./]. This string is used to perturb the algorithm in one of 4096 different ways.
By taking the lowest 7 bits of each of the first eight characters of the key, a 56-bit key is obtained. This 56-bit key is used to encrypt repeatedly a constant string (usually a string consisting of all zeros). The returned value points to the encrypted password, a series of 13 printable ASCII characters (the first two characters represent the salt itself). The return value points to static data whose content is overwritten by each call.
Warning: The key space consists of 2**56 equal 7.2e16 possible values. Exhaustive searches of this key space are possible using massively parallel computers. Software, such as crack(1), is available which will search the portion of this key space that is generally used by humans for passwords. Hence, password selection should, at minimum, avoid common words and names. The use of a passwd(1) program that checks for crackable passwords during the selection process is recommended.
The DES algorithm itself has a few quirks which make the use of the crypt(3) interface a very poor choice for anything other than password authentication. If you are planning on using the crypt(3) interface for a cryptography project, don't do it: get a good book on encryption and one of the widely available DES libraries.
RETURN VALUE
A pointer to the encrypted password is returned. On error, NULL is returned.ERRORS
- ENOSYS
- The crypt function was not implemented, probably because of U.S.A. export restrictions.
GNU EXTENSION
The glibc2 version of this function has the following additional features. If salt is a character string starting with the three characters "$1$" followed by at most eight characters, and optionally terminated by "$", then instead of using the DES machine, the glibc crypt function uses an MD5-based algorithm, and outputs up to 34 bytes, namely "$1$论RPG游戏的策划
作者:月光流星雨 来源:月光流星雨
第一章:概述
RPG游戏即角色扮演游戏(Role Personate Game),玩家需要扮演游戏中的一位或者多位角色,在虚拟的世界中进行冒险。首先,让我们先来认识RPG游戏,从表现形式和玩法上,它可以分为以下几种:
RPG:普通RPG游戏,有专门的战斗画面。战斗画面用不同的视角来表现:采用斜45度视角,如台湾《仙剑奇侠传》;采用平行90度视角的,如日本《太空战士》系列采用主观视角,如日本《勇者斗恶龙》系列。
A·RPG:又称动作(Act)RPG,这种RPG没有专门的战斗画面,也就是说随时可以挥刀挥剑。如日本《不可思议之谜宫·风来的西林》、日本《天地创造》等等,也有主观视角的A·RPG,如美《魔法门》系列。
S·RPG:又称模拟(Simulation)RPG,这种RPG在战斗时是采用SLG式的。也就是一种可控制一组角色,可移动的战斗方式,如日本《光明与力量II》。
AVG·RPG:即解谜冒险游戏与角色扮演游戏的组合,这类游戏将解谜冒险放在很重要的部分。如日本CAPCOM公司《BIO HAZARD》(《生化危机》)。
T·RPG:是TAB(桌面类游戏)与RPG的组合,它的普通模式在TAB环境下运行,英业达出品的《虚拟人生》就属此例
F·RPG:是FGT(格斗类游戏)与RPG的组合,它的战斗方式采用的是格斗类。
其它RPG:是除上述外,其它类型的游戏与RPG的组合,但并不是很多见。
除了表现形式,其次就是游戏背景,从背景上可分往往可以分出以下几个派别:
欧洲中世纪:这类游戏的背景常发生在欧洲中世纪的不知名国家(多为撰论),在那个年代,白袍罩头的古魔法师、会喷火的凶龙、美丽而神秘的巫女、英武的长矛骑士、古老的城堡做为主要代表,无不散发浓郁的神话色彩,吸引游戏制作者纷纷以它为题材做了大量的这方面游戏。在后期即使有人试图突破这种氛围,也很少可以跳出魔法师、大巫师、骑士这类内容。所以说,欧洲中世纪类游戏在游戏内容和风格上起着举足轻重的作用。
日本风格:来源于日本,多是以日本民间传说或民族英雄为背景。在悠扬的日本风格音乐伴奏下,勇士们拿着日本战刀,开始自己的冒险。武士、忍者、忍术各显风采,八岐大蛇、草雉、雨村刀也纷纷出台,是日本特有风格的写照。
科幻宇宙:情节背景通常发生在不知名的星球,在这样的游戏中,枪、炮、火箭、激光剑(枪)、粒子武器,代替了魔法和刀剑;时空穿梭机代替了穿越时空的魔法;飞船或是巨大的变形机器人成为基本交通工具和武器;外星生物取代了传统的妖魔鬼怪;小型机器人代替了精灵;主人公要得到了多是能源器,而不再为寻找魔法书而奔波。无尽的星空、变幻的星云是美丽的大舞台,游戏制作者们在这个背景上写下了动人的故事。
中国武侠:起源于台湾,一款《仙剑奇侠传》一夜间高登榜首,久居不下。其主要原因就是它开创了一种新的风格--这就是中国武侠风格。带有中国武术的招式,中国色彩的法术,武术门派,带您进入血雨腥风、打打杀杀的江湖。
其它:多是上述两种或两种以上的组合。
写到这里,笔者发现,居然有很多的背景题材从未被使用,如:
中国神话:其实不可以小看中国特有的神话题材《山海经》、《西游记》、《搜神记》、《叙异经》、《神仙传》……这么多的题材,难道不可以做成游戏吗?我们的神话里也一样有具有大神通、大智慧的高僧、道士、隐士;一样有金、木、水、火、土五行八卦九宫魔法;也一样有神奇的飞车、木人、木牛流马;一样有龙渊、巨阙、绕指柔这样的名刀名剑;一样有大人国、女儿国、鬼国这样神奇国家;也一样有刑天、魑魅魍魉、穷奇、旱魃这样的怪物;一样有后弈这样传说中不朽的英雄。这些为什么不把它们做到游戏里,让世界了解我们的文化呢?
现代战争:《抗日烽火》、《地雷战》这些SLG游戏纷纷出台,欧美也有《二战特种兵》这样记实的游戏。如果一款描写抗日时期地下工作者的游戏,接头、搜集情报、潜入敌人内部(换衣服)、炸铁路、破坏敌人司令部。可以说将RPG游戏内含一样表达的淋漓尽至。
现代生活:描写现代生活的游戏实在是不多,除了SLG的一些如《模拟城市》、《主题医院》、《主题公园》这样的模拟游戏;就是《同级生》、《心跳纪念品》这类AVG解谜游戏;要不就是《D之食卓》、《第七访客》这类AVG恐怖氛围解谜游戏,而以现代人生活为背景的RPG、AVG游戏几乎是空白,正有待于游戏制作涉足这个题材。
说到了背景,就不能不说说情节内容了,现在的RPG游戏,情节内容越来越丰富多彩了。总体的跟据内容来分分类,似乎是不可能的。但总的来说,还是有一定的轨迹可以追溯的,如:
勇者斗恶龙类:这类情节往往从恶魔的复活说起,恶魔(恶龙、厉鬼……及一切相关的邪恶魔物)被无意中放了出来(解开了封印、放出了禁锢……),它的能力是非乎寻常的大,它的出现可以导致世界的毁灭(永远的黑暗、世人的苦难……)。这时,年轻的勇士(剑客、骑士……)背负着神圣的宿命(神的指示、师傅的命令、亡父的遗命、为父母报仇……),开始的艰难的征途。他的身边往往有一位美丽的女孩子(青梅竹马、暗恋他的女子、无意中同行最后会爱上他的女子……),途中,他需要找全一些装备(勇士之剑、宿命之珠、龙珠、神的利刃……),最后来到了恶魔的世界(山洞、龙宫、诡异的世界……),开始了一场殊死的战斗,这场战斗往往非常非常惨烈,最后恶魔终于被战败了(勇士与恶魔同归于尽、女子为救勇士悲剧的牺牲了、大团圆救回了公主……)。
身事之谜类:不知自己身事的男孩(女孩)为是解开这个谜开始了冒险。途中,遇到心爱的人(心爱主角的人),一起经历了种种离奇(有趣……)的事,最终知道了自己的身事(神之子、魔之子、普通人……)。
寻找失散亲人类:为了找到失散的亲人(父亲、母亲、姐姐、妹妹、恋人、妻子、邻居家的小女孩……)开始了冒险,经历了种种离奇(有趣……)的事,最终找到了亲人(或是没找到……^_^)。
寻找宝物类:无意中出现的宝物(宝杯、宝珠、宝瓶、宝剑、财宝、龙珠),传说得到它就会有不可思议的事发生(主宰世界、无敌江湖、青春永驻、长生不死、富甲天下、实现三个愿望……),人们为了各自的愿望纷纷向宝物出现地出发。其中一个邪恶的势力(邪恶的集团、帮派、组织)的首脑也向宝物伸出了魔爪。主角为了粉碎坏人的阴谋,与之周旋、斗争,最终主角获得了胜利(或是玉石俱焚)。
开创天地类:可以说这类情节是一个另类,至今笔者也仅见到过一例《天地创造》。故事也很莫明奇妙,随着主角的冒险,创造了天地万物。主角那怕一个小小的动作,对人类都是可怕的改变。
时空穿梭类:也是一种比较独特的类型,特点是主角可以穿梭于时空之中,穿梭时空的玩点就在于过去、现在、未来的必然性。当改变过去时,会影响到现在和未来,甚至为了自己保护自己的祖先,从而制作出种种玩点。
除了上述几种,其它的还有很多,只是不成系列而已。
各游戏公司、厂商为了提高自己的产品的销量,在制作时可谓绞尽脑汁。玩家在游戏过程中,可以领略到种种非常吸引人的东西,试述如下:
加入小游戏:在大的RPG过程中,加入小游戏,在SQUARE公司《FINAL FANTASY VII》(《太空战士VII》)中,玩家控制角色进入娱乐城时,用钱买代币,不但可以做过山车疯狂一把,还可以在游戏机前一显身手,笔者就曾在摩托车游戏中赚了大量的代币来换取非常不错的道具。除此之外,在其它游戏中还有用角子老虎机赚代币换钱的,用纸牌、骰子来赚钱都不罕见。
与游戏无直接关系的角色:随着情节的发展,或是隐藏情节的完成,在一些游戏中,会出现与游戏无直接关系的角色,在日本A·RPG《天地创造》中,玩家可以到类似于日本形状的小岛上,直接参观这家游戏制作公司。在另一款传统RPG游戏中,出现了春丽(《街霸》中女主角之一)教百裂脚的情节,令人啼笑皆非。
增加玩家对直接参与游戏的满足感:有不少RPG游戏主角的名字和配角的名字是可以由玩家自己来设定的。除了游戏角色的名字之外,还有生日,星座、年龄……,这样在游戏过程中,游戏中角色(尤其是漂亮的女主角:))亲切的叫着玩家的名字时,对玩家来说的确是不小的满足。更有在情节上得到的名剑、开发出的商会都可以由玩家来自己命名,使玩家感觉玩得不是由游戏制作者设计的游戏,而是自己设身亲历的真实世界……
最后,在这里再说说,关于游戏的结构,一般的RPC游戏,都是单线式结构或者橄榄状结构,但也有树根状结构、树状结构和网状结构,让我们来看看
单线式结构游戏:这类游戏没有什么分支,故事结构往往比较紧凑。最典型的莫过于《仙侠奇侠传》,它按着策划的意思,一步步紧密的进行游戏的运程。可以看出它的结构图,可以是这样的:李逍遥起床(游戏初始化)--进厨房与婶婶交谈--送酒食给黑苗人(得到杏花酒)--在门口与酒剑仙交谈(使用杏花酒)-- 进厨房与婶婶交谈(得到金钱)--到小镇码头与渔夫交谈--走到村口(播动画)--回到婶婶的房间--出婶婶的房间遇到黑苗头领(得到破天锥)--???
游戏就是这样按步就班,完成一个条件,生成下一个条件,直到游戏最终结束。这类游戏的特点在于:
一. 制作简单:因为没有什么分支,所以在制作和调试时,都比较方便。但也正因为这个原因,故事情节上就格外的要求感人。
二. 再玩率低:因为游戏是这样单线索的发展,故玩一次和再玩一次,情节上没有什么不同,除了刻意怀旧或情节特别感人,很少玩家会在短时间内打很多遍。
橄榄状结构游戏:这类游戏总的来说,与单线式差不多,一个开头,一个结局。但不同的是,在游戏过程中,它存在一些分支,这些并不会影响到游戏的结局。这里可以举个例子,是智冠公司出的《金庸群侠传》就是一个典型,游戏中,玩家扮演的角色是一个现代游戏少年,进入到金庸武侠世界,需要找到14本书,才可以回到自己的世界。在这过程中,玩家可以自己决定先拿哪一本书,也可以决定选择谁做为自己的伙伴,甚至可以选择正邪两派的不同玩法(一些事件的解决方式,是否翻箱倒柜、是否与邪派中人为伍)。但游戏最终结果是一样的,也就是找到14本书,与十个高手大战一把。虽然正邪两种类型,但总的来说是一个结局(不同点仅仅在于十个高手不一样而已)。
这类游戏的特点在于:制作略微复杂、再玩率较高
树根状结构游戏:这类游戏可以顾名思义,象树根一样,一个开头,多个结局。游戏过程中出现了种种分支,将会影响到游戏的结局。毫无疑问,这种类型的游戏,往往最能吸引玩家。我最喜欢的游戏之一,是日本史克威尔出品SFC(超级任天堂)游戏《时空之钥》(亦名《时空之旅》、《时空穿梭机》),故事大致是讲一个现代的少年,与其伙伴掌握了穿越时空的能力,为了挽救世界将要崩坏的厄运,负起了改变历史的重任。事实上,游戏的结果无外是杀死最终的那个BOSS,但因为中间的一些情节分支,使游戏者可以以不同方式打出游戏结局,变化非常多。
这类游戏的特点在于:对策划逻辑上的要求非常的高,绝不是新手可以胜任的。但对于玩家来说,可玩性也是非常的高,可以使玩家不厌其烦的一遍又一遍的攻关,以欣赏不同的结局。
树状结构游戏:与树根状结构游戏相类似,可以想象结构象树一样,有多个开始,但万源归宗,只有一个结局。所谓多个开始,可以是不同的主角色,也可以主角色起始点和初期的经历的不同。象树一样,从上往下,经过多条分支,最后渐渐归向总结局。有一款史克威尔出的SFC游戏《浪漫沙加3》(亦名《浪漫魔界塔 3》)即是如此,玩家在初期可以选择不同的角色做为主角色。每一个角色都有属于自己的一套情节,一些分支情节是共享的,但不论选择谁为主角色,最终需要打的那个总BOSS,是不可避免的。
这类游戏的特点是:也是对策划要求较高,各角色或是各路线,其难度要达成平衡,绝不是一件容易的事。对玩家来说,也是可再玩率极高,都想以不同的身份,不同的路线来体验不同的感觉。
网状结构游戏:终于说到正题上来了,可以肯定,这种结构的RPG游戏将会是将来游戏的趋势,这种的概念是什么呢?这么说吧,象是一张网,玩家可以随意从任意的地方开始,也可以随意向任意的方向发展。假设这张网是无限大的,这款游戏也将是无限大的。有同志说了,"天啊,那这个游戏将要多大呀?将耗多少美术量呀?将耗多少程序呀?"呵,别急,听我说完呀。其实这根本不是问题,有没有玩过网络MUD呢?其实那就是多人版的网络RPG,只不过情节很单薄而已。什么意思呢?就是虚拟一套环境,这套环境可以多人共享,也就是支持网络。玩家需要做的事,就是在这套环境下,演绎自己的故事。更有甚者,可以因玩家不同的处事理念、不同的情节,来生成新的情节。可以想象,NPC与NPC之间,可以因其性格、性别等因素,自动结婚生子,自生自灭。当有一天,你无意中杀死了这个家庭中的老NPC,那个小NPC将会以杀死你做为最终的目地而四处寻找你。而这时,另一位玩家登录到本游戏中,也许他就将扮演这个小NPC的角色,开始四处找寻你。
也可以想象,你来到一个陌生的城市,你可以学习任何一种或多种技能,比如说医疗,当你学业有成时,可以开一家诊所。第一位来找你看病的,是一个NPC,也有可能是另一位玩家。你们就这样相识,最后发展到结婚,甚至生个强壮的儿子,到了一定时间,你的儿子就有可能由另一位玩家来扮演。
嗯,这种感觉是什么呢?就是一套真正接近到现实的虚拟社会。当然这个社会无所谓建立在什么时代,可以是中世纪、可以是古罗马、可以现代、也可以是未来,甚至是虚幻的神话背景。但重要的是这套规则的成熟,杀人者在一定概率上,会受到制裁;偷窃者也会在一定概率上被送到监狱;如何不轨的行为都会受到规则的惩罚,相反任何善事也会得到一定的报酬。玩家进入时,随机将他(她)安放在任意点上。玩家与NPC之间的距离和差异减小到看不出来的程度。
呵,思维有点天马行空了,两个多小时都沉溺在对未来游戏的憧憬中了。还是言归正传吧。
事实上,不论是玩家在玩RPG游戏时,还是游戏制作人在制作时,RPG所拥有因素无非是几点:场景、角色、道具、事件、对白、语音和音效、音乐、界面、规则、命名。下面我们分章针对这几个因素做一下说明:
第二章:场景
什么是场景呢?是指运行在游戏中的主控角色可以到达的场地。换句话说,也就是如果没有角色,游戏本身就是由很多单独的场景相连组成。
那么场景是做什么用的呢?OK,这么说吧,如果看过电影的人,一定知道电影的镜头的概念。比如在某甲家发生的一组镜头,某甲与某甲之妻发生了口角,某甲一怒之下出了门。这是一组镜头,现在需要继续拍摄某甲出门后的第二个地方所发生的事,如在楼道遇见某乙。那么在游戏中某甲的家是一个场景,出门后的楼道是一个场景,这两个场景相互连接。场景就是一个接一个舞台。同一件事运行在游戏中,如果两个场景没有连接。某甲和其妻发生完了口角,这时你控制某甲这个角色想要离开家这个场景,会出不去(呵,当然,不排除窗户的连接,但如果是十一层楼……),那么这个游戏就陷进了死角,成为永远玩不完,永远玩不通的游戏。
即使场景就是舞台,那么在布置这个舞台时,当然就要下一番功夫了。首先要控制氛围,搞清楚你要做的游戏是什么样的氛围。是富有浪漫色彩的,还是写实的?浪漫色彩的氛围,可是或多或少的加入一些夸张的因素;而写实的则力求接近于真实。是卡通Q版的,还是恐怖的?卡通Q版可以将场景设计的可爱爆笑;恐怖的则不易加过于明快的色调,使之阴暗。
布置时要根据具体场景和你设计时需要的效果,这正象拍摄一个电影镜头时需要布置摄影棚一样。如果你想表现一个世外仙境的话,奇花异草当然是少不了的。天空的背景可以是湛蓝,一条小溪潺潺而过,整体感觉是干净亮丽又有一丝深邃和神秘。OK,当你设计角色时,再加入一头梅花鹿和一个打坐的老神仙;佐以悠远的音乐,你的场景大概就设计的差不多了。
当然如果要想游戏精美,仅做到一个大概是不够的,民居墙上的一串干辣椒,门前一幅对联,正是这点点滴滴的小东西,构成一个场景的和谐。
那么一个场景是如何做成的呢?I will tell you, 首先你需要画一些材质,如果是室外就是一些草地、土地、路、石头、树、房屋等等;如果是室内则是一些桌椅、火炉、柜子、床这些家俱。用这些素材,在专门的编辑器中做处理,然后再搭建。搭建的时候就象是我们小时玩的积木,你可以按你的意愿把场景做成各种各样。
在搭制的时候,有的因素可以不去管它,象是生物角色(人、猫、狗、马厩里的马)、非生物角色(会动的喷泉、火、可以打开的箱子)、场景出口的链接都先不去考虑,先将静态的东西搭好。
OK,这时你就可以划出不可达区域了,利用你的场景编辑器,把房屋、树木、河水等你不愿意玩家到达的地方定义成不可达域。这样你的场景在走起来时,就会象你玩过其它游戏一样,有不可达的地方,达到仿真的效果。
最后一步,把这个场景存成固定的格式,一般情况C语言不支持8位以上的文件名,所以合理的命名是很重要的。
第三章:角色
什么是角色呢?在游戏制作过程中,角色所包含的内容很大,第一类是指游戏中人物。人物有两种,一种是你正在控制的人物,我们称之为主角;另一种是不可控制的角色,我们称之为NPC,它分为行走角色和站立角色。第二类是指游戏中带有动画属性的物体,如燃烧的火、喷水的喷泉等等。第三类是指空白的角色,也就是什么都没有的透明角色,是用来暂时阻挡“路”的。
它的总体分类方法是这样的:
人物角色:可控制的
不可控制的:行走
站立
物体角色
空白角色
先来说说游戏中的人物,根据你的剧本,设计好每一个人物可以说至关重要。就象拍摄电影,每一个人物都有他的职业、性格,职业性格又会影响到他的外型、服饰甚至武器。故此在设计人物时,一块小小的玉佩、一根小小的金钗都可以关键的地方起到画龙点睛的作用。
在具体设计时,每一个人物虚拟一段基本资料,这样无论绘画时还是在写对白时,都可以以此为依据。
如:
姓名:孟斐
性别:男 年龄:18岁
职业:剑客 流派:龙华剑派
武器:长剑
性格:心地善良、性格开朗,喜欢开开玩笑,吹吹牛。
简历:本是孤儿,父母不祥,自幼被龙华真人收养。从小学习龙华剑术,如今十八岁的他,剑术已有大成。此番龙华真人得知天地异变将要开始,便命他担负起拯救世界的重任。
外形设计:长发及肩,红色缎带束发,剑客装束,身背名剑"梅花血",剑长五尺三寸。
这样“孟斐”这个角色就设计的比较成熟了,根据他的性格,在写对白时,就可以适当的加入一些玩笑和吹牛的话。在写外形设计时,一个策划的心目中大概要有这个人物的构想,不用写的太详细,剩下的可以由美术人员来发挥。这是可以控制的角色,如果你的引擎支持多人组队的话,其它的主角都可以这样设计。
再说说NPC角色,这类角色不由你控制,大致分为行走角色和站立角色。行走角色是指角色可以在你指定的几个点上按路线不停的行动的角色,也包括一些动物(小猫、小狗什么的)。而站立角色相对美术的要求就简单一些,比如坐在地上的乞丐、卖菜的小贩。在设计NPC角色时,要注意的是搭配场景,在后宫出现的角色当然是皇妃、宫女,不可能是张屠夫、李财主吧?而什么角色站立、什么角色行走也根据实际情况来做安排,就以后宫为例:皇妃当然不可能走来走去,让她安祥的坐在皇座上比较好;宫女呢,除了侍立在旁的,就可以在回廊上加几个行走的。
嗯,再简单说说带有动画属性的物体,象是会喷水的喷泉、燃烧的火焰等等,在制作上,我们通常也把它们做成角色。这样的角色有以下的特点:
A.它们是物体角色而区分于一般场景上的不可达区域。这样你控制主角色击点到它们的旁边时,可引发一句话(如:“这是一个喷水的喷泉。”),或者得到道具(如:“你在喷泉边找到一枚钱币。”)
B.它们可以有动画或是可以消失。以一团燃烧的火为例,第一次你来到这个场景,使用火具,可以点燃燃烧物,这时这一团火焰就是物体角色;而当你下次来这个场景时,这团火焰可能就成了灰烬,当然,这就是另一个物体角色了。这时,你也许可以在灰烬中找到诸如“烤白薯”这样的道具;而你再下次来到这个场景时,也许连灰烬也看不见了,这就是所谓的角色消失了。
好,最后说一说空白角色,什么叫做空白角色呢?所谓空白角色就是将一块透明物用角色的方式放置在场景中,游戏者进入这个场景是看不见空白角色的。那么空白角色有什么作用呢?它的作用无外乎是两点,即:
阻挡:当在场景A中,没有完成一些情节,或是没有得到一些道具,是不可以去场景B的。可是玩家如果到了场景B的入口点时,怎么办呢?这时,这个入口点就需要放置一个空白角色,来告诉玩家,如“你没有拿到某某道具,是不可以进入这里的。”“你应该带着某某一起离开。”等等。当玩家的情节完成后,或是得到了某道具时,加一句此空白角色(当然是要命名的)消失,这样玩家就理所应当的可以通过了。
使用或是给予道具:记得在做《镜花缘》时,有一个钓鱼的情节。一座小桥上的一条区域做成了空白角色,玩家对着该空白角色使用渔具后,播放钓鱼的动画,然后得到鱼。这就是对空白角色使用和得到道具。
第四章:道具
接来这一章,我们来说说道具,所谓道具就是指在游戏过程中,使用或是装备的物品。道具大致上可以分为三种:使用类、装备类和情节类。
使用类:使用类的特点是用过后,就消失了的物品。它又分为食用型和投掷型两种。食用型是指在游戏过程中,可以食用,以增加某种指数提高的物品。一般来说也就是药品或是食品。象什么草药、金创药之类的,食用之后可以使受伤的体力得以恢复;人参、雪莲之类的吃了后,可以增加角色的一些数值(如灵力);大饼、油条之类的,吃了后绝对不再饿。:)投掷类道具是指在战场上使用的可投掷的物品,如飞镖、金针、菩提子,打着敌人后可以使敌损HP(体力)值;毒虫、蛇卵、蔓陀罗,打着敌人后可以让其中毒;其它的,嗯,其它只要你能想到的象板儿砖什么的,都可以做成道具扔出去。嘿……,如果是食用型道具,在设计时就要注意,食用一次可以加多少数值,有的是限定死的,有的是在一定范围内随机加的。也有类似是食物,不止可以食用一次,所以就有了可食用的次数。
装备类:固名思议嘛,当然是指可以装备身上的东西啦!右手上拿的菜刀,左手上拿的锅盖,头上戴着的太阳帽,身上穿着的T恤衫,脚上踏着的托鞋,腰上系着的皮带,肩上披着的床单,还有魔法定婚戒指、魔法金项链什么的,都可以做为装备类道具出场使用。如果你的角色有不同的系,那么各系之间的装备类道具应该也不大一样,就像男式服装和女式服装不可以混穿是一个道理。设计这样的道具,要详细说明道具的等级、重量或是大小(有负重值的游戏要考虑道具的轻重,有可视道具栏的游戏要考虑道具的大小)、数值(加攻防、敏捷等数据)、特效(对某魔法可防,对某系敌人效果加倍)、价格(买进时的价格和卖出时的价格),其它的还有材质(木、铜、铁……)、耐久值、弹药数、准确率等等。
情节类:这类道具在游戏的运程和发展中,是最不可少的。什么是情节类道具呢?就是诸如钥匙之类的,在情节发展过程中必不可少的道具。这类道具存在的目地,就是为了判断玩家的游戏进程是否达到设计者要求的程度的一个标尺。诸如钥匙、腰牌、徽章、某某的信等等,在游戏中都是重要的判断因素。有了它,游戏者才可以进行下一步的流程。
道具是如何获得的呢?我们都或多或少的玩过一些RPG游戏,在游戏过程中,我们知道道具的得到方法,无除乎有以下几点:
情节获得:对NPC角色说话,当你完成某情节后,会给你道具。这一类道具多是情节类的道具,或是致关重要的道具。
金钱购买:用你手中的Money,到武器铺、防具铺、道具铺购买,这一类道具则多为装备类和使用类的道具。
战斗取得:一场战斗结束后,所获得的战利品,一般分随机和固定两种,随机的多为装备类和使用类道具;固定的多为情节类道具。
翻箱倒柜:进入一个新的场景,首先在可疑的箱子、柜子、炉台等可能放置道具的地方痛痛快快地调查一番,这几乎成为每一个RPG迷的通病。尽管在现实生活中,这种行为是偷窃,也就是法律上所说的犯罪行为,可是在RPG游戏中,人们却乐此不疲。
解开谜题:这一种类型,也并不少见,在钢琴前弹奏一曲,左边的暗门打开,从里面拿到一颗闪闪发光的宝珠。
自己冶炼:用矿石或是其它的什么材料,去冶炼屋冶炼自己喜欢的道具。当你用原始材料制作出一柄非常强大的宝剑,这柄宝剑甚至还带着魔法,这种快感,远远胜于你得到道具的其它方式。
在实际的制作中,还有一些细节,要格外的注意。根据你的系统,来做其它的一些设计。一款游戏的好与坏,主要是它系统是否新,搬着别人的游戏规则,重编一套故事,还不如去玩《RPG工厂》呢。
第五章:事件
在游戏中的事件有两种,一种是可触发的,另一种是随机的。而在RPG游戏中,可触发的居多。所谓事件,也就是情节,有单体情节,按着游戏策划的设计思路一步步完成判断的条件;也有互动式情节,会根据游戏者的所作所为,做出不同的反应,生成新的事件。从当今游戏的主体趋势来看,互动式情节已经越来越受到玩家的青睐了。
那么事件是如何被触发的呢?有以下可能会触发事件
1. 是否与某人对过话?可通过查找该话标识,或是查找关键字。
2. 是否所持某道具)???(数)?
3. 是否杀死(或打败)某NPC?
4. 是否主角色某项属性值 )???(数)?
5. 是否主角色某项属性值 )?%(百分数)?
6. 是否该NPC某项属性值 )?%(百分数)?
7. 是否去过某场景?
8. 是否有某NPC(或可辅助角色)跟随?
9. 是否主角色职业为某某?
10. 是否主角色的师傅为某某NPC?
11. 是否初次来到当前场景?
12. 是否使用某道具?
13. 当前的任务时间是否为???(数)?
14. 当前的系统时间为???(数)?
15. 当前主角色的任务为?
16. 是否击打该NPC?
触发的条件,根据游戏内容的不同也会有些许的不同,但总的来说,万变不离其宗,大致无外乎于此。OK,现在我们有触发的判断点了,接下来就会按策划案导出触发的结果。触发的结果都包括什么呢?试着列举一下:
1. 打开某场景!
2. 消失某角色!
3. 得到或失去某道具???(数)!
4. 使主角色某属性提升或下降 ???(数)!
5. 使主角色某属性提升或下降 ?%(百分数)!
6. 得到金钱???(数)!
7. 得到金钱?%(百分数)!
8. 使主角色某属性回复???(数)!
9. 使主角色某属性回复?%(百分数)!
10. 使该NPC某属性提升或下降 ???(数)!
11. 使该NPC某属性提升或下降 ??%(百分数)!
12. 对话!
13. NPC跟随主角色!
14. NPC成为辅助角色,跟随主角色!
15. 该NPC或其它NPC会杀或打主角色!(如果不是A·RPG,这时往往会切屏进入战斗模式)
16. 得到任务(如果有任务栏将会被记录致任务栏)
17. 切换场景
18. 播放动画(或是音乐,或是进入小游戏)
19. 逃跑
20. 使主角色死亡
21. 游戏结束
一款普通的RPG游戏,正是由这样无数个触发点构成的。这的确感觉很奇妙,当我们点击一个NPC后,会发生什么呢?也许,你给它金钱,会有性命之虞。也许,你按下杀死这个NPC的指令后,它反而会向你提供重要的情报,或是送给你很棒的道具。大家还记得《仙剑奇侠传》吗?来到仙灵岛,初次到了那个什么什么宫,一向前走,就会有提示"你正要进去,一股大力将你推了出来",这里就是放了一个空角色用来挡住你的路的。而当你偷看赵灵儿洗澡,大段的键空动画播放完毕后,这时触发的结果就是使挡在那个什么什么宫门前的空角色消失。明白了吗?呵呵,事件就先说到这里吧。
第六章:对白
在RPG游戏中,对白往往会占很大的比重,对白也是一款游戏最直接、最平滑的表白。一款游戏素质如何,也从对白就可以直接表现出来。当你为你的游戏写对白时,毋庸置疑是要突出角色的性格、感情和文化背景。
突出性格:如果你为角色设定为豪爽的汉子,象“嘿,我说朋友,……”、“对不起,我是个大老粗,我说错话了,我给你赔礼”、“朋友,就此别过,我们后会有期!”这样的对白设定就非常符合角色的性格。而相反,如果你为角色设定为羞怯的小姑娘,那么与上面相同的意思,就应该为“嗯……嗯……这位公子请留步,……”、“嗯……对不起啦……请……不要生气……”、“嗯……公子,奴家要走了,还能再见到你吗?”
突出感情:你的角色随着你的剧情,会有喜怒哀乐忧思恨等种种感情。这一切,除了用相关的动画、音乐、音效来配合你表现这一切,最主要的表现方式还是在于对白。这就象是写一部小说,对白是赋于你角色生命力最直观的途径。一段感人肺腑的对白,甚至可以成为名句流传下来,举个例子,《仙剑奇侠传》中,林月茹(那个大大咧咧的女孩子)对李逍遥深情地说:"我们吃到老、玩到老,永远也不分开",初听不觉得咋地,但当林月茹死后,李逍遥回忆时,再出现这段对白,给人的感觉就有说不出的心酸与遗憾。
突出文化背景:这在你设计角色时,就应该有一个大致的感觉。说起来,很容易做到,就是呢?我们在给角色或NPC设计对白时,应该考虑到它们的文化背景。很难想象一个杀猪的屠户会说出"路漫漫其修远兮,吾将上下而求索"这样子雅句;也难以想象一个饱读诗书的江南才子,会说出 “贼直娘”、“天杀的”这样的粗口。文化背景另一点,则是针对地域方言、俗语俚语、习惯用语、职业用语、历史语言变迁而言的。说到这里,其实已经在语言学的范畴里了,一个优秀的策划,应该懂许多与游戏没有直接关系的知识,文学(诗歌、小说、散文等等)、艺术(音乐、美术、建筑美学等等)、语言(方言、音韵)、社会(历史、地理、哲学、经济等等)、民俗(神话、民风、服饰、习俗等等)、医学(中医)、玄学(易、术数等等),甚至一些杂七杂八的知识…… (呵,有自我标榜之嫌了,打住!)
另外提到的一点,就是对白,通常是要命名的,有的是一句对白为一个文件名,有的是一组对白为一个文件名,它的作用除了表现在画面的字幕上之外,还为语音留下接口。另一个作用,是用这些文件名来代替标识。也就是说,当你触发事件时,原则是判断主角色是否说过什么话,这正是以这句话的文件名来判断的。
如图示:
场景cj02
db02007-->仙机老人:见了孔雀神,只要说出我的名字,她就会把钥匙给你的。
文件名 说话人 内容
(cj为场景的缩写,02为第二场景)
(db为对白的缩写,02为第二场景,007为第7句话)
--------------
场景cj04
db04009-->孔雀神:是天机老人让你来的,好吧,钥匙给你。
db04010-->孔雀神:本座不认识你,凭什么把钥匙给你?
Dj024=神殿钥匙:一把金光闪闪的钥匙,可以用它来打开神殿的大门
(dj为道具的缩写,024为第24件道具)
Y
击点rw12-->是否发生过对白db02007?——>调对白db04009/得到道具Dj024 |
| N
v
调对白db04010
(rw为人物的缩写,12是第12个角色,即孔雀神)
这里需要提及的一点就是素材的命名,与你流程上的命名必须是一样的。相于命名,和流程,我在后面将会做专门的介绍。
第七章:语音和音效
在本章开始前,我就隐隐约约的感觉到,这一章的内容不太多,故将语音和音效合并为一体来写。现在我们先来看看语音吧,随着游戏开发技术的提高,不少游戏都是要求语音的,甚至是全程语音。在录制语音时,往往是请专业的配音人员来完成的。记得当时做《镜花缘》时,请了四位广播学院配音系的学生,因为游戏是全程语音,所以每一句文字都要求有语音。这样80多个角色,全是由四个人来完成。我们制作人员也想过把瘾,一人挑了一个角色,兴致勃勃的配了起来。结果一听声音,全不是那么一回事,对着录音设备几乎每个人都耗出两个多小时练习。结果谁挑的对白量越多,谁就练的时间更长:)
在制作上,有一些细节,在上一章,我们看到,每一句对白或每一组对白,都有它自己的编号,重要的是,当我们录制语音时,应该给每一个语音(WIV)文件起相同的名字。这样,当系统调用那一句(或一组)话的文字时,将同时调出语音文件。
虽然,全程语音或间断语音,是未来游戏的大趋势。但我个人并不看好,主要原因是质量太差。质量差的原因又是因为费用太高,请专业的配音演员,甚至达到每分钟几百元。即使是一般的配音演员,每小时也需要50~80元,对于游戏的开发,成本非常高。一般情况,一款全程语音的游戏,配音费用也得达到一至二万。而专业的游戏配音演员,在中国一个也没有,这样我想起游戏业商业化非常重的日本,从这点来说,就先进的多了。
再聊聊音效,音效在一款成功游戏中是极其重要的,很难想象无效果声的世界是什么样子。在《仙剑奇侠传》中,当发生战斗时,那林月茹的鞭子声,打到怪物时那声嘶力竭的惨叫声,对于玩家来说,的确是一种身临其境的感受。有的音效,甚至可以流行,记得《魔兽争霸》中魔兽族士兵,用极其可爱的声调回答一声"O?"、"Yes, master!"虽然,这部分应该是语音,在这里,我举得还是可以用音效来看待它们的。
在策划音效上,与场景、氛围相配合是极其重要的。山明水秀、良辰美景、湖光山色中,配以一两声鸟鸣;狂风呼啸的雪原上,隐隐约约的一声狼嚎;月下丛林里,依稀可以听到猫头鹰的笑声;工匠铺里,叮叮当当的打铁声;深山古刹的晚钟声和颂课声。这些都是为了将气氛达到我们要求的那样。
一般的来说,音效在游戏中,以三种形态出现。
背景音效:与背景音乐同时,不间断的播放,如工匠铺里,叮叮当当的打铁声。
随机音效:在一个场景中,随机播放出来,如湖光山色中,偶有一两声鸟鸣。
定制音效:随玩家的操作而播放的音效,如用剑砍敌人时"唰"的一声。或击点一只狗(NPC),它会发出"汪汪"声。
再或打开、关闭界面时,发出的"咔"的一声。
灵活机动的把你的音效,放在游戏中,使游戏更丰富多彩吧。
第八章:音乐
音乐在游戏中,是非常重要的一个因素。很有可能画面、规则、情节、程序都非常棒,可是忽略的音乐,而失去一大批玩家。
做为一个策划,没有必要掌握专业的音乐知识,但至少有差不多音乐感觉。当你音乐说明文档写出来时,应该清楚的列出,游戏中所出现的音乐(可以起个名,象是云山晚照、异境仙踪之类)、文件名(什么场景或是什么样情况调用什么音乐,所使用的标识名)、对音乐的要求和氛围,例如:
yy01,异境仙踪,音乐突出山水间的宁静,感觉上海外小凫,落英缤纷,仙风凫凫。要求,可循环播放。
yy02,群魔乱舞,战斗时的音乐,突出阴霾的氛围,同时也有战斗的激烈感觉。要求,可循环播放。
Yy03,剑士之歌,主旋律,突出节奏性,且有进行曲的风格。平缓中有高潮叠起,结尾部分,感觉悠扬舒远。可不必循环播放。
……
这样,音乐的要求说明就基本上差不多了,当音乐制作人员制作完毕,再审核一下,就行了。在合成时,需要把你要配乐的场景写清楚。
如:场景一(文件名):播放音乐yy01
某场景战斗画面:播放音乐yy02
片头音乐:播放音乐yy03
……
记得我的朋友LY(也是策划)对游戏的音乐就极尽挑剔之能事。从他嘴里哼哼出来的歌,都是游戏中的音乐。曾经是《三国之霸王大陆》,后来是《时空之钥》,再后来是《……》。(不过他哼得都非常难听,我发誓)所以我想,这样对游戏音乐要求"品味"很高的玩家应该绝不在少数吧?
本想可以写多些关于音乐的话题,但写得时候才发现,自己对音乐,真的是所知甚少。无奈,最后把《镜花缘》中的主题歌词奉献出来,大家可以学着唱唱。:D
《镜花缘》片头歌词
望不断的秋水苍桑,
走不尽的异地他乡。
莫道千壑万水路茫茫,
又谁知素裙罗衫满风霜。
理不清的寸断柔肠,
抹不煞的淡淡凄凉。
何必愁云满面泪成双,
都只为咫尺天涯情更伤。
夜长长,情更长,人不寐,向洪荒。
梦入高唐,世事无常,却是珠泪化馨香。
又几曾是月笼纱窗,
又几曾是楚瑟潇湘。
可怜一曲伤心泪汪汪。
终日里蓬莱晚暮尽悲怆。
又几曾是懒贴花黄,
又几曾是慵理晨妆。
且对莺歌燕舞锦春光,
莫辜负锦绣韶华共芬芳。
夜长长,情更长,人不寐,向洪荒。
梦入高唐,世事无常,却是珠泪化馨香。
第九章:界面
这一章说说游戏的界面,一款游戏的界面,当然不是策划来绘制的,但界面上的功能按钮,菜单的索引,界面与界面之间的跳转关系等等,却是实打实由策划来完成的。甚至在画面中,按钮的位置都应该告诉美术工作人员。说说界面及菜单的概念吧。
功能按钮:这里指在游戏过程中,每一个按钮的作用。这也是一个游戏是否容易上手的关键点,也就是操作吧。击点一个按钮,又弹出子级界面,再点再弹一个,再点……你想是不是非常烦琐。而做为策划要做的,就是使菜单尽可能的简化,功能尽可能的集中。再比如,在战斗画面时,按钮的功能应该是这样的:
攻击-->普通的攻击
魔法-->(弹出魔法列表)
道具-->(弹出道具列表)
逃跑
再比如,在普通画面时,按钮的功能应该是这样的:
魔法-->(弹出魔法列表)
道具-->(弹出道具列表)
装备-->(弹出装备界面)
情报-->(弹出情报界面)
功能-->子界面:音乐开关-->(出音乐开关选择按钮,点"OK"返回前一界面)
音效开关-->(出音效开关选择按钮,点"OK"返回前一界面)
速度调整-->(出速度调整滑条,点"OK"返回前一界面)
储荐进度-->(出进度列表,点"OK"储荐点亮栏,并返回前一界面)
装载进度-->(出进度列表,击亮栏目点"OK"进入进度游戏)
Y
退出游戏-->(询问是否真的退出,缺省设在否处)-->退回Windows
| N
v
退出询问界面
这是随便举了个例子,在设计界面时,尤其需要注意的是,一级界面跳到它的子集界面,一定要留给玩家返回来的路径。试想一下,在刚安装完这款游戏后,玩家只是想看看界面,来到了装载进度这一层界面。游戏刚装上,当然没有可装载的进度,可是策划又没有加返回按钮,结果玩家进退两难,只有强行关闭这个窗口。(还没玩呢,就给玩家留下了一个不好的影响 :()
还有一点值得一提,最近见到不少游戏,给功能按钮起了古里古怪的名字。什么梅开二度(装载进度),梦醒时分(退出游戏)……弄得玩家一头雾水。其实在合理的前提下,给功能按钮起上相关好听的名字,本是好事,但做到让玩家看不懂的地步,就做过了。
做为一个策划,要做的是迁就玩家(适应玩家),而不是让玩家迁就你(让玩家适应你),这是至关重要的。当你有一套新的操作系统已经出来后,先让一个菜鸟级玩家给你提提意见。你的游戏主要面向对象就是这样的初段位玩家,所以游戏操作越简单越好。当然简单不是说粗糙,更不是功能的弱化。
第十章:规则
这一章里的内容,虽然是精华,但是好些东西只可意会,不可言传。什么是规则,就是玩法、创意。一条创意得来绝不容易,甚至象写诗、写散文一样,需要灵感,需要突然迸发的火焰。刚来北京时,也是刚刚做策划时,1996年底的事吧。初来乍到,踌躇满志,当时立了一个名为《模拟猎》的游戏。游戏者用起始资金购买猎枪,有春、夏、秋、冬四个季节,根据季节去不同的地方(南美洲亚马逊森林、中国东北兴安岭、俄罗斯西伯利亚针叶林地带、非洲热带草原、非洲热带雨林、北美美国大峡谷)打猎。打回来的种种猎物可以分开卖,如虎皮、熊掌、象牙、鳄鱼皮(肉怎么处理?吃掉?)等等。(大大违反了《野生动物保护法》,这只是游戏,你要是真这么做,就得坐牢了)卖出钱后,可以买进更为先进的设备,如高倍望远镱、防护背心、录有动物叫声的磁带、热力跟踪探测仪等等。视角为主观视角,三维场景。这本是一个可大可小的游戏,但当时金盘公司游戏开发部的决策人以资料太难找为由,而继续开发爱国主义教育为题材的游戏。这个项目就搁浅了,可是一年以后,一款名为《猎鹿人》的游戏出品了,那感觉真叫人难受。一个以猎为题材的创意,也报废了。
1998年初,一个《模拟餐厅》的创意,因没有时间独自做,而随99年推出的《模拟西餐厅》而报废。其实《模拟餐厅》的立意是挺新的,即时经营类游戏,可以租不同档次的门面,也可以自己买下。前期的服务生可以少一些,到后期不单需要高素质的服务生,还需要门卫、保安、迎宾。按中国八大菜系来分类的大师傅,也有厨师等级。每过一段时间,都会开发出新的菜谱。这些菜谱是录入到系统里的,玩家可以根据菜谱模拟炒菜。在界面上配料,然后烹制,火候(火的大小调节)、味道(调料的多少调节),都是需要自己掌握的,最后一盘色香味美的菜上桌(每一道菜都有一张,与真实的菜一样的图)。至于食神来访、厨王挑战赛等小创意,就不足以述了。
嗯,怎么说呢?在没有《猎鹿人》、《模拟西餐厅》之前,这些都是极新的创意。但人家出来了,没有做的这些就只好丢弃了,这也许就是机遇吧。
怎么说到这儿了?上面是项目的大创意,整体、宏观的创意,现在回到我们所说的RPG上。RPG的创意,一般情况可以从这几点着手来想。
情节:故事的好坏有时起决定性的作用,《仙剑》从玩法、操作等等,没有任何创新,但只是因为它的故事感人,而久居榜首。
玩法:通常分系统和战斗两大版块,打个比方来说,史克威尔《FFVII》(亦名《太空战士VII》)中的,魔导石就是一个比较新的创意,突破传统游戏魔法因人而异,而是魔导石本身附有魔法具有级别,并可附在武器上,这属于系统玩法创意;还有象是《浪漫沙加3》(亦名《浪漫魔界塔3》)中的战斗时的阵法, 2~5个人之间产生千变万化的"阵"来,且每个阵通过锻炼都有非常酷的终结阵技,这就属于是战斗创意了。这里要注意的,玩法是否新,并不在于是否是一个游戏+另一个游戏,这就像很难想象DOOM类游戏和棋牌类的组合是一个道理。
表现:是指游戏的表现形式,多与美术人员和程序编程人员息息相关。如《FFVII》(亦名《太空战士VII》)中战斗时每一招都有它特有的一个或几个3D视角来表现。
在立创意时,往往应该从几个角度来考虑是否成熟。
第一.系统平衡:当一条创意出来,它将牵扯到全局。打个比方,你的RPG中,如果牵扯到职业,各职业之间孰强孰弱,便是一个系统平衡问题。
再举例,升级系统的平衡,游戏者需要积累多少Experience才可升级,这就需要与这个级别相对应的NPC(普通NPC供该级别游戏者锻炼,故较弱;BOSS级NPC则应与该级别游戏者相差无几等等),这称为升级系统平衡。
另外,如果角色有多个,没有参加战斗的角色,在后期如果要登场,打起来就根本不可能胜利。(偏偏这个玩家不练它,这时我们不能强迫玩家去从头练,只能想办法把根本不可能胜利变为可能胜利但非常困难,这就是迁就玩家,而不是要玩家迁就你)就这个问题来说,《FFVII》(亦名《太空战士VII》)是这样做的,参加战斗的角色可以得到全部的Experience,而未参加战斗的其它角色匀可以得到一场战斗的50%Experience。这样,后期如果强制要某个未参加战斗的角色出场,也不至于根本打不过。
第二.美术工作量:一条创意,要考虑其实现的可能性。实现关键是程序平台和美术工作量。程序平台可以开发,而美术工作量却取不了巧,需要夯大量的美工,这就等于大量的投资。当你非常轻松的设计了一个NPC角色,就得有人为你做模型、画头像;当你金口一开设计出一组动画,就意味着美工一帧帧画,再一帧帧连。所以,在设计游戏时,这是一个必须要考虑的因素。
第三. 玩点:所谓玩点,就是玩家认为好玩的地方。一个创意固然要新,但它始终要建立在好玩的基础上,否则就没有生命力。创意再新,玩家不喜欢也是不行的。正是:气拔山兮力盖世,玩家不爱兮可奈何?策划兮策划兮奈若何?删!
第四.上手性:在一个创意之初,另一点需要考虑就是上手性,所谓上手性,就是以最简单的方式让玩家上手开始游戏。想想看,一位玩家,可能是一位从没有摸过游戏的新玩家,面对你的繁琐的操作,复杂的系统,不知其可的按钮,他愿意继续玩下去吗?嘿,他不玩下去就不会向其它人推荐,不推荐就不会有很多人来买,没人买公司就挣不上钱,公司挣不上钱就不发我工资,没钱我只好跳槽去找工作,一说出这个繁琐、复杂、不知其可的游戏是我做的就没有公司骋我……
当然一个创意的得到是可遇不可求的,往往是一个偶然,一个灵感,她才个姗姗来临,而你去苦思冥想经常是一无所得。而一个创意从雏形到这个创意的完全成熟是需要时间的,有时一年,有时是几年,这个过程中,不乏有别人已经把你的创意用了这样的痛苦事件发生,这也是难免的。一个成熟的策划,不仅仅是想出新的创意想法,更重要的是在完善这个创意过程中,敢于否定自己。(这是LY说的,很有道理)
第十一章:命名
这一章,随便聊聊游戏的命名,一是游戏本身的名字,二则是游戏内部文件的命名规则。
先说游戏本身的名字吧。其实游戏的命名,与文学作品的命名差不多,名字好坏,将直接影响到玩家对一个游戏的最初影响。我们不妨来看看,其它的很多游戏的命名。
咏史类:以这一部分为题材的游戏作品,它的名字往往较为写实,以三国题材的游戏为例,如《三国志》、《三国演义》、《升龙三国志》、《三国英杰传》、《三国群英传》、《三国英雄传》等等(走到《三国XX传》这个份上,已经没有什么意义了),不得已,只好在大标题下,加小标题(象什么"三国志之霸王の大陆"),状似一个系列的某一版,或者说是还有后继作品。其实是无名可拟,只好有口难言了。另外还有《孔明传》这样人物传记体的名字,也有《官渡》、《赤壁》、《荆州》这样叙事体的命名,也有以著作名为题《红楼梦》、《水浒》、《西游记》、《镜花缘》无所谓好,也无所谓不好。
RPG类:我们暂抛开美式RPG,如《魔法门》、《博德之门》这样无背景或自定义背景的RPG,也抛开日式RPG,如《太空战士》、《时空之钥》、《浪漫沙加》这样也是无背景或自定义背景的RPG。单说,中国(包括了台湾)一些游戏的命名,如《仙剑奇侠传》、《金庸群侠传》等,真是'这次第,怎一个"传" 字了得';再要么,就是以武侠小说的作品名为名,既不伤神,也不费力,《射雕英雄传》、《鹿鼎记》、《天龙八部》,真是信手拈来,语自天成呀。
其它的就很多了,名字的作用也似乎不仅仅是从突出内容而言,更有宽大其辞、哗众取宠之嫌,当年的《血狮~~保卫中国》(血字血淋淋,狮字雄纠纠,更令人叫绝的是最后还要保卫中国,不明其理者百思莫明该游戏之妙)就是典型的一例。
但有的游戏名字感觉真是不错,以楚汉为题材的《项刘记》;以成吉思汗为题材的《苍狼与白鹿》;以日本丰臣秀吉为题材的《太阁立志传》;以织田信长为题材的《信长的野望》,都是可以载入史册,不可多得的好名字。
从名字的角度来说,我个人的感觉还是突出主题,但到了《三国XX传》的确也没什么意思了。主要还是针对游戏本身的内容或是内涵,起一个合适自己的独一无二的名字。
再说说游戏内部文件的命名规则。一个游戏内部的文件成千上万,分别放在不同的库里,象是角色库、场景库、道具库、音乐库、音效库、对白库、动画库……,当游戏运行的时候,就开始从这些库中调出有用的文件。
而在成千上万的文件中,怎么才能保证调用时不会调错呢?这就需要一套合理的命名规则。在命名时,不但清楚的要分开角色、场景、音乐等等,有时还需要一个文件加上标识。随便举个例子来说,比如说给道具的命名
道具命名规则:djac05,第一、二位dj为"道具"的缩写;
第三位为a和b代表两种持有方式,a是持有,b代表装备
第四位代表类型a食品,b治疗药,c营养药,e头装备,f身穿装备,h脚装备,i武器,j书籍,k杂货,l情节道具
任意一件道具的文件名,都以此为原则。
djal06和氏璧:产自楚国,是价值连城的名宝 情节道具
djbk05璜:一种美玉,佩带后可使思路灵活 悟性+5
djaj37神农:农业书籍,战国时期农家所著 耕作技能可学至20级
djbi16昆吾刀:用昆吾山上的石铁冶练而刀,天下名刀 攻击力+10
djbf04儒衫:产自齐国,儒士的服饰 防御力+1
djab02白药:产自百越,可回复些许生命值 生命恢复30%
djac05柏实:产自魏国,可以提高耐力 耐力+5
最后一见到djac05,我们就马上可以知道这些信息:它是一件道具,是可以持有的营养药品。
其它类型的文件,只要有它自己的属性,最好能在命名中标识出来,不单做策划时,可以方便的调用,最关键在库中,这些文件可以排序查找。比如上面的命名规则,当查到dj时,所有的道具都会被排出来;再进一位a时,所有可以持有的道具又站出来了;再进一位j时,列出所有书籍;最后调37,就是我们想要的《神农》。(学学这本书,就会耕地啦,哈)
再顺带说一下,策划一个项目是,策划的文档也应合理的建好文件夹和系统的命名,这样做既便于随时找到你写的文档,将来你做完了这个项目后也可以以此压缩保存。如:
d:Game战国行
1. 立项-->?
2. 策划-->?
3. 概述-->?
4. 列表-->?
5. 系统-->·关于单机模式与联机模式的问题.doc
·关于时间的设计.doc
·技能规则.doc
·界面指令及操作.doc
·界面指令及操作(修正1).doc
·情节判断条件及结果一览.doc
·行动及战斗操作规则.doc
·属性分类.doc
6. 文章-->?
7. 美术-->?
8. 相关-->?
OK,就到这儿吧
Linux下的多线程编程
1
引言
线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux。
为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题。
使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来桓鼋痰目笤际且桓鱿叱炭?0倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
除了以上所说的优点外,不和进程比较,多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:
1)
提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time
consuming)置于一个新的线程,可以避免这种尴尬的情况。
2)
使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
3)
改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
下面我们先来尝试编写一个简单的多线程程序。
2
简单的多线程编程
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序example1.c。
/*
example.c*/
#include <stdio.h>
#include <pthread.h>
void
thread(void)
{
int i;
for(i=0;i<3;i++)
printf("This is a
pthread.n");
}
int
main(void)
{
pthread_t id;
int
i,ret;
ret=pthread_create(&id,NULL,(void *)
thread,NULL);
if(ret!=0){
printf ("Create pthread error!n");
exit
(1);
}
for(i=0;i<3;i++)
printf("This is the main
process.n");
pthread_join(id,NULL);
return
(0);
}
我们编译此程序:
gcc example1.c -lpthread -o
example1
运行example1,我们得到如下结果:
This is the main process.
This is a
pthread.
This is the main process.
This is the main process.
This is a
pthread.
This is a pthread.
再次运行,我们可能得到如下结果:
This is a pthread.
This
is the main process.
This is a pthread.
This is the main process.
This
is a pthread.
This is the main
process.
前后两次结果不一样,这是两个线程争夺CPU资源的结果。上面的示例中,我们使用到了两个函数, pthread_create和pthread_join,并声明了一个pthread_t型的变量。
pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:
typedef
unsigned long int
pthread_t;
它是一个线程的标识符。函数pthread_create用来创建一个线程,它的原型为:
extern int
pthread_create __P ((pthread_t *__thread, __const pthread_attr_t
*__attr,
void *(*__start_routine) (void *), void
*__arg));
第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。
函数pthread_join用来等待一个线程的结束。函数原型为:
extern
int pthread_join __P ((pthread_t __th, void
**__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:
extern
void pthread_exit __P ((void *__retval)) __attribute__
((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。
在这一节里,我们编写了一个最简单的线程,并掌握了最常用的三个函数pthread_create,pthread_join和pthread_exit。下面,我们来了解线程的一些常用属性以及如何设置这些属性。
3
修改线程的属性
在上一节的例子里,我们用pthread_create函数创建了一个线程,在这个线程中,我们使用了默认参数,即将该函数的第二个参数设为NULL。的确,对大多数程序来说,使用默认属性就够了,但我们还是有必要来了解一下线程的有关属性。
属性结构为pthread_attr_t,它同样在头文件/usr/include/pthread.h中定义,喜欢追根问底的人可以自己去查看。属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。属性对象主要包括是否绑定、是否分离、堆栈地址、堆栈大小、优先级。默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。
关于线程的绑定,牵涉到另外一个概念:轻进程(LWP:Light
Weight
Process)。轻进程可以理解为内核线程,它位于用户层和系统层之间。系统对线程资源的分配、对线程的控制是通过轻进程来实现的,一个轻进程可以控制一个或多个线程。默认状况下,启动多少轻进程、哪些轻进程来控制哪些线程是由系统来控制的,这种状况即称为非绑定的。绑定状况下,则顾名思义,即某个线程固定的"绑"在一个轻进程之上。被绑定的线程具有较高的响应速度,这是因为CPU时间片的调度是面向轻进程的,绑定的线程可以保证在需要的时候它总有一个轻进程可用。通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反应之类的要求。
设置线程绑定状态的函数为pthread_attr_setscope,它有两个参数,第一个是指向属性结构的指针,第二个是绑定类型,它有两个取值:PTHREAD_SCOPE_SYSTEM(绑定的)和PTHREAD_SCOPE_PROCESS(非绑定的)。下面的代码即创建了一个绑定的线程。
#include
<pthread.h>
pthread_attr_t attr;
pthread_t
tid;
/*初始化属性值,均设为默认值*/
pthread_attr_init(&attr);
pthread_attr_setscope(&attr,
PTHREAD_SCOPE_SYSTEM);
pthread_create(&tid, &attr, (void *) my_function, NULL);
线程的分离状态决定一个线程以什么样的方式来终止自己。在上面的例子中,我们采用了线程的默认属性,即为非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。设置线程分离状态的函数为pthread_attr_setdetachstate(pthread_attr_t
*attr, int detachstate)。第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD
_CREATE_JOINABLE(非分离线程)。这里要注意的一点是,如果设置一个线程为分离线程,而这个线程运行又非常快,它很可能在pthread_create函数返回之前就终止了,它终止以后就可能将线程号和系统资源移交给其他的线程使用,这样调用pthread_create的线程就得到了错误的线程号。要避免这种情况可以采取一定的同步措施,最简单的方法之一是可以在被创建的线程里调用pthread_cond_timewait函数,让这个线程等待一会儿,留出足够的时间让函数pthread_create返回。设置一段等待时间,是在多线程编程里常用的方法。但是注意不要使用诸如wait()之类的函数,它们是使整个进程睡眠,并不能解决线程同步的问题。
另外一个可能常用的属性是线程的优先级,它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam进行存放,一般说来,我们总是先取优先级,对取得的值修改后再存放回去。下面即是一段简单的例子。
#include
<pthread.h>
#include <sched.h>
pthread_attr_t
attr;
pthread_t tid;
sched_param param;
int
newprio=20;
pthread_attr_init(&attr);
pthread_attr_getschedparam(&attr,
¶m);
param.sched_priority=newprio;
pthread_attr_setschedparam(&attr,
¶m);
pthread_create(&tid, &attr, (void *)myfunction,
myarg);
4
线程的数据处理
和进程相比,线程的最大优点之一是数据的共享性,各个进程共享父进程处沿袭的数据段,可以方便的获得、修改数据。但这也给多线程编程带来了许多问题。我们必须当心有多个不同的进程访问相同的变量。许多函数是不可重入的,即同时不能运行一个函数的多个拷贝(除非使用不同的数据段)。在函数中声明的静态变量常常带来问题,函数的返回值也会有问题。因为如果返回的是函数内部静态声明的空间的地址,则在一个线程调用该函数得到地址后使用该地址指向的数据时,别的线程可能调用此函数并修改了这一段数据。在进程中共享的变量必须用关键字volatile来定义,这是为了防止编译器在优化时(如gcc中使用-OX参数)改变它们的使用方式。为了保护变量,我们必须使用信号量、互斥等方法来保证我们对变量的正确使用。下面,我们就逐步介绍处理线程数据时的有关知识。
4.1
线程数据
在单线程的程序里,有两种基本的数据:全局变量和局部变量。但在多线程程序里,还有第三种数据类型:线程数据(TSD:
Thread-Specific
Data)。它和全局变量很象,在线程内部,各个函数可以象使用全局变量一样调用它,但它对线程外部的其它线程是不可见的。这种数据的必要性是显而易见的。例如我们常见的变量errno,它返回标准的出错信息。它显然不能是一个局部变量,几乎每个函数都应该可以调用它;但它又不能是一个全局变量,否则在A线程里输出的很可能是B线程的出错信息。要实现诸如此类的变量,我们就必须使用线程数据。我们为每个线程数据创建一个键,它和这个键相关联,在各个线程里,都使用这个键来指代线程数据,但在不同的线程里,这个键代表的数据是不同的,在同一个线程里,它代表同样的数据内容。
和线程数据相关的函数主要有4个:创建一个键;为一个键指定线程数据;从一个键读取线程数据;删除键。
创建键的函数原型为:
extern
int pthread_key_create __P ((pthread_key_t *__key,
void (*__destr_function)
(void
*)));
第一个参数为指向一个键值的指针,第二个参数指明了一个destructor函数,如果这个参数不为空,那么当每个线程结束时,系统将调用这个函数来释放绑定在这个键上的内存块。这个函数常和函数pthread_once
((pthread_once_t*once_control, void (*initroutine)
(void)))一起使用,为了让这个键只被创建一次。函数pthread_once声明一个初始化函数,第一次调用pthread_once时它执行这个函数,以后的调用将被它忽略。
在下面的例子中,我们创建一个键,并将它和某个数据相关联。我们要定义一个函数createWindow,这个函数定义一个图形窗口(数据类型为Fl_Window
*,这是图形界面开发工具FLTK中的数据类型)。由于各个线程都会调用这个函数,所以我们使用线程数据。
/*
声明一个键*/
pthread_key_t myWinKey;
/* 函数 createWindow */
void createWindow
( void ) {
Fl_Window * win;
static pthread_once_t once=
PTHREAD_ONCE_INIT;
/* 调用函数createMyKey,创建键*/
pthread_once ( & once,
createMyKey) ;
/*win指向一个新建立的窗口*/
win=new Fl_Window( 0, 0, 100, 100,
"MyWindow");
/* 对此窗口作一些可能的设置工作,如大小、位置、名称等*/
setWindow(win);
/*
将窗口指针值绑定在键myWinKey上*/
pthread_setpecific ( myWinKey,
win);
}
/* 函数
createMyKey,创建一个键,并指定了destructor */
void createMyKey ( void )
{
pthread_keycreate(&myWinKey,
freeWinKey);
}
/* 函数
freeWinKey,释放空间*/
void freeWinKey ( Fl_Window * win){
delete
win;
}
这样,在不同的线程中调用函数createMyWin,都可以得到在线程内部均可见的窗口变量,这个变量通过函数pthread_getspecific得到。在上面的例子中,我们已经使用了函数pthread_setspecific来将线程数据和一个键绑定在一起。这两个函数的原型如下:
extern
int pthread_setspecific __P ((pthread_key_t __key,__const void
*__pointer));
extern void *pthread_getspecific __P ((pthread_key_t
__key));
这两个函数的参数意义和使用方法是显而易见的。要注意的是,用pthread_setspecific为一个键指定新的线程数据时,必须自己释放原有的线程数据以回收空间。这个过程函数pthread_key_delete用来删除一个键,这个键占用的内存将被释放,但同样要注意的是,它只释放键占用的内存,并不释放该键关联的线程数据所占用的内存资源,而且它也不会触发函数pthread_key_create中定义的destructor函数。线程数据的释放必须在释放键之前完成。
4.2
互斥锁
互斥锁用来保证一段时间内只有一个线程在执行一段代码。必要性显而易见:假设各个线程向同一个文件顺序写入数据,最后得到的结果一定是灾难性的。
我们先看下面一段代码。这是一个读/写程序,它们公用一个缓冲区,并且我们假定一个缓冲区只能保存一条信息。即缓冲区只有两个状态:有信息或没有信息。
void
reader_function ( void );
void writer_function ( void );
char
buffer;
int buffer_has_item=0;
pthread_mutex_t mutex;
struct timespec
delay;
void main ( void ){
pthread_t reader;
/*
定义延迟时间*/
delay.tv_sec = 2;
delay.tv_nec = 0;
/*
用默认属性初始化一个互斥锁对象*/
pthread_mutex_init
(&mutex,NULL);
pthread_create(&reader, pthread_attr_default, (void
*)&reader_function), NULL);
writer_function(
);
}
void
writer_function (void){
while(1){
/* 锁定互斥锁*/
pthread_mutex_lock
(&mutex);
if (buffer_has_item==0){
buffer=make_new_item(
);
buffer_has_item=1;
}
/*
打开互斥锁*/
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}
void
reader_function(void){
while(1){
pthread_mutex_lock(&mutex);
if(buffer_has_item==1){
consume_item(buffer);
buffer_has_item=0;
}
pthread_mutex_unlock(&mutex);
pthread_delay_np(&delay);
}
}
这里声明了互斥锁变量mutex,结构pthread_mutex_t为不公开的数据类型,其中包含一个系统分配的属性对象。函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如果需要声明特定属性的互斥锁,须调用函数pthread_mutexattr_init。函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来设置互斥锁属性。前一个函数设置属性pshared,它有两个取值,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进程中的线程同步,后者用于同步本进程的不同线程。在上面的例子中,我们使用的是默认属性PTHREAD_PROCESS_
PRIVATE。后者用来设置互斥锁类型,可选的类型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE和PTHREAD
_MUTEX_DEFAULT。它们分别定义了不同的上所、解锁机制,一般情况下,选用最后一个默认属性。
pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直至调用pthread_mutex_unlock为止,均被上锁,即同一时间只能被一个线程调用执行。当一个线程执行到pthread_mutex_lock处时,如果该锁此时被另一个线程使用,那此线程被阻塞,即程序将等待到另一个线程释放此互斥锁。在上面的例子中,我们使用了pthread_delay_np函数,让线程睡眠一段时间,就是为了防止一个线程始终占据此函数。
上面的例子非常简单,就不再介绍了,需要提出的是在使用互斥锁的过程中很有可能会出现死锁:两个线程试图同时占用两个资源,并按不同的次序锁定相应的互斥锁,例如两个线程都需要锁定互斥锁1和互斥锁2,a线程先锁定互斥锁1,b线程先锁定互斥锁2,这时就出现了死锁。此时我们可以使用函数pthread_mutex_trylock,它是函数pthread_mutex_lock的非阻塞版本,当它发现死锁不可避免时,它会返回相应的信息,程序员可以针对死锁做出相应的处理。另外不同的互斥锁类型对死锁的处理不一样,但最主要的还是要程序员自己在程序设计注意这一点。
4.3
条件变量 前一节中我们讲述了如何使用互斥锁来实现线程间数据的共享和通信,互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。
条件变量的结构为pthread_cond_t,函数pthread_cond_init()被用来初始化一个条件变量。它的原型为:
extern
int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t
*__cond_attr));
其中cond是一个指向结构pthread_cond_t的指针,cond_attr是一个指向结构pthread_condattr_t的指针。结构pthread_condattr_t是条件变量的属性结构,和互斥锁一样我们可以用它来设置条件变量是进程内可用还是进程间可用,默认值是PTHREAD_
PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用。注意初始化条件变量只有未被使用时才能重新初始化或被释放。释放一个条件变量的函数为pthread_cond_
destroy(pthread_cond_t
cond)。
函数pthread_cond_wait()使线程阻塞在一个条件变量上。它的函数原型为:
extern int
pthread_cond_wait __P ((pthread_cond_t *__cond,
pthread_mutex_t
*__mutex));
线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒,但是要注意的是,条件变量只是起阻塞和唤醒线程的作用,具体的判断条件还需用户给出,例如一个变量是否为0等等,这一点我们从后面的例子中可以看到。线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。这个过程一般用while语句实现。
另一个用来阻塞线程的函数是pthread_cond_timedwait(),它的原型为:
extern
int pthread_cond_timedwait __P ((pthread_cond_t *__cond,
pthread_mutex_t
*__mutex, __const struct timespec
*__abstime));
它比函数pthread_cond_wait()多了一个时间参数,经历abstime段时间后,即使条件变量不满足,阻塞也被解除。
函数pthread_cond_signal()的原型为:
extern
int pthread_cond_signal __P ((pthread_cond_t
*__cond));
它用来释放被阻塞在条件变量cond上的一个线程。多个线程阻塞在此条件变量上时,哪一个线程被唤醒是由线程的调度策略所决定的。要注意的是,必须用保护条件变量的互斥锁来保护这个函数,否则条件满足信号又可能在测试条件和调用pthread_cond_wait函数之间被发出,从而造成无限制的等待。下面是使用函数pthread_cond_wait()和函数pthread_cond_signal()的一个简单的例子。
pthread_mutex_t count_lock;
pthread_cond_t
count_nonzero;
unsigned count;
decrement_count () {
pthread_mutex_lock
(&count_lock);
while(count==0)
pthread_cond_wait( &count_nonzero,
&count_lock);
count=count -1;
pthread_mutex_unlock
(&count_lock);
}
increment_count(){
pthread_mutex_lock(&count_lock);
if(count==0)
pthread_cond_signal(&count_nonzero);
count=count+1;
pthread_mutex_unlock(&count_lock);
}
count值为0时,decrement函数在pthread_cond_wait处被阻塞,并打开互斥锁count_lock。此时,当调用到函数increment_count时,pthread_cond_signal()函数改变条件变量,告知decrement_count()停止阻塞。读者可以试着让两个线程分别运行这两个函数,看看会出现什么样的结果。
函数pthread_cond_broadcast(pthread_cond_t
*cond)用来唤醒所有被阻塞在条件变量cond上的线程。这些线程被唤醒后将再次竞争相应的互斥锁,所以必须小心使用这个函数。
4.4
信号量 信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用函数sem_post()增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。函数sem_trywait()和函数pthread_
mutex_trylock()起同样的作用,它是函数sem_wait()的非阻塞版本。下面我们逐个介绍和信号量有关的一些函数,它们都在头文件/usr/include/semaphore.h中定义。
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:
extern
int sem_init __P ((sem_t *__sem, int __pshared, unsigned int
__value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
函数sem_post(
sem_t *sem
)用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait(
sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait (
sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
函数sem_destroy(sem_t
*sem)用来释放信号量sem。
下面我们来看一个使用信号量的例子。在这个例子中,一共有4个线程,其中两个线程负责从文件读取数据到公共的缓冲区,另两个线程从缓冲区读取数据作不同的处理(加和乘运算)。
/*
File sem.c */
#include <stdio.h>
#include
<pthread.h>
#include <semaphore.h>
#define MAXSTACK 100
int
stack[MAXSTACK][2];
int size=0;
sem_t sem;
/*
从文件1.dat读取数据,每读一次,信号量加一*/
void ReadData1(void){
FILE
*fp=fopen("1.dat","r");
while(!feof(fp)){
fscanf(fp,"%d
%d",&stack[size][0],&stack[size][1]);
sem_post(&sem);
++size;
}
fclose(fp);
}
/*从文件2.dat读取数据*/
void
ReadData2(void){
FILE
*fp=fopen("2.dat","r");
while(!feof(fp)){
fscanf(fp,"%d
%d",&stack[size][0],&stack[size][1]);
sem_post(&sem);
++size;
}
fclose(fp);
}
/*阻塞等待缓冲区有数据,读取数据后,释放空间,继续等待*/
void
HandleData1(void){
while(1){
sem_wait(&sem);
printf("Plus:%d+%d=%dn",stack[size][0],stack[size][1],
stack[size][0]+stack[size][1]);
--size;
}
}
void
HandleData2(void){
while(1){
sem_wait(&sem);
printf("Multiply:%d*%d=%dn",stack[size][0],stack[size][1],
stack[size][0]*stack[size][1]);
--size;
}
}
int
main(void){
pthread_t
t1,t2,t3,t4;
sem_init(&sem,0,0);
pthread_create(&t1,NULL,(void
*)HandleData1,NULL);
pthread_create(&t2,NULL,(void
*)HandleData2,NULL);
pthread_create(&t3,NULL,(void
*)ReadData1,NULL);
pthread_create(&t4,NULL,(void *)ReadData2,NULL);
/*
防止程序过早退出,让它在此无限期等待*/
pthread_join(t1,NULL);
}
在Linux下,我们用命令gcc -lpthread sem.c -o sem生成可执行文件sem。
我们事先编辑好数据文件1.dat和2.dat,假设它们的内容分别为1 2 3 4 5 6 7 8 9 10和 -1 -2 -3 -4 -5 -6 -7 -8
-9 -10
,我们运行sem,得到如下的结果:
Multiply:-1*-2=2
Plus:-1+-2=-3
Multiply:9*10=90
Plus:-9+-10=-19
Multiply:-7*-8=56
Plus:-5+-6=-11
Multiply:-3*-4=12
Plus:9+10=19
Plus:7+8=15
Plus:5+6=11
从中我们可以看出各个线程间的竞争关系。而数值并未按我们原先的顺序显示出来这是由于size这个数值被各个线程任意修改的缘故。这也往往是多线程编程要注意的问题。
5
小结
多线程编程是一个很有意思也很有用的技术,使用多线程技术的网络蚂蚁是目前最常用的下载工具之一,使用多线程技术的grep比单线程的grep要快上几倍,类似的例子还有很多。希望大家能用多线程技术写出高效实用的好程序来。
诺基亚 N-Gage QD
没有碰到过白屏的都算不上NG的玩家!”“今天你白屏了吗?”这是时下NG玩家们很流行的一句话。
拥有蓝牙、MP3、收音、3D游戏的N-GAGE和N-GAGE
QD凭着超强的娱乐、多媒体功能和低廉的价格被众多的好玩一族视为超级性价比的手机,纷纷追捧和购买,一时间,手机玩乐的风潮再次在我们身边刮起。但是,
每一件事物都注定会有正反的两面,“白屏”现象曾让多少人对“小N”爱恨交织;骄气的“小N”稍有不甚就会白屏罢工,50-120元/次的白屏修复是玩家
们难以承担的负累,更有甚者抓住这个机会狠狠的发了一笔“白屏”财。今天IT.com.cn手机频道就和大家一起对NG的白屏现象进行终极揭密,教大家自
己动手解决白屏,让你的“小N”更加可爱。
其实很多时候我们碰见的“白屏”现象是可以自己动手解决的,也就是假“白屏”,但是真正的“白屏”目前只能通过刷机解决。下面我们就真假“白屏”分两个部分来为大家详细探密和公布解决方法:
一、假“白屏”现象的解决方法:
如果你的NG出现了系统错误或者所谓的“白屏”问题,可以通过以下方法解决:
1、尝试开机解决(如果可以正常开机可以跳过此步骤)
a.拆下电池和SIM卡,如果后台的运行程序(如T9)没有装在E盘,可以同时卸下SIM卡和MMC卡,然后放置一段时间再装上电池开机。
b.如果使用上面的方法没有效果,那么请按住键盘右下方的笔形键不放,同时按住开机键开机,等屏幕出现“NOKIA”的标志后放开开机键,成功后就可以进入安全模式了(系统运行正常是不会进入安全模式的)。
c.假如上面的方法还是不行,那么就要按住笔形不放,同时按住开机键,然后快速的不间断按左边键盘导航键的中间,成功后就可以进入手机菜单界面。
2、格式化手机解决(如果手机没有系统冲突或者错误提示可以跳过此步骤)
把手机退出到待机界面,输入“*#7370#”,手机会出现“Restore all original settings? Device will restart”,按“Yes”,然后输入密码“12345”,等手机重启后恢复出厂状态。
二.导致NG假“白屏”引起的原因:
1、NG手机C盘使用的相关问题:
a.在用NG玩游戏的时候同时用其他手机通过蓝牙传了个900KB左右的档案到NG的C盘,手机“白屏”。
b.手机格式化MMC卡的时候贪图方便直接把卡里的相片和资料拷到C盘,拷贝还没结束手机就提示错误,重启后“白屏”
c.无意中删除了C盘中的某个未知文件后自动关机,手动按方向键加笔形键再开机屏幕只闪了几下图标,之后就白屏,接着就黑屏没任何反应。
原因:文中所说的a.b是由于NG手机容量不足造成的无法开机“白屏”,可以尝试长时间拔下电池,用上文提到过的方法解决,如果开不了机就只能刷机解决。文中所说的c现象已经无法启动,也只能通过刷机解决。
提示:NG手机的C盘保持一定的空间和容量是保证系统运行正常的必要条件,若需要安装大容量的文件请选择装在MMC卡上,请别乱删C盘中的文件。
2、Q9和T9输入法的相关问题:
a.用NG在听MP3的时候收到短信,直接切换到Q9菜单开启,结果手机重启后提示错误,但可以正常使用,一段时间后,手机再次重启后不能进入系统,
提示“Device start-up failed contact the retailer”,只能关机拔电池处理。
b.用SeleQ设置下载的Logo后重启,但不能进入系统,拔电池后重启会出现APP出错信息,Q9或T9输入法不可以用,文字出现乱码,删除输入法重新安装后同样问题出现,然后白屏。
原因:以上的两个列子都是假“白屏”,一般用“尝试开机法”就可以解决,成功开机后就可以格式化手机恢复功能。
提示:Q9和T9输入法不是专门给NG设计的,这样两者的磨合不是很好,但是又要必须使用,那么Q9在后台运行的时候肯定会和一些程序引起冲突,而经
常开启 关闭的操作更容易和其他软件发生冲突,所以Q9在开启后不要随意关闭和卸载正在使用的Q9,以免增加白屏的风险。
3、修改运行商Logo导致白屏的相关问题:
a.自己在电脑上做了一张图片,准备作为Logo,传到手机上用Sele Q设置后,手机白屏。
b.用制作好并且符合尺寸的Logo替换了系统的Logo,用SeleQ重启后白屏。
原因:很多玩家都反映更改Logo会使手机白屏,有人认为是SeleQ的问题,使用软件方法重启会造成白屏,但是很多人不止一次的修改Logo,都没
有任何问题,这种情况将NG设置为OFFILINE模式后重启的白屏相同,这种问题一般都是通过尝试开机法解决,如不能则只能刷机解决。
提示:尽量少修改或不修改系统的文件。
4、关机前未关闭应用程序的相关问题
正在玩一游戏,直接按挂机键退出,让其在后台运行,一小时后手机重启白屏。
原因:对后台运行中的非C盘程序未终止关机或者重启动,特别是MMC卡的兼容性不好的还可能导致系统崩溃或者出错,这样的情况可以用尝试开机法解决,如不能就只能刷机。
提示:避免在非C盘软件运行的情况下重启手机,不要设置开机自动运行E盘(MMC卡)程序,关机前尽量退出所有后台运行的程序。
5、MMC卡使用的相关问题:
a.使用SeleQ时插入了USB线,系统马上报错,重新启动后白屏。
b.在使用USB和电脑时执行了MP3的播放操作(音乐文件在MMC卡里),结果报错,重启后白屏。
c.无意中将NG连接电脑的数据线插拔了几下,当按下NG功能表键后屏幕闪动几下后无法开机。
原因:以上的三个现象都发生NG对MMC卡访问控制时(不同于NG和MMC卡的识别兼容性问题),如系统和应用程序同时访问MMC卡或多个设备(程序)同时访问由于NG自身脆弱存储卡访问机制,使得这类白屏一般无法自行解决,只能通过刷机解决。
提示:在使用USB线连接电脑时,尽量不要使用NG内的程序(如SeleQ MP3播放器等)访问MMC卡。
6、硬件损坏的相关问题:
硬件损坏这种情况也会存在,就是尝试了所有的方法,并且经过刷机也未见效果的时候就是硬件方面的问题了,唯一的解决方法就只能换件维修了。
正如我们这片文章所说的,NG的很多白屏问题都是可以通过开机尝试法解决的,但是NG不稳定的系统使恢复也具有随机性,所以请耐心和细心尝试,对于无
法自己修复的真白屏就只能通过刷机解决了,下面我们就为大家介绍NG和QD白屏终极制胜武器——GRIFFIN软件维修仪。
电池
关于手机 电池 (由于目前市面上手机几乎全部采用锂离子 电池 供电,在此不讨论镍氢、镍铬类 电池 ,下文所说的“ 电池
”全部代表手机使用的锂离子 电池
)的使用,太多的文章做过介绍,太多的网友做过讨论,但直到今天在各个手机论坛依然看见很多错误的使用指导以及相关的提问!今次就和大家讨论一下如何使用
好手机的 电池 。
一、关于 电池 激活
首先要说的是关于“ 电池 激活”的问题,很多人包括手机经销商和个别手机厂家一直强调:“新买手机,头三次充电一定要充满十几个小时”。这个观点本人不敢苟同。原因如下:
不妨先了解一下究竟什么叫“ 电池 激活”?锂 电池 的确需要一个激活过程,但这个程序是在生产厂家进行,没有理由更没有必要让用户去激活 电池 。让我们从制造角度看看锂 电池 在生产中如何激活的,下面是典型的理 电池 生产流程:
1: 电池 壳灌装电解液
2:封口
3:化成(激活的过程:对 电池 进行恒压充电,然后放电,如此进行几个循环,使电极充分浸润电解液,充分活化,以容量达到要求为止)
4:分容(测试 电池 的容量选取不同性能(容量)的 电池 进行归类,划分 电池 的等级,进行容量匹配等)
5:帖标签出厂
通过上面的过程我们可以看到理 电池 的激活过程是在生产步骤3完成的,个别 电池 的生产流程甚至是先激活再封口的,所以 电池
的激活对用户来说是“不可能完成的任务”。就像有人说要给电脑硬盘低级格式化,道理也是一样的,硬盘低格是封装前用特别的设备对盘片进行磁微粒进行排序的
过程,试问除了厂家谁能完成这样的工作?说远了呵呵,继续说 电池 。
从原理上我们已经知道 电池 出厂前已经进行了激活,那关于头三次使用要充满多长时间的观点自然站不住脚,理 电池
最大的一个优点就是没有记忆效应,随用随充电,以往对镍铬/镍氢 电池 进行的深度放电和充电是为了消除它的记忆效应,这两种 电池
都需要用尽电再充电,锂 电池 是不需要的,所以到达我们手里的 电池 不管有多少电,拿来就可以用,充电也是随时可以进行。
有一点值得注意的是锂 电池 出厂到用户手中可能需要一段时间,少则个吧月,多则半年一年,短时间内出产的 电池
电极不会产生钝化现象,出厂时间过长的 电池
,电极就可能钝化,这个时候对它进行几次完全的充电以达到活化电极的目的也是必要的,也有人说这叫二次激活,也就是为什么有厂家和经销商建议我们头几次要
充电多长时间。关于是否需要二次激活,从实际测试来看,出厂3个月以内的 电池 ,对它进行深充深放的循环处理,其意义几乎没有, 电池
的容量并不会因此增加。
最后我们得到的结论是:新买的手机 电池
不需要激活,没有多少人有时间做到头几次充满十几个小时,特别是只有一部手机的朋友,那样意味着你有段时间无法使用手机。 电池
及手机生产厂家对这些问题应该早有考虑。但如果你购买到的是出厂很久的 电池 ,(建议最好不要买,因为过久出厂的 电池
如果存储环境不当,就算多少次充放电循环也不能挽回其容量的下降)对其进行必要的充放电循环是合理的。
二、 电池 的使用和保养
锂 电池 的特性决定了它的使用是很方便的,不需要在乎是不是用完了再充电。但锂 电池
是有寿命的,衡量标准一般都是充放电次数,所以建议大家电用完了,至少是电量用的差不多的时候再充电,以此减少充电次数,对 电池
寿命的延长是否有效还没有科学的定论。可以肯定的是没有害处,我的QD 电池 就是这么用的,呵呵!
对锂离子 电池 充电一定要慎用座充,特别是经销商送的和街边买的那种座充,切记!切记!不是万不得已不要使用这个东西,可以毫不夸张的说他们就是 电池 杀手!至于原因,稍后另一篇专门解释锂离子 电池 充电器的文章详细介绍。
还有最重要的一点锂 电池
怕什么,怕高温,特别怕高温放置,就是高温存储下不使用,这样做的结果是寿命和容量大打折扣。举例来说买QD时经销商送了一块5C的 电池
,QD本身配备6C 电池 一块,有人认为把原装电收起来,先用送的代用电,等代用 电池
用到寿命不行的时候再拿出原装电用,表面上看这样很划算,其实对于锂 电池
,这样的用法是极度错误的,就算是你把原装电放在常温下保存,等你的代用电寿命不行的时候拿出原装电时你会发现原电待机和使用时间可能还不如代用电了。其
实这也就是说到了 电池 的保养,最好的保养就是经常用它,我的方法就是原电和送的电交替使用。
另外锂 电池 不要和钥匙等金属物放置在一起,短路的结果可能是爆炸!需要长时间存储而不使用的锂 电池
,如果有条件你可以把它密封在尽量不要有太多空气的塑料袋里,然后放入冰箱,这样对其寿命延长是有一定帮助的!最后不要尝试打开锂 电池
,对你的身体没有任何好处,呵呵!
三、购买建议
对于需要购买锂 电池 的朋友,我个人的购买建议是:
1、我们购买 电池 一定要到正规的店,不要贪图便宜购买小店的没有品牌的 电池 ,这些 电池 就算不是用镍氢/镍铬冒充的锂离子 电池
,质量也是不敢恭维的,不但使用时间和寿命短,而且有安全隐患,出厂时间更不得而知,换句话说,出厂时间过长的锂离子 电池
,假设它的质量是很好的,如果存储在30度以上的环境中,一年后到达你手中,这块 电池 的可以使用的容量最多就只有它出厂时的6成了。
2、正规厂家生产的锂 电池 一般会标注出厂日期,购买正规的产品也要选择出厂日期最近的。避免长期放置产生的电极钝化,容量下降。
3、永远的道理一分价钱一分货,锂 电池 价格不是高不可攀但绝对不会是白菜叶价钱,就拿QD 电池 来说,能达到6C原电容量和质量的 电池 ,售价不会低于50元!
4、购买 电池 不要迷信原电,原电的质量是很好,但未必能好过兼容 电池 ,很多品牌的代用锂 电池
质量和寿命都是不错的,只要厂家愿意完全可以制造出比原电质量、容量及寿命指标更好的 电池 。一些JS正是掌握了我们非原电不买的心理,大肆制造假冒
电池 ,打的可都是原装电的牌号,即使是真原电,也被KF提高价格使物不超所值。所以自要认准型号,可以购买各种容量的代用 电池 。
5、最后一点,还是要强调,不要去街边和一些小店购买锂 电池 ,据我所知,正是由于锂 电池 生产工艺虽复杂但可从简的特点,一些山寨厂的生产工艺极度简化的垃圾产品都是在这样的地方销售。
我爱我的QD,我相信善待 电池 就是善待QD!!
1,如果3楼的方法不行,请看下面的内容
2,换一张SIM卡插到你手机,再进入你的手机的短信里,然后退出关机,再把你自己的SIM卡放进去,就OK了!(如果不可以请看下面的内容)
3,当进入短信功能显示出mac错误时,不用管他,再次进入短信功能,马上猛按方向键的下键(要在还没弹出mac错误信息之前按),就能顺利进入短信功能了。(如果不可以请看下面的内容)
5,①在手机出现“MCE”错误的时候,说明你的信箱里的短信容量过多了,建议删除一些。
②如果你不幸的发现,你的收件箱已经无法打开了。我这里有两种解决办法:
1.用别人的手机给你的手机发一条短信,问题有可能会解决。然后立即清空收件箱。
2.安装软件message saver(短信保存软件),可通过套件或读卡器拷贝到手机或卡上以后用EFILEMAN 或 SELEQ安装。安装完毕以后立即执行,并在后台运行。然后进入短信菜单就会恢复正常。然后立即清空收件箱。
③1.如果上述方法无法解决,请拆除MMC卡,在无卡状态下进入收件箱,将储存介质改为"手机"。然后再将MMC卡插回手机,将储存介质改回为MMC卡就可以恢复正常了。然后进入短信菜单就会恢复正常。然后立即清空收件箱。
2.如果在操作红色步骤的时候,无法进入短信菜单,请找另外一步手机给自己发一条短信,在阅读短信的同时,也可以进入设置菜单了。
补充2点:
1.如果出现MCE错误,用菜单里的信息进入。如果不行,用收藏夹里的收件箱进入。不行的话看第2条。
2.如果急于查看信息,可以输入*118*11#,然后拨出。请求查手机积分。这样1860会给你发送一条积分信息来。多半就可以解决了。如果还不行
就多发两次。一定行的。联通的号也可参照这一方法。就是要浪费两三角钱。不过在找不到人给你发消息的情况下,这个办法最方便快捷。
再作些补充:在出现MCE错误的时候,如果是要发送短消息,有两个方法可以不用进入“信息”而达到发送消息的目的:1。在电话模式下直接输入对方号
码,按下左功能键选择发送—短消息就可以直接进入发信息的界面了!2。在名片夹里找到要发送信息的号码,也是按下左功能键选择写信息—短信息即可!以上两
个方法的优点是:在出现“程序已关闭
MCE”错误的时候,可以几乎100%能成功发出短消息。缺点是无法从根本上解决这个错误。一旦退出就会回到原来的界面。
Java 软件:把 jar 文件复制 mmc 卡根目录下,然后用 seleq 打开,手机会自动安装。安装完后会在 mmc 卡上自动生成一个 jad 文件,它和安装的 jar 文件都可以删除。安装好的软件在“百宝箱”里运行。
首先,当然要有一个蓝牙适配器(有内置蓝牙笔记本电脑的不在此列)。现在有很多10米甚至100米的蓝牙适配器,其实10米就够了,qd的蓝牙还没100米的这么强劲,100蓝牙适配器基本上属于资源浪费了,当然你要为将来做准备也是可以的。
将蓝牙适配器接上电脑,安装驱动,还要记得安装nokia pc suite(pc套件,随机光盘上有),安装完毕后,右下角任务栏会出现蓝牙标志和pc套件的标志。
进入工具--设置--连接设置,确定,会“显示未定义接入点,现在定义?”,点“是”,“连接名称”随便起一个就行,默认为“连接”,剩下的除了把
“接入点名称”改为你的计算机名外,别的都可以不动。计算机名是什么?在你的电脑桌面上右击“我的电脑”,点属性,剩下的自己看吧。点返回,可以看到接入
点列表里出现了“连接”(当然你起的什么连接名称,这里就会显示什么)。
接着来,电脑上的蓝牙准备好了,当然要启动手机蓝牙,然后双击电脑桌面右下角的mrouter,就是那个pc套件的图标,在弹出的com口都选上,很快就会显示连接成功。
目前有三种情况:
其一,下载解压后得到 system 文件(如 fifa2004 )将 system 文件夹下的 apps 和 Libs 两个文件夹,复制到
mmc 卡的 system 文件夹下,复制的时候需要覆盖原文件夹。 复制完成后将卡插入 QD,QD 的桌面自动出现里 fifa2004
的图标。不用我说了吧,赶紧爽去吧。
其二,解压后得到一个文件夹例如 RAYMAN3 文件夹(雷曼 3 ),只要将文件夹复制到 mmc 卡 systemapps 下即可。插卡桌面自动出现雷曼 3 的游戏图标。
其三,利用 blzinstapp 程序安装 .blz 破解版游戏。
首先,安装 blzinstapp.sis (方法参照: sis 软件的安装。注意将 blzinstapp 安装在 mmc 卡上以节省手机内存。)
将解压文件如 tonyhawk.blz (职业滑板)复制到 mmc 卡的根目录。
运行 blzinstapp 可以看到 tonyhawk.blz 文件选择 options > Install 进行安装,安装的画面可能会很长要耐心点。我装了十几个都没有的死机的现象。安装后在桌面上运行游戏图标即可。
3、Java 软件:把 jar 文件复制 mmc 卡根目录下,然后用 seleq 打开,手机会自动安装。安装完后会在 mmc 卡上自动生成一个 jad 文件,它和安装的 jar 文件都可以删除。安装好的软件在“百宝箱”里运行。
方法1::用SELEQ到CSYSTEM DATA 下删2个文件,
第1个是 ip_config_x2.sys
第2个是 utility_dump.dat
然后把 SMARTMOVIE 也卸载了重新安装。
方法2:备份一下出错前原机的date文件夹,出错后删除date,用原来的date文件夹覆盖到c盘
方法3:为出错状态下,到存储卡选项里备份手机内容。出错后,恢复即可。
方法4:先去他官方(http://www.lonelycatgames.com/)下载一个未注册版的安装,删除后再安装确解版的
方法5:老版C:SYSTEM DATA 中的101feaf3.bin 101feaf8x.bin删了就可以了。下一次出现死机还是删这两个文件就可以了。先开始还以为只有我有此情况,后来看到有其他人也遇到了。
方法6:卸载新版本,装老版,然后再装新版本。如果不能解决,多换几个版本。
smartmovie 播放错误修复方法7大方法:
方法1::用SELEQ到CSYSTEM DATA 下删2个文件,
第1个是 ip_config_x2.sys
第2个是 utility_dump.dat
然后把 SMARTMOVIE 也卸载了重新安装。
方法2:备份一下出错前原机的date文件夹,出错后删除date,用原来的date文件夹覆盖到c盘
方法3:为出错状态下,到存储卡选项里备份手机内容。出错后,恢复即可。
方法4:先去他官方(http://www.lonelycatgames.com/)下载一个未注册版的安装,删除后再安装确解版的
方法5:老版C:SYSTEM DATA 中的101feaf3.bin 101feaf8x.bin删了就可以了。下一次出现死机还是删这两个文件就可以了。先开始还以为只有我有此情况,后来看到有其他人也遇到了。
方法6:卸载新版本,装老版,然后再装新版本。如果不能解决,多换几个版本。
方法7:如果以上的都不行(只有万分之一的可能,RPWT),格机格卡后重装肯定会好的
在左边的Video settings里,选上Landscape表示要横屏播放电影;Reduec frames是指自动将原视频文件的帧频减半,一般都要选上,不然压出来的文件会不够流畅;Codec选择刚刚安装上的XviD encoder;下面的Bitrate是指码率,越高视频的效果就越好,但体积也越大,一般选择128kbps,高了容易出现掉帧的现象,低了效果又比较 差。在Audio settings里,Enable是指允许播放声音,打上钩;Force mono是指将文件的音频转换成单声道,这样有助于让画面更流畅,当然,因为6600只支持单声道输出,所以6600的用户要记得打上钩;下面的 Frequency和Bitrate一般也不用设置得太高,一方面会使压出来的文件增大,另一方面容易使画面不够流畅,所以选择22050Hz和 24kbps就比较合适了,不过经过测试22050HZ的效果不太理想,完全还可以再提高两个档次以便得到更好的音效;最底下的Volume boost(%)是指将音量调解成原文件的百分之几,大小要视原文件的音量而定,一般选择250%左右就足够了。左边的Subtitles项目是导入字幕 用的,可以到国外的一些专门提供字幕的网站找到现成的电影字幕文件。不过如果原视频文件的字幕在全屏播放时能看清也就没有必要再去找字幕了。
进了"功能表"后选"工具"
"工具"->"设置"->"游戏手机设置"->(按两下方向键的右)"连接设置"
1)"接入点"按左键->"新增接入点"->"使用默认设置"
2)建好以后,在刚建的连接,按"选项"(左键)->"修改"
3)"连接名称"(可以随意改),我改成中国移动 GPRS
"数据承载方式"= GPRS
"接入点名称"=cm wap
"用户名"=无
"提示输入密码"=否
"密码"=无(你会看到四个星号,这一项不须设定)
"鉴定"=普通
"主页"=http:// wap .monternet.com
"网关IP地址"=10.0.0.172
"连接安全"=关
"连接类型"=永久
4)这几项都完成后,继续按"选项"(左键)->"高级设置"
5)"高级设置"里
"游戏手机IP地址"=自动
"主域名服务器"及"次域名服务器",不用填写
"代理服务器地址"=10.0.0.172
"代理端口号码"=80
6)回到"连接设置"->" GPRS "里的接入点可能还要设置成刚"连接名称"一样
smartmovie 播放错误修复方法7大方法:
方法1::用SELEQ到CSYSTEMDATA 下删2个文件,
第1个是 ip_config_x2.sys
第2个是 utility_dump.dat
然后把 SMARTMOVIE 也卸载了重新安装。
方法2:备份一下出错前原机的date文件夹,出错后删除date,用原来的date文件夹覆盖到c盘
方法3:为出错状态下,到存储卡选项里备份手机内容。出错后,恢复即可。
方法4:先去他官方(http://www.lonelycatgames.com/)下载一个未注册版的安装,删除后再安装确解版的
方法5:老版C:SYSTEMDATA中的101feaf3.bin 101feaf8x.bin删了就可以了。下一次出现死机还是删这两个文件就可以了。先开始还以为只有我有此情况,后来看到有其他人也遇到了。
方法6:卸载新版本,装老版,然后再装新版本。如果不能解决,多换几个版本。
方法7:如果以上的都不行(只有万分之一的可能,RPWT),格机格卡后重装肯定会好的
sis 游戏安装 方法:
方法1 把sis文件放在卡的根目录,用 工具-》程序管理-》选中游戏sis文件-》选项-》安装
方法2 sis文件随便放在卡上任意位置(只要你能找到),用seleq选择sis文件-》选项-》文件-》开启 或是 用seleq选择sis文件-》直接摁 确定键(√键)-》开启
java程序(游戏)安装方法:
把***.jar程序拷到卡上随便位置,运行seleq,查找并选中***.jar-》选项-》文件-》开启
java程序(游戏)使用和卸载方法:
使用:附加功能-》百宝箱-》选中程序-》确定键(√键) OR 选项-》打开
卸载:方法1 附加功能-》百宝箱-》选中程序-》选项-》删除
方法2 附加功能-》百宝箱-》选中程序-》摁 C 键 -》选择 是
symbian S60平台手机病毒查杀攻略
估计这是目前为止最全的介绍病毒的文章,讲述了所有经symbian s60 系统传播的病毒介绍和杀除方法!希望大家能够防范和保护自己的爱机!而且随着病毒源代码的地下公开,以后会有越来越多的病毒出现。
首先,是大家熟悉的Cabir系列,不同的Cabir病毒,有不同的处理方法,介绍如下:
Cabir.A
Cabir是通过蓝牙传播复制病毒来感染symbian s60平台手机的!
它通过蓝牙连接,以短信形式发送cabir.sis手机的收件箱,这个文件含有蠕虫病毒。当用户点击cabir.sis并安装时,蠕虫病毒就被激活,并开始通过蓝牙寻找感染新的手机或其他设备。当它找到另外的蓝牙设备时,就可是发送cabir.sis!
注意,Cabir蠕虫病毒只能感染支持蓝牙,并且蓝牙状态为可见的手机,而且一旦感染,再关闭蓝牙已经不起作用,所以一般情况下,不要开蓝牙。
感染后处理方法:
用seleq或fileman删除以下文件:
c:systemappscaribecaribe.rsc
c:systemappscaribecaribe.app
c:systemappscaribeflo.mdl
c:systemrecogsflo.mdl
c:systemsymbiansecuredatacaribesecuritymanagercaribe.app
c:systemsymbiansecuredatacaribesecuritymanagercaribe.rsc
Cabir.B
Cabir.B是Cabir.A的一种不同的镜像,和Cabir.A最重要的不同点是,Cabir.B在开机后显示不同的文本。
Cabir.A显示文本是"Caribe-VZ/29a",而Cabir.B显示的就是"Caribe".
还有一种重新打包的Cabir.B,也是sis文件形式,当病毒被装到不同的文件夹时,显示popup。这种Cabir.B病毒和最初的Cabir.B病毒没有不同,就是冲洗打包时设置不同而已。
感染后处理方法同Cabir.A
Cabir.C
Cabir.C是一种不同的Cabir.B的镜像,和Cabir.B最重要的不同是Cabir.C在安装时显示的是MYTITI.SIS。
感染后处理方法同Cabir.A
Cabir.D
Cabir.D也是一种不同的Cabir.B的镜像,和Cabir.B最重要的不同是Cabir.C在安装时显示的是[YUAN].SIS。
感染后处理方法同Cabir.A
Cabir.E
Cabir.E也是一种不同的Cabir.B的镜像,和Cabir.B最重要的不同是Cabir.C在安装时显示的是Ni&Ai-.SIS。
感染后处理方法同Cabir.A
Cabir.Dropper
Cabir.Dropper是把Cabir.B, Cabir.C 和 Cabir.D都安装到手机的sis安装文件,让蓝牙失去控制。
最初版本的Cabir.Dropper 被命名为Norton AntiVirus 2004 Professional.sis 。
Cabir.Dropper安装不同Cabir变种到手机文件系统的不同地方,而且可能替换第三方应用程序文件。所以一旦用户安装了这个第三方程序,病毒就会替换这个程序文件,并且丢失图标。
如果用户点击了被病毒替换的图标,病毒就会替换程序,开始传播到其他的手机。
感染后处理方法:
删除以下文件:
c:images
c:soundsdigital
c:systemapps
c:systeminstall
c:systemrecogs
c:systemappsbtui
c:systemappsfexplorer
c:systemappsfile
c:systemappsfreakbtui
c:systemappssmartfileman
c:systemappssmartmovie
c:systemappssystemexplorer
c:systemapps[yuan]
Cabir.H
它是以上Cabir病毒的重新组合,并且修改了复制路线,比以前复制传播的更快,用户安装它时,文件名为velasco.sis。
Cabir.I 和 Cabir.J 和 Cabir.K
是Cabir.H的镜像,但使用了不用的编码编写。
Cabir.L
Cabir.L是Cabir.B的镜像,但是它和Cabir.B不同的是,安装时,它的名字是Skulls.SIS 而不是Cabir.sis。但是注意,Cabir.L仍然是Cabir病毒而不是Skulls病毒。
诺基亚N-Gage QD实现MP3铃声方法
所需软件:UltraMP3;增强情景模式:eProfiles
设置:在eProfiles中“选择”--“标准”---“个性化”----“运行应用程序”,再选择“UltraMP3”;
然后在计划任务中新建一个任务,设置如下:开始时间(闹铃时间);切换情景模式选“标准”;下面选每天 ;返回选“没有”;(注意,这个时候UltraMP3一定要正常运行)
我们可以利用增强情景模式定时切换,切换时自动运行了UltraMP3程序,而UltraMP3又自动播放了MP3(如果你选择了循环播放,那当有来电时就会不停的唱下去了,除非你接听或挂断)。
N-Gage QD典型问答综合
常有朋友在论坛问一些基础且重复的问题,为了方便起见,我把一些典型问题整理了一下,希望新手们看一看
汉化和破解补丁怎么使用?
sis是安装主文件,先传到手机里安装好,rsc文件是汉化补丁,只要把它覆盖到安装目录下,即e:systemapps下相应的目录里,替换原有同名文件即可。有时还有个app文件,一般是破解文件,和rsc文件一样操作
请问现在如果把系统全删掉。用什么把系统再传进手机啊。用数据线还是蓝牙
系统是固化在ROM里的,不能删除,只能格式化手机,从ROM重新读取数据到机身闪存,只要待机下输入*#7370#,输入保密码12345即可,所有的工作自动完成,不需要你操心
开机提示存储空间不足,无法接受信息,请先删除一些数据,这数据怎么删啊?搞不太懂,高人指点下啊!
可放心删除的有:
csysteminstall下的文件
csystemappsxxxx下的文件,xxxx为自己安装的软件
cnokiaimages下的文件
大哥们,告诉小弟怎么看电影啊?只要把电影下到mmc上就行了吗??要不要装什么东西啊?
不同的播放器支持不同的视频格式,realone支持rm和3gp格式,smartmovie支持avi格式琾vplayer支持mp4格式,mobiclip支持mo格式。手机播放前还必须转换为合适的分辨率,对码率也是有要求的
怎么样才能把"中国移动的"几个字改图标啊!????
logo可以用seleq换,选择"set as operator logo",重起即可;或在c盘的systemapps下建一个phone的目录,然后在phone下建一个oplogo的目录,再把97*25的的图片(必须是bmp格式)放进去改名为460_0_0.bmp(这是移动,而联通用460_1_0.bmp)
欧版和行货差别在哪里?
欧版是水货,没保修,行货全国联保;欧版充电器是ACP-12U或E,行货是ACP-12C;欧版配件和说明书都是英文,行货是中文;欧版电池不标记容量,水货有容量标记;欧版键盘没有笔画,或是后来刻上的,行货键盘有笔画;欧版送一张游戏卡,行货是一张64MB的MMC卡,预装了一些游戏和软件
我的机子程序乱了 请问怎么格机 我的是欧版的 格机后会少什么 那位大哥告诉我 谢谢~~
待机下输入*#7370#格式化手机,格机后,会删除机身内存里所有非系统数据,包括游戏软件的注册信息,设置和存档以及一些备份,短消息和名片夹也会全部删除。需要的话,先做好数据备份再格式化。格式化会从ROM重新读入系统数据,恢复出厂时的干净软件环境
在images文件夹里,还有一个_PAlbTN隐藏文件夹,是干什么用的呀?能删除吗?
可以删除,这是缩略图的文件夹,在图象管理里中看图片,打开过的图片都会在这个文件夹下的_PAlbTN目录里多出其相应的缩略文件,按缩略图浏览时就可以显示
请问5c和6c电池的区别是什么呢?
触点相同,但6C比5C厚,6C容量为1070mAh,5C有850,900和970的容量
在网上下了个MD模拟器,但是进入后找不到ROM文件阿,而且在读卡器上不知道应该把ROM放在那里,那位能帮忙解决一下,谢谢
MD的模拟器是PICODRIVE,游戏ROM后缀为SMD,放在存储卡任何位置都可以,但路径和文件名不能有中文
掌上词霸怎么关闭?
长按菜单键然后按C键关不了,掌上词霸这个软件设计的初衷就是要经常在后台运行,所以必须要在查完一个单词后,按左功能键,选择退出才可以
模拟器死机了~应该怎么做才是最好的解决方法呢?直接把电池拿出来可以吗?
如果机器没有反应,按关机键也不行,就只能拔电池了。但有可能是假死,机器一时无响应,可以先等一下
请问行货机电池的生产厂家应该是哪里????
诺基亚手机大陆行货原配的电池有三个厂家生产:深圳华强三洋和珠海松下,少数是北京三洋
我输入*#0000#后看V4.10是版本号吧,是最新的吗??还有下面两行09-09-2004是生产日期吗?RH-29是什么意思啊??
4.10是最新版本,09-09-2004是软件版本发布日期,RH-29是机型型号
用smartmovie放电影时,显示APP CLOSD SMAREMONVIE,怎么回事啊?
删除csystemdata文件夹中的三个文件:dualmode_fea8.xdb,ip_config_x2.sys,utility_dump.dat,然后把smartmovie卸载,重新安装smartmovie。老版csystemdata中的101feaf3.bin和101feaf8x.bin删了就可以了。最好是安装完了就备份C盘文件,出了错就覆盖回去
QD可以玩哪些模拟器?
QD可以玩FC,SFC,GBC,MD,先装模拟器,再把ROM放进存储卡。FC模拟器主要有yewnes和vnes,前者画质非常好,但是声音模拟很差,速度较慢,并且不能自定义按键;后者画质差一些,声音模拟很好,速度快,支持自定义按键;GB模拟器可以用VBOY或GOBOY,速度不错,但不能全屏,声音模拟不好;MD模拟器可以用Picodrive,速度快,但是画面不是很好;SFC模拟器用VSun,画面好,但还是新出的,有待完善
请问:有人用水货QD吗,和行货有多大差距?(稳定性方面)
刷了机和行货使用一样,稳定性没有区别。水货不刷机是外文的,不支持中文的输入和显示,刷了行货简体版本才会拿出来卖
小弟问个问题啊
1.闹钟只能设置第二天的么?当天或者后几天的呢>?闹钟铃声怎么选?有什么好的闹钟软件?
2.我发现按关机键选无声后短信和来电还是有声音,这个怎么设置
3.键盘右上角的"铅笔"键是干吗使用的?
1、关机闹钟要每天设置,可以用软件,如增强情景模式,HANDYCLOCK等很多
2、不在于你选哪个情景模式,而在于情景模式你是怎么设置的
3、编辑键,用来调出编辑菜单,切换输入法,多项选择,强行开机
请教:*.gbc的游戏用什么软件能玩?
是GBC模拟器游戏,可以用VBOY或GOBOY,如果用VBOY,ROM放在evampentgbroms下,如果用GOBOY,ROM放在egoboy下
请问游戏有几个格式,都分别怎样安装??
SIS是SYMBIAN特有的安装格式,安装SIS,只要把SIS文件放到存储卡根目录,然后在程序管理里选择安装
JAR是JAVA的安装文件,安装JAVA,只要把JAR文件放到存储卡根目录,然后用SELEQ打开安装,之后到百宝箱里找到运行
NG专用游戏基本上都是直接复制版本,打开压缩包,把system文件夹覆盖到E盘根目录即可,如果文件夹就是一个游戏的名字或6R**的话,就复制到esystemapps下,如果有apps,libs和programs等文件夹,就都复制到esystem下
我刚买QD,现在不知道是买读卡器好,还是蓝牙好,
读卡器和蓝牙作用不同。读卡器用来传输大文件和文件夹,而蓝牙用来传输小文件和配合PC套件同步,所以读卡器是必须的,蓝牙适配器可以根据自己的需要购买
QD专用游戏怎样安装?请教高手
NG专用游戏基本上都是直接复制版本,打开压缩包,把system文件夹覆盖到E盘根目录即可,如果文件夹就是一个游戏的名字或6R**的话,就复制到esystemapps下,如果有apps,libs和programs等文件夹,就都复制到esystem下即可。如果是blz后缀,就用Blzinstapp安装
csystemapps下的文件可以删除吗?
软件安装后,在csystemapps下回有个目录产生,里面主要是软件的设置记录和存档的信息文件,如果删除了软件,这个文件夹也可以删除。之后还是会留下一些垃圾文件的,如果不清楚,不要随便删除系统盘里的文件,容易使系统出错
弱弱的问一句,什么是主题?和S60的有啥不一样
主题包括了待机图片,菜单图案,图标形象等一系列的图片文件,它可以集中这些文件,你只要切换一下主题,就可以马上更改这些图片文件,这样就不用你专门去设置待机图片之类的了!另外你可以做一些个性化的主题,比如你是AC球迷,就可以做一个全是AC米兰图片的主题,这样你的手机里哪里都是AC的图片了,看起来就很过瘾
为什么一个才5MB的rm文件NG放不了,提示文件太大了,video clip too large?
这并不是指文件体积太大,而是规格不符合手机要求。用REALONE播放的RM视频,需要先转换才可以在手机里看,否则可能不能播放,或只有声音没有图象。转换工具一般用Easy RealMedia Producer或Batch Real Producer,分辨率不超过176*144,对码率也是有要求的
能不能用组装电池?
组装电池是可以用的,但要选择品质比较好的组电。不合格的组电做工粗糙,电池壁薄,使用时间长可能发生危险;另外由于电路偷工减料,性能也没有原电好,电量低的时候,电压便急剧下降,运行大程序或使用通话功能时,容易自动关机
我的E盘没有system文件夹,怎么办?
看不到这个文件夹那是因为SYSTEM是隐藏属性的,你进入WINDOWS窗口的上面的工具--文件夹选项--查看--高级设置--显示所有文件和文件夹就可以了,然后你用读卡器操作MMC卡的时候就可以看到SYSTEM文件夹了
或用SELEQ,打开SELEQ,把光标移动到SYETEM文件夹上,OPTIONS-FILE-PROPERTIES-ATTRIBUTE-HIDDEN-选择NO,就取消了SYSTEM的隐藏属性
诺基亚N-Gage QD游戏手机之新手十五大问题
1.问:QD的软件和游戏是什么格式?
答:分别有SIS,JAR,还有NG特有的BLZ和“SYSTEM文件夹版”
2.问:软件怎么安装?
答:SIS有两种最简单的,一是直接用蓝牙发送到QD,QD收到会以短信形式存在,并自动开始安装,二是用读卡器把SIS拷贝到MMC的跟目录,在QD的程序管理里安装。JAR步骤同上,要注意的是不需解压,直接把*.JAR的文件弄到QD上就可以。
3.问:QD的游戏要怎么安装?
答:SIS和JAR安装同问题2。BLZ格式,首先需要安装一个BLZINSTAPP的程序,接着把*.BLZ文件拷贝到MMC根目录,打开BLZINSTAPP,就可以看到你要装的游戏BLZ,接着按INSTALL就可以安装到QD上,注意的是MMC要有一定的空间。“SYSTEM文件夹版”,直接用读卡器把SYSTEM复制去你的MMC卡,覆盖就可以了。
4.问:qd各种图片的尺寸是多少。
答:全屏是176×208,待机是176×132,LOGO 是97×25
5.问:mms(多媒体信息服务)如何设置?
答:1.首先在“功能表-工具-设置-连接设置”里创建一个数据承载方式为gprs、接入点名称为Cmwap、网关ip地址为10.0.0.172、端口80。安全连接为关。http://mmsc.monternet.com的接入 点,这个接入点需要开通gprs服务。
2.设置mms:功能表-信息-选项-设置-多媒体信息;然后可以如下设置: 首选连接:选择刚刚创建的接入点;次选连接:不选择,或是选择刚刚创建的另一个接入点;其它设置项根据自己的需要设置,建议有效期设置为最长时间,图像大小设为小。
6.问:出现短信MCE错误如何解决呢?
答:关机 --> 换一张SIM卡 --> 开机,进短信,没问题,关机 --> 换回原SIM卡,开机,问题解决。
7.问:qd可以看动态视频吗,怎么看?
答:可以。最常见的格式 3GP、MP4、RM,AVI3GP和RM格式用REALONE可以看,REALONE可以安装光盘里的,也可以装其他版本,个人推荐7650版,MP4格式可以用PVPLAYER看,AVI可以用SMARTMOVIE看
8.问:QD能够使用的闪存卡都是什么规格的?
答:QD只支持MMC卡,不能使用SD卡。MMC支持的分别有16M 32M 64M 128M 256M 512M,MMC品牌个人推荐PQI
9.问:QD怎么实现播放MP3?
答:可以装MP3GO,MP3PLAYER或者ULTRAMP3等软件实现。个人推荐ULTRAMP3
10.问:如何安装破解软件或者游戏?
答:下载的破解软件通常有3种。一种是直接的破解的SIS文件,直接安装就可第2种是一个SIS,里面还有个*.APP的文件。这种首先安装SIS,接着把APP文件拷贝去你所安装的软件目录覆盖原文件就可以了。第3种是一个SIS,还有一个KEY的EXE文件,首先安装SIS,接着在电脑里打开KEY的应用程序,输 入你的QD的IMIE手机串号,下面就会生成一个注册码,接着把注册码输入进QD软件就可以。
11.问:QD支持什么格式的铃声和如何使用?
答:QD用的最普遍的就是WAV和MIDI,不支持MP3铃声,WAV和MIDI文件放在手机或MMC卡里的SOUNDDIGITAL文件夹里,在情景模式里选择就可以了。
12.问:如何格式化QD?
答:在待机下按*#7370#,默认密码12345
13.问:QD如何卸载程序和游戏?
答:程序在程序管理里卸载,JAR程序或者游戏在百宝箱里卸载,NG游戏需手动删除。
14.问:QD能看电子书吗?
答:可以,QD本身可以直接打开TXT文件,也可以通过安装电子书软件来看。
15.问:QD支持来电大头贴吗?
答:支持,但自带的不好用,可以装FSCALL等软件效果会比较好。
诺基亚N-gage QD的GPRS和彩信功能设置
诺基亚N-gage QD的GPRS和彩信功能设置
一、关于GPRS的设置,首先要确定已经开通GPRS服务
进入工具-设置-连接设置-接入点
1新增一个接入点,连接名称随便设
2数据承载方式为GPRS
3接入点名称为cmwap(一定要小写)
4用户名 无
提示输入密码 否
密码 不用设置
鉴定 普通
主页 http://wap.monternrt.com(很重要,和彩信设置相区别的地方)
网关ip地址 10.0.0.172
连接安全 关
连接类型 永久
完成上述后在按“选项”进入“高级设置”
游戏手机ip地址 自动
主域名服务器 0.0.0.0
次域名服务器 0.0.0.0
代理服务器地址 10.0.0.172
代理端口号码 80
二、彩信设置,彩信设置首先要开通GPRS
然后进入“连接设置”增添新的默认接入点
连接名称:随便
数据承载方式:GPRS
接入点名称:cmwap (一定小写)
用户名:无
提示输入密码:否
密码:(不输入)
鉴定:普通
主页:http://mmsc.monternet.com(这里是和GPRS设置的主要区别)
网关IP地址:10.0.0.172
连接安全:关
连接类型:永久
完以上后进入“信息”
选项-设置-彩信
将“使用的接入点”改为刚才设置的彩信连接名称
编辑器: vi
vi 的工作模式
编辑模式
插入模式
命令模式
shell 切换
选项设置
vim 和 gvim 的高级特色
1.6.1 vi 的工作模式
Vi 在初始启动后首先进入编辑模式,这时用户可以利用一些预先定义的按键来移动光标、删除文字、 复制或粘贴文字等。这些按键均是普通的字符,例如 l 是向右移动光标,相当于向右箭头键,k 是 向下移动光标,相当于向下箭头键。在编辑模式下,用户还可以利用一些特殊按键选定文字,然后 再进行删除、或复制等操作。
当用户在编辑模式下键入 i, a, o 等命令之后,可进入插入模式;键入 : 可进入命名模式。 在插入模式下,用户随后输入的,除 Esc 之外的任何字符均将被看成是插入到编辑缓冲区中 的字符。按 Esc 之后,从插入模式切换到编辑模式。
在命令模式,Vi 将把光标挪到屏幕的最下方,并在第一个字符的位置显示一个 :(冒号)。这时, 用户就可以键入一些命令。这些命令可用来保存文件、读取文件内容、执行 Shell 命令、设置 Vi 参数、以正则表达式的方式查找字符串或替换字符串等。
1.6.2 编辑模式
1. 移动光标
要对正文内容进行修改,首先必须把光标移动到指定位置。移动光标的最简单的方式是按键盘的上、下、左、
右箭头键。除了这种最原始的方法之外,用户还可以利用 vi 提供的众多字符组合键,在正文中移动光标,迅
速到达指定的行或列,实现定位。例如:
k、j、h、l 功能分别等同于上、下、左、右箭头键
Ctrl+b 在文件中向上移动一页(相当于 PageUp 键)
Ctrl+f 在文件中向下移动一页(相当于 PageDown 键)
H 将光标移到屏幕的最上行(Highest)
nH 将光标移到屏幕的第 n 行
2H 将光标移到屏幕的第 2 行
M 将光标移到屏幕的中间(Middle)
L 将光标移到屏幕的最下行(Lowest)
nL 将光标移到屏幕的倒数第 n 行
3L 将光标移到屏幕的倒数第 3 行
w 在指定行内右移光标,到下一个字的开头
e 在指定行内右移光标,到一个字的末尾
b 在指定行内左移光标,到前一个字的开头
0 数字0,左移光标,到本行的开头
$ 右移光标,到本行的末尾
^ 移动光标,到本行的第一个非空字符
2. 替换和删除
将光标定位于文件内指定位置后,可以用其他字符来替换光标所指向的字符,或从当前光标位置删除一个或多
个字符。例如:
rc 用 c 替换光标所指向的当前字符
nrc 用 c 替换光标所指向的前 n 个字符
5rc 用 c 替换光标所指向的前 5 个字符
x 删除光标所指向的当前字符
nx 删除光标所指向的前 n 个字符
3x 删除光标所指向的前 3 个字符
dw 删除光标右侧的字
ndw 删除光标右侧的 n 个字
3dw 删除光标右侧的 3 个字
db 删除光标左侧的字
ndb 删除光标左侧的 n 个字
5db 删除光标左侧的 5 个字
dd 删除光标所在行,并去除空隙
ndd 删除 n 行内容,并去除空隙
3dd 删除 3 行内容,并去除空隙
3. 粘贴和复制
从正文中删除的内容(如字符、字或行)并没有真正丢失,而是被剪切并复制到了一个内存缓冲区中。用户可
将其粘贴到正文中的指定位置。完成这一操作的命令是:
p 小写字母 p,将缓冲区的内容粘贴到光标的后面
P 大写字母 P,将缓冲区的内容粘贴到光标的前面
如果缓冲区的内容是字符或字,直接粘贴在光标的前面或后面;如果缓冲区的内容为整行正文,则粘贴在当前
光标所在行的上一行或下一行。
注意上述两个命令中字母的大小写。vi 编辑器经常以一对大、小写字母(如 p 和 P)来提供一对相似的功能
。通常,小写命令在光标的后面进行操作,大写命令在光标的前面进行操作。
有时需要复制一段正文到新位置,同时保留原有位置的内容。这种情况下,首先应当把指定内容复制(而不是
剪切)到内存缓冲区。完成这一操作的命令是:
yy 复制当前行到内存缓冲区
nyy 复制 n 行内容到内存缓冲区
5yy 复制 5 行内容到内存缓冲区
4. 搜索字符串
和许多先进的编辑器一样,vi 提供了强大的字符串搜索功能。要查找文件中指定字或短语出现的位置,可以
用 vi 直接进行搜索,而不必以手工方式进行。搜索方法是:键入字符 / ,后面跟以要搜索的字符串,然后
按回车键。编辑程序执行正向搜索(即朝文件末尾方向),并在找到指定字符串后,将光标停到该字符串的
开头;键入 n 命令可以继续执行搜索,找出这一字符串下次出现的位置。用字符 ? 取代 / ,可以实现反向
搜索(朝文件开头方向)。例如:
/str1 正向搜索字符串 str1
n 继续搜索,找出 str1 字符串下次出现的位置
?str2 反向搜索字符串 str2
无论搜索方向如何,当到达文件末尾或开头时,搜索工作会循环到文件的另一端并继续执行。
5. 撤销和重复
在编辑文档的过程中,为消除某个错误的编辑命令造成的后果,可以用撤消命令。另外,如果用户希望在新
的光标位置重复前面执行过的编辑命令,可用重复命令。
u 撤消前一条命令的结果
. 重复最后一条修改正文的命令
6. 文本选中
vi 可进入到一种成为 Visual 的模式,在该模式下,用户可以用光标移动命令可视地选择文本,然后再 执行其他编辑操作,例如删除、复制等。 v 字符选中命令 V 行选中命令
#DEMO#
1.6.3 插入模式
1. 进入插入模式
在编辑模式下正确定位光标之后,可用以下命令切换到插入模式:
i 在光标左侧输入正文
a 在光标右侧输入正文
o 在光标所在行的下一行增添新行
O 在光标所在行的上一行增添新行
I 在光标所在行的开头输入正文
A 在光标所在行的末尾输入正文
上面介绍了几种切换到插入模式的简单方法。另外还有一些命令,它们允许在进入插入模式之前首先删去一段
正文,从而实现正文的替换。这些命令包括:
s 用输入的正文替换光标所指向的字符
ns 用输入的正文替换光标右侧 n 个字符
cw 用输入的正文替换光标右侧的字
ncw 用输入的正文替换光标右侧的 n 个字
cb 用输入的正文替换光标左侧的字
ncb 用输入的正文替换光标左侧的 n 个字
cd 用输入的正文替换光标的所在行
ncd 用输入的正文替换光标下面的 n 行
c$ 用输入的正文替换从光标开始到本行末尾的所有字符
c0 用输入的正文替换从本行开头到光标的所有字符
2. 退出插入模式
退出插入模式的方法是,按 ESC 键或组合键Ctrl+[ 。
#DEMO#
1.6.4 命令模式
在 vi 的命令模式下,可以使用复杂的命令。在编辑模式下键入“:”,光标就跳到屏幕最后一行,并在 那里显示冒号,此时已进入命令模式。命令模式又称“末行模式”,用户输入的内容均显示在屏幕的最后 一行,按回车键,vi 执行命令。
1. 退出命令
在编辑模式下可以用 ZZ 命令退出 vi 编辑程序,该命令保存对正文所作的修改,覆盖原始文件。如果只需要
退出编辑程序,而不打算保存编辑的内容,可用下面的命令:
: q 在未作修改的情况下退出
: q! 放弃所有修改,退出编辑程序
2. 行号与文件
编辑中的每一行正文都有自己的行号,用下列命令可以移动光标到指定行:
: n 将光标移到第 n 行
命令模式下,可以规定命令操作的行号范围。数值用来指定绝对行号;字符“.”表示光标所在行的行号;字符
符“$”表示正文最后一行的行号;简单的表达式,例如“.+5”表示当前行往下的第 5 行。例如:
:345 将光标移到第 345 行
:345w file 将第 345 行写入 file 文件
:3,5w file 将第 3 行至第 5 行写入 file 文件
:1,.w file 将第 1 行至当前行写入 file 文件
:.,$w file 将当前行至最后一行写入 file 文件
:.,.+5w file 从当前行开始将 6 行内容写入 file 文件
:1,$w file 将所有内容写入 file 文件,相当于 :w file 命令
在命令模式下,允许从文件中读取正文,或将正文写入文件。例如:
:w 将编辑的内容写入原始文件,用来保存编辑的中间结果
:wq 将编辑的内容写入原始文件并退出编辑程序(相当于 ZZ 命令)
:w file 将编辑的内容写入 file 文件,保持原有文件的内容不变
:a,bw file 将第 a 行至第 b 行的内容写入 file 文件
:r file 读取 file 文件的内容,插入当前光标所在行的后面
:e file 编辑新文件 file 代替原有内容
:f file 将当前文件重命名为 file
:f 打印当前文件名称和状态,如文件的行数、光标所在的行号等
3. 字符串搜索
给出一个字符串,可以通过搜索该字符串到达指定行。如果希望进行正向搜索,将待搜索的字符串置于两个“
/”之间;如果希望反向搜索,则将字符串放在两个“?”之间。例如:
:/str/ 正向搜索,将光标移到下一个包含字符串 str 的行
:?str? 反向搜索,将光标移到上一个包含字符串 str 的行
:/str/w file 正向搜索,并将第一个包含字符串 str 的行写入 file 文件
:/str1/,/str2/w file 正向搜索,并将包含字符串 str1 的行至包含字符串 str2 的行写
入 file 文件
4. 正文替换
利用 :s 命令可以实现字符串的替换。具体的用法包括:
:s/str1/str2/ 用字符串 str2 替换行中首次出现的字符串 str1
:s/str1/str2/g 用字符串 str2 替换行中所有出现的字符串 str1
:.,$ s/str1/str2/g 用字符串 str2 替换正文当前行到末尾所有出现的字符串 str1
:1,$ s/str1/str2/g 用字符串 str2 替换正文中所有出现的字符串 str1
:g/str1/s//str2/g 功能同上
从上述替换命令可以看到:g 放在命令末尾,表示对搜索字符串的每次出现进行替换;不加 g,表示只对搜索
字符串的首次出现进行替换;g 放在命令开头,表示对正文中所有包含搜索字符串的行进行替换操作。
5. 删除正文
在命令模式下,同样可以删除正文中的内容。例如:
:d 删除光标所在行
:3d 删除 3 行
:.,$d 删除当前行至正文的末尾
:/str1/,/str2/d 删除从字符串 str1 到 str2 的所有行
6. 恢复文件
vi 在编辑某个文件时,会另外生成一个临时文件,这个文件的名称通常以 . 开头,并以 .swp 结尾。vi 在
正常退出时,该文件被删除,若意外退出,而没有保存文件的最新修改内容,则可以使用恢复命令:
:recover 恢复文件
也可以在启动 vi 时利用 -r 选项。
1.6.5 选项设置
为控制不同的编辑功能,vi 提供了很多内部选项。利用 :set 命令可以设置选项。基本语法为:
:set option 设置选项 option
常见的功能选项包括:
autoindent 设置该选项,则正文自动缩进
ignorecase 设置该选项,则忽略规则表达式中大小写字母的区别
number 设置该选项,则显示正文行号
ruler 设置该选项,则在屏幕底部显示光标所在行、列的位置
tabstop 设置按 Tab 键跳过的空格数。例如 :set tabstop=n,n 默认值为 8
mk 将选项保存在当前目录的 .exrc 文件中
1.6.6 shell 切换
在编辑正文时,利用 vi 命令模式下提供的 shell 切换命令,无须退出 vi 即可执行 Linux 命令,十分
方便。语法格式为:
:! command 执行完 shell 命令 command 后回到 vi
另外,在编辑模式下,键入 K ,可命令 vi 查找光标所在单词的手册页,相当于运行 man命令。
1.6.7 vim 和 gvim 的高级特色
Vim 代表 Vi IMproved,如同其名称所暗示的那样,Vim 作为标准 UNIX 系统 vi 编辑器的提高版而存在。 Vim 除提供和 vi 编辑器一样强大的功能外,还提供有多级恢复、命令行历史以及命令及文件名补全等 功能。
gvim 是 vi 的 X Window 版本,该版本支持鼠标选中,一些高级光标移动功能,并且带有菜单和工具按钮。
Linux 系统命令及其使用详解(大全)
Linux 系统命令及其使用详解(大全)
cat cd
chmod chown
cp cut
名称:cat
使用权限:所有使用者
使用方式:cat
[-AbeEnstTuv] [--help] [--version] fileName
说明:把档案串连接后传到基本输出(萤幕或加 > fileName 到另一个档案)
参数:
-n 或 --number 由 1 开始对所有输出的行数编号
-b 或 --number-nonblank 和 -n 相似,只不过对于空白行不编号
-s 或 --squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行
-v 或 --show-nonprinting
范例:
cat -n
textfile1 > textfile2 把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里
cat -b
textfile1 textfile2 >> textfile3 把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3
名称:cd
使用权限:所有使用者
使用方式:cd
[dirName]
说明:变换工作目录至 dirName。 其中 dirName 表示法可为绝对路径或相对路径。若目录名称省略,则变换至使用者的 home
directory (也就是刚 login 时所在的目录).另外,"~" 也表示为 home directory 的意思,"." 则是表示目前所在的目录,".." 则表示目前目录位置的上一层目录。
范例:跳到 /usr/bin/:
cd /usr/bin
跳到自己的 home
directory:
cd ~
跳到目前目录的上上两层:
cd ../..
指令名称:chmod
使用权限:所有使用者
使用方式:chmod
[-cfvR] [--help] [--version] mode file...
说明:Linux/Unix
的档案存取权限分为三级:档案拥有者,群组,其他。利用 chmod 可以藉以控制档案如何被他人所存取。
把计:
mode:权限设定字串,格式如下:[ugoa...][[+-=][rwxX]...][,...],其中u 表示该档案的拥有者,g 表示与该档案的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。
+ 表示增加权限,- 表示取消权限,= 表示唯一设定权限。
r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该档案是个子目录或者该档案已经被设定过为可执行。
-c:若该档案权限确实已经更改,才显示其更改动作
-f:若该档案权限无法被更改也不要显示错误讯息
-v:显示权限变更的详细资料
-R:对目前目录下的所有档案与子目录进行相同的权限变更(即以递回的方式逐个变更)
--help:显示辅助说明
--version:显示版本
范例 :将档案 file1.txt 设为所有人皆可读取:
chmod ugo+r
file1.txt
将档案
file1.txt 设为所有人皆可读取:
chmod a+r
file1.txt
将档案
file1.txt 与 file2.txt 设为该档案拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入:
chmod ug+w,o-w
file1.txt file2.txt
将 ex1.py 设定为只有该档案拥有者可以执行:
chmod u+x
ex1.py
将目前目录下的所有档案与子目录皆设为任何人可读取:
chmod -R a+r
*
此外chmod也可以用数字来表示权限如 chmod 777 file
语法为:chmod
abc file
其中a,b,c各为一个数字,分别表示User,Group,及Other的权限。
r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。
范例:
chmod a=rwx
file
和
chmod 777
file
效果相同
chmod
ug=rwx,o=x file
和
chmod 771
file
效果相同
若用chmod 4755
filename可使此程式具有root的权限
指令名称:chown
使用权限:root
使用方式:chmod
[-cfhvR] [--help] [--version] user[:group] file...
说明:Linux/Unix
是多人多工作业系统,所有的档案皆有拥有者。利用 chown 可以将档案的拥有者加以改变。一般来说,这个指令只有是由系统管理者(root)所使用,一般使用者没有权限可以改变别人的档案拥有者,也没有权限可以自己的档案拥有者改设为别人。只有系统管理者(root)才有这样的权限。
把计:
user:新的档案拥有者的使用者 IDgroup:新的档案拥有者的使用者群体(group)-c:若该档案拥有者确实已经更改,才显示其更改动作-f:若该档案拥有者无法被更改也不要显示错误讯息-h:只对于连结(link)进行变更,而非该 link 真正指向的档案-v:显示拥有者变更的详细资料-R:对目前目录下的所有档案与子目录进行相同的拥有者变更(即以递回的方式逐个变更)--help:显示辅助说明--version:显示版本
范例:
将档案
file1.txt 的拥有者设为 users 群体的使用者 jessie:
chown
jessie:users file1.txt
将目前目录下的所有档案与子目录的拥有者皆设为 users 群体的使用者 lamport:
chmod -R
lamport:users *
名称:cp
使用权限:所有使用者
使用方式:
cp [options]
source dest
cp [options]
source... directory
说明:将一个档案拷贝至另一档案,或将数个档案拷贝至另一目录。
把计:
-a 尽可能将档案状态,权限等资料都照原状予以复制。
-r 若 source 中含有目录名,则将目录下之档案亦皆依序拷贝至目的地。
-f 若目的地已经有相同档名的档案存在,则在复制前先予以删除再行复制。
范例:
将档案 aaa 复制(已存在),并命名为 bbb:
cp aaa bbb
将所有的C语言程式拷贝至 Finished 子目录中:
cp *.c
Finished
名称:cut
使用权限:所有使用者
用法:cut
-cnum1-num2 filename
说明:显示每行从开头算起
num1 到 num2 的文字。
范例:
shell>>
cat example
test2
this is
test1
shell>>
cut -c0-6 example ## print 开头算起前 6 个字元
test2
this i
用法:find
使用说明:
将档案系统内符合
expression 的档案列出来。你可以指要档案的名称,类别,时间,大小,权限等不同资讯的组合,只有完全相符的才会被列出来。
find 根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部份为 path,之后的是 expression。如果 path 是空字串则使用目前路径,如果 expression 是空字串则使用 -print 为预设 expression
expression 中可使用的选项有二三十个之多,在此只介绍最常用的部份。
-mount,
-xdev:只检查和指定目录在同一个档案系统下的档案,避免列出其它档案系统中的档案
-amin n:在过去 n 分钟内被读取过
-anewer
file:比档案 file 更晚被读取过的档案
-atime n:在过去 n 天过读取过的档案
-cmin n:在过去 n 分钟内被修改过
-cnewer file
:比档案 file 更新的档案
-ctime n:在过去 n 天过修改过的档案
-empty:空的档案-gid n or -group name:gid 是 n 或是 group 名称是 name
-ipath p,
-path p:路径名称符合 p 的档案,ipath 会忽略大小写
-name name,
-iname name:档案名称符合 name 的档案。iname 会忽略大小写
-size n:档案大小 是 n 单位,b 代表 512 位元组的区块,c 表示字元数,k 表示 kilo bytes,w 是二个位元组。-type c:档案类型是 c 的档案。
d: 目录
c: 字型装置档案
b: 区块装置档案
p: 具名贮列
f: 一般档案
l: 符号连结
s: socket
-pid
n:process id 是 n 的档案
你可以使用 ( ) 将运算式分隔,并使用下列运算。
exp1 -and exp2
! expr
-not expr
exp1 -or
exp2
exp1, exp2
范例:
将目前目录及其子目录下所有延伸档名是 c 的档案列出来。
# find .
-name "*.c"
将目前目录其其下子目录中所有一般档案列出
# find .
-ftype f
将目前目录及其子目录下所有最近 20 分钟内更新过的档案列出
# find .
-ctime -20
名称:less
使用权限:所有使用者
使用方式:
less
[Option] filename
说明:
less 的作用与 more 十分相似,都可以用来浏览文字档案的内容,不同的是 less 允许使用者往回卷动
以浏览已经看过的部份,同时因为 less 并未在一开始就读入整个档案,因此在遇上大型档案的开启时,会比一般的文书编辑器(如 vi)来的快速。
范例:
指令名称:ln
使用权限:所有使用者
使用方式:ln
[options] source dist,其中 option 的格式为:
[-bdfinsvF]
[-S backup-suffix] [-V {numbered,existing,simple}]
[--help]
[--version] [--]
说明:Linux/Unix
档案系统中,有所谓的连结(link),我们可以将其视为档案的别名,而连结又可分为两种:硬连结(hard link)与软连结(symbolic link),硬连结的意思是一个档案可以有多个名称,而软连结的方式则是产生一个特殊的档案,该档案的内容是指向另一个档案的位置。硬连结是存在同一个档案系统中,而软连结却可以跨越不同的档案系统。
ln source
dist 是产生一个连结(dist)到 source,至于使用硬连结或软链结则由参数决定。
不论是硬连结或软链结都不会将原本的档案复制一份,只会占用非常少量的磁碟空间。
-f:链结时先将与 dist 同档名的档案删除-d:允许系统管理者硬链结自己的目录-i:在删除与 dist 同档名的档案时先进行询问-n:在进行软连结时,将 dist 视为一般的档案-s:进行软链结(symbolic link)-v:在连结之前显示其档名-b:将在链结时会被覆写或删除的档案进行备份-S SUFFIX:将备份的档案都加上 SUFFIX 的字尾-V METHOD:指定备份的方式--help:显示辅助说明--version:显示版本
范例:
将档案 yy 产生一个 symbolic link:zz
ln -s yy zz
将档案 yy 产生一个 hard link:zz
ln yy xx
名称:locate
使用权限:所有使用者
使用方式: locate
[-q] [-d ] [--database=]
locate [-r ]
[--regexp=]
locate [-qv]
[-o ] [--output=]
locate [-e ]
[-f ] <[-l ] [-c]
<[-U ]
[-u]>
locate [-Vh]
[--version] [--help]
说明:
locate 让使用者可以很快速的搜寻档案系统内是否有指定的档案。其方法是先建立一个包括系统内所有档案名称及路径的资料库,之后当寻找时就只需查询这个资料库,而不必实际深入档案系统之中了。在一般的 distribution 之中,资料库的建立都被放在
contab 中自动执行。
一般使用者在使用时只要用
# locate
your_file_name
的型式就可以了。 参数:
-u
-U
建立资料库,-u 会由根目录开始,-U 则可以指定开始的位置。
-e
将排除在寻找的范围之外。
-l
如果 是 1.则启动安全模式。在安全模式下,使用者不会看到权限无法看到的档案。这会始速度减慢,因为 locate 必须至实际的档案系统中取得档案的权限资料。
-f
将特定的档案系统排除在外,例如我们没有到理要把 proc 档案系统中的档案放在资料库中。
-q
安静模式,不会显示任何错误讯息。
-n
至多显示 个输出。
-r
使用正规运算式 做寻找的条件。
-o
指定资料库存的名称。
-d
指定资料库的路径
-h
显示辅助讯息
-v
显示更多的讯息
-V
显示程式的版本讯息 范例:
locate
chdrv:寻找所有叫 chdrv 的档案
locate -n
locate -u:建立资料库
名称:ls
使用权限:所有使用者
使用方式:ls
[-alrtAFR] [name...]
说明:显示指定工作目录下之内容(列出目前工作目录所含之档案及子目录)。
-a 显示所有档案及目录 (ls内定将档案名或目录名称开头为"."的视为隐藏档,不会列出)
-l 除档案名称外,亦将档案型态,权限,拥有者,档案大小等资讯详细列出
-r 将档案以相反次序显示(原定依英文字母次序)
-t 将档案依建立时间之先后次序列出
-A 同 -a ,但不列出 "." (目前目录) 及
".." (父目录)
-F 在列出的档案名称后加一符号;例如可执行档则加
"*", 目录则加
"/"
-R 若目录下有档案,则以下之档案亦皆依序列出
范例:
列出目前工作目录下所有名称是 s 开头的档案,愈新的排愈后面:
ls -ltr s*
将 /bin 目录以下所有目录及档案详细资料列出:
ls -lR /bin
列出目前工作目录下所有档案及目录;目录于名称后加 "/", 可执行档于名称后加 "*":
ls -AF
名称:more
使用权限:所有使用者
使用方式:more
[-dlfpcsu] [-num] [+/pattern] [+linenum] [fileNames..]
说明:类似 cat ,不过会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示,而且还有搜寻字串的功能(与 vi 相似),使用中的说明文件,请按 h 。
参数:-num 一次显示的行数
-d 提示使用者,在画面下方显示 [Press space to continue, q to quit.] ,如果使用者按错键,则会显示 [Press h for instructions.] 而不是 哔 声
-l 取消遇见特殊字元 ^L(送纸字元)时会暂停的功能
-f 计算行数时,以实际上的行数,而非自动换行过后的行数(有些单行字数太长的会被扩展为两行或两行以上)
-p 不以卷动的方式显示每一页,而是先清除萤幕后再显示内容
-c 跟 -p 相似,不同的是先显示内容再清除其他旧资料
-s 当遇到有连续两行以上的空白行,就代换为一行的空白行
-u 不显示下引号 (根据环境变数 TERM 指定的 terminal 而有所不同)
+/ 在每个档案显示前搜寻该字串(pattern),然后从该字串之后开始显示
+num 从第 num 行开始显示
fileNames 欲显示内容的档案,可为复数个数
范例:
more -s
testfile 逐页显示 testfile 之档案内容,如有连续两行以上空白行则以一行空白行显示。
more +20
testfile 从第 20 行开始显示 testfile 之档案内容。
名称:mv
使用权限:所有使用者
使用方式:
mv [options]
source dest
mv [options]
source... directory
说明:将一个档案移至另一档案,或将数个档案移至另一目录。
参数:-i 若目的地已有同名档案,则先询问是否覆盖旧档。
范例:
将档案 aaa 更名为 bbb:
mv aaa bbb
将所有的C语言程式移至 Finished 子目录中:
mv -i *.c
名称:rm
使用权限:所有使用者
使用方式:rm
[options] name...
说明:删除档案及目录。
把计:
-i 删除前逐一询问确认。
-f 即使原档案属性设为唯读,亦直接删除,无需逐一确认。
-r 将目录及以下之档案亦逐一删除。
范例:
删除所有C语言程式档;删除前逐一询问确认:
rm -i *.c
将 Finished 子目录及子目录中所有档案删除:
rm -r
Finished
名称:rmdir
使用权限:于目前目录有适当权限的所有使用者
使用方式: rmdir
[-p] dirName
说明: 删除空的目录。
参数: -p 是当子目录被删除后使它也成为空目录的话,则顺便一并删除。
范例:
将工作目录下,名为 AAA 的子目录删除:
rmdir AAA
在工作目录下的 BBB 目录中,删除名为 Test 的子目录。若 Test 删除后,BBB 目录成为空目录,则 BBB 亦予删除。
rmdir -p
BBB/Test
名称:split
使用权限:所有使用者
使用方式:split
[OPTION] [INPUT [PREFIX]]说明:
将一个档案分割成数个。而从 INPUT 分割输出成固定大小的档案,其档名依序为
PREFIXaa, PREFIXab...;PREFIX 预设值为 `x。若没有 INPUT 档或为 `-,则从标准输入读进资料。
匡兜:
-b,
--bytes=SIZE
SIZE 值为每一输出档案的大小,单位为 byte。
-C,
--line-bytes=SIZE
每一输出档中,单行的最大 byte 数。
-l,
--lines=NUMBER
NUMBER 值为每一输出档的列数大小。
-NUMBER
与 -l NUMBER 相同。
--verbose
于每个输出档被开启前,列印出侦错资讯到标准错误输出。
--help
显示辅助资讯然后离开。
--version
列出版本资讯然后离开。
SIZE 可加入单位: b 代表 512, k 代表 1K, m 代表 1 Meg。
范例:
PostgresSQL 大型资料库备份与回存:
因 Postgres 允许表格大过你系统档案的最大容量,所以要将表格 dump 到单一的档案可能会有问题,使用 split进行档案分割。
% pg_dump
dbname | split -b
重新载入
% createdb
dbname
% cat
filename.dump.* | pgsql dbname
名称:touch
使用权限:所有使用者
使用方式:
touch
[-acfm]
[-r
reference-file] [--file=reference-file]
[-t
MMDDhhmm[[CC]YY][.ss]]
[-d time]
[--date=time] [--time={atime,access,use,mtime,modify}]
[--no-create]
[--help] [--version]
file1 [file2
...]
说明:
touch 指令改变档案的时间记录。 ls -l 可以显示档案的时间记录。
参数:
a 改变档案的读取时间记录。
m 改变档案的修改时间记录。
c 假如目的档案不存在,不会建立新的档案。与 --no-create 的效果一样。
f
alexclark
发表于:2005.07.08 14:06
::分类:
( 动手操作文档
)
::阅读:(5230次)
:: 评论
(0)
跟我一起写 Makefile
PalmOS开发汇总
Palm OS Develop的小总结
转自
Palm OS Develop的小总结
Document Actions
Palm OS programming看起来很简单. PilRC是基于GTK+的针对Palm的UI资源编译器. 这里可以下载Palm OS Emulator, 并且Palm OS SDK 在这里. 这里有份关于用Prc-tools的开发文档, 很有参考价值.
requires (at minimum) a C or C++ compiler, a Palm OS SDK,and a UI resource compiler.Most programmers will also use the Palm OS Emulator,
and many will have several Palm OS SDKs and other Palm OS-related headers,libraries, and SDKs installed.
上面是一些基本的资料, 另外还有一个IDE叫Falch.net DeveloperStudio , 可惜这个网页打不开, 不知道是不是中止开发了. 以后有空再关注一下.
另外不知道Palm对Java的支持怎么样, 最近正在弄Java的实习, 有空关注一下.
CodeWarrior是个好东西, 用它的话肯定比在Linux下面效率高很多... ...
程序员的吸星大法-IDA反汇编工具初探
但开源的程序毕竟是在少数,大多数程序都只会分发可执行文件及相关文件,这时我们要想查看此程序的代码,就只有把它反汇编,当然这需要一定的汇编功底,但是一个好的反汇编工具能为你阅读反汇编出来的程序提供非常大的帮助.
了解反汇编的朋友也一定知道WINDASM这个有名的反汇编工具,比如我们用WINDASM反汇编一个程序,在其程序入口点反汇编得到如下代码:
//*********************** Program Entry Point *****************
:00401000 6A00 push 00000000
:00401002 E8FF050000 call 00401606
:00401007 A316304000 mov [00403016], eax
:00401007 E8EF050000 call 00401600
:00401011 A30E304000 mov [0040300E], eax
:00401016 6A0A push 0000000A
:00401018 FF350E304000 push dword ptr [0040300E]
:0040101E 6A00 push 00000000
:00401020 EF3516304000 push dword ptr [00403016]
:00401026 E806000000 call 00401031
:0040102B 50 push eax
:0040102c E8C9050000 call 004015FA
如果不联系上下文及知道这是程序入口的话,很难看出来这一段代码到底是干什么的,但IDA就不一样了,它不但会反汇编程序,并会尽量分析程序,并加上相应的注释(正因为这样,IDA反汇编一个大的程序会花非常长的时间),请看下面一段IDA反汇编出来的代码,是不是明了多了?
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax
.text:0040100C call GetCommandLineA
.text:00401011 mov dword_0_40300E, eax
.text:00401016 push 0Ah
.text:00401018 push dword_0_40300E
.text:0040101E push 0
.text:00401020 push hInstance
.text:00401026 call sub_0_401031
.text:0040102B push eax ; uExitCode
.text:0040102C call ExitProcess
IDA反汇编程序后,会生成一个 .idb文件,里面保存了反汇编出来的代码及注释及IDA的一些其它相关数据,我们可以直接在IDA中写自己的分析结果和注释并保存,下次直接打开.idb文件就可以了,例如上面
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax
我们可以看出来实际上就是hInstance = GetModuleHandleA(nil);我们可以在后面直接加上注释,在.text:00401007这一行最后面的空白处点右键,在弹出的菜单中选择"注释",然后在弹出的窗口中填上"取得当前模块实例句柄",这一行就会变为
.text:00401007 mov hInstance, eax ; 取得当前模块实例句柄
这样就为我们的反汇编出的代码增加了可读性.
IDA不但可以在当前代码中加注释,还可以更改其默认的符号名,比如
.text:00401011 mov dword_0_40300E, eax
其中的dwrd_0_40300E可以看出来是存放取得的命令行的缓冲区指针(可以双击符号名,函数名跳到其定义处),在dword_0_40300E上面点右键,选取"重命名",然后在弹出的窗口中填入lpCommandline,点确定,这样程序中所有使用到了dword_0_40300E这个变量的地方都会将dword_0_40300E替换为lpCommandline.如下所示:
.text:00401011 mov lpCommandline, eax
.text:00401016 push 0Ah
.text:00401018 push lpCommandline
我们再来看.text:00401026 call sub_0_401031这一行
可以从上面的代码看出来,这是调用的WinMain函数,在sub_0_401031上面点右键,选取"重命名",然这个函数命名为WinMain,这时IDA就将所有sub_0_401031符号变为WinMain, 并且自动加上函数定义,并会在函数调用时入栈的参数后面加上其对应的变量注释,这时我们反汇编出来的这一段代码就成了下面这个样子的了:
.text:00401000 start proc near
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax ; 取得当前模块实例句柄
.text:0040100C call GetCommandLineA
.text:00401011 mov lpCommandline, eax
.text:00401016 push 0Ah ; nShowCmd
.text:00401018 push lpCommandline ; lpCmdLine
.text:0040101E push 0 ; hPrevInstance
.text:00401020 push hInstance ; hInstance
.text:00401026 call WinMain
.text:0040102B push eax ; uExitCode
.text:0040102C call ExitProcess
是不是一目了解了呢?
当我们通过阅读源码,能确定某一个子函数的作用及传入的参数类型时,我们可以双击这个函数名,跳到函数定义处,在函数定义处点右键,使用"设置函数类型"功能来编辑函数定义(C++语法),这样所有调用到这个函数的地方都会在入栈的参数后面加上其对应的变量注释. 还可以通过在函数定义处后面空白处点右键加上"可重复注释",这样所有调用此函数的地方都会在后面加上这个重复的注释.
如果想查看某个变量或函数被调用的情况,可以通过在函数或变量名上点右键,点击"查看操作数交叉索引处"功能,就可以在打开的窗口中查看到所有调用其的代码,并可通过双击跳到这段代码处.这是一个很有用的功能,能帮助你快速的搞清函数及变量的调用关系.
按下F12还可以查看到程序的流程图,CTRL+12可以查看到函数的调用图.
IDA还拥有符号调试技术,能识别常见编释器编释的程序,例如下面反汇编出的VC6.0的程序代码段:
.text:00405427 push edx
.text:00405428 call _swscanf
.text:0040542D lea eax, [esp+38h+arg_40]
.text:00405431 push offset unk_0_5DB1A4 ; const wchar_t *
.text:00405436 push eax ; const wchar_t *
.text:00405437 call _wcscmp
.text:0040543C add esp, 1Ch
.text:0040543F test eax, eax
.text:00405441 jz short loc_0_405459
.text:00405443 lea ecx, [esp+24h+arg_40]
.text:00405447 push offset unk_0_5DB18C ; const wchar_t *
.text:0040544C push ecx ; const wchar_t *
.text:0040544D call _wcscmp
就检查到了其调用了MFC类库中的函数,并把它们替换成了相应的函数名.
还可以调用IDA导出.MAP文件,来配合其它动态调试工具如SOFT-ICE来进行代码分析.
IDA是一个非常强大的反汇编工具,这里只是讨论了一下它的一些基本的应用,希望能起到抛砖引玉的作用,如果对IDA应用有兴趣的朋友可以来信讨论,或参考段钢先生的<<加密与解密>>一书,里面对IDA的应用有较祥细的讲解.
我的Mail:akunspy@sina.com
Compound Interest formula
The formula we will use to perform the calculations is as follows:
![]() |
P = Principal |
| r = Annual (Interest) Rate | |
| m = Number of Compounding Periods per Year | |
| n = Total Number of Compounding Periods | |
| A = Amount Earned After n periods |
http://www.functionx.com/visualc/applications/compoundinterest.htm
如何在 Red Hat Linux 9 上安装 Eclipse
先下载eclipse,网址为 http://www.eclipse.org。
eclipse 可以在很多个平台上执行,在此我们要安装在linux上面,参考下图,
请选择linux(x86/GTK 2)。
下载这个
eclipse所支持的平台
在本文撰写时,eclipse的最新版本为 3.0 版,2.1.1版本支持C/C++开发执行。
执行eclipse 时须使用到 Sun JDK
1,但eclipse的安装程序并未包含 Sun JDK,
且 Red Hatlinux 9 也未包含 Sun JDK。所以接下来我们要下载该档案。Sun 最
新版本的 JDK 可至 http://www.javasoft.com 下载,在此我们使用的是 Java 2 SDK (J2SE) 1.4.2-01 版
1,eclipse 似乎也可搭配 IBM 或其它公司的 JDK,不过我并没有实际测试过。
两个软件都下载完毕之后, 我们先安装 JDK(需以 root 身分安装):
[root @ljn] chmod 711 j2sdk-1_4_2_01-linux-i586-rpm.bin
[root @ljn] ./j2sdk-1_4_2_01-linux-i586-rpm.bin
[root @ljn] rpm –ivh j2sdk-1_4_2_01-linux-i586-rpm
执行后会出现好几页的版权声明,回答 yes
即可继续安装。完成后会产生一个
j2sdk-1_4_2_01-linux-i586-rpm 档案,接下
来用 rpm 来安装
[root @ljn]rpm –ivh j2sdk-1_4_2_01-linux-i586-rpm
将档案权限改为可执行檔
安装好后的 JDK 会储存在 /usr/java/j2sdk1.4.2_01 目录中(不同版本的 JDK 目录名称会不一样,例如 /usr/java/j2sdk1.x.y_zz)。
做一个符号连接
[root @ljn] ln –s /usr/java/j2sdk1.4.2_01 /usr/java/jdk
接下来我们要安装eclipse,在此我们把eclipse 安装在 /opt 这个目录中,你也
可以选择安装在其它不同的目录。安装 eclipse很简单,只要把下载回来的压缩档案解开就可以了:
2指定将档案解到 /opt 目录中,如果目录不
存在 unzip 会自动建立该目录
[root @ljn] unzip –d /opt eclipse-SDK-2.1.1-linux-gtk.zip
不管哪一个版本的eclipse(目前安装过 2.1.1 和 3.0 M3)
,解压缩后都会解到eclipse这个目录中。如果我们在同一台计算机上安装不同版本的eclipse,除非安装在不同目录,否则先前的版本将会被覆盖。因此,我们将刚刚解压缩出来的
/opt/eclipse
为了让每一位linux的使用者都可以执行eclipse,我们写了一个 script(eclipse.sh):
#!/bin/bash
#
# 文档名: eclipse.sh
#
# 执行 eclipse2.1 版本
#
export JAVA_HOME=/usr/java/jdk
export CLASSPATH=/usr/java/jdk/lib
/opt/eclipse/eclipse -vm /usr/java/jdk/bin/java -data ~/workspace &
-vm 参数用以指定使用哪一个 jvm 来执行eclipse,在此我们指定之前安装的 Sun JDK 1.4.2-01 版-date 参数用以告诉eclipse要将项目储存
在哪一个目录中。在此我们指定储存在使
用者home目录(~)的 workspace 目录中
3接下来我们将 clipsem.sh 复制到/usr/local/bin 目中并设定其权限:
[root @ljn]cp eclipse.sh /usr/local/bin
[root @ljn]chmod 755 /usr/local/bin/eclipse.sh
此时执行 eclipse.sh 既可启动 eclipse。请参考下图
eclipse启动后画面
4如果嫌每次都要打 eclipse.sh 太麻烦,我们也可以设定一个 alias,让使用者只要输入 eclipse2.1 即可。请修改 /etc/profile.d 目录下的 which-2.sh:
alias eclipse2.1=`/usr/local/bin/eclipse.sh`
在最后面加上这一行。
如果这样还是太麻烦,我们也可以像是在 Windows 系统里面一样,为eclipse在桌面上建立一个「快捷方式」
。请参考下图;
首先,在桌面上按下鼠标右键,在跳出
窗口中选择第三个选项「新增启动器(A) 」,之后会出现上图 的画面。分别在
「名称」栏中输入eclipse、
「指令」栏中输入/usr/local/bin/eclipse.sh,然后按
下「图标」栏右边的「没有图标」按钮。这时候按下确定按
钮桌面上就会出现的eclipse 图标,以后就可以直接点选该图标来执行eclipse。
备注:
1.
虽然 Sun JDK 和eclipse可以在 Red Hat Linux 7.x 版中成功安装,但是在执行eclipse 时,却会出现
error while loading shared libraries: libgtk-x11-2.0.so.0:
cannot load shared object file: No such file or directory 错误讯息。我想可能是
gtk 版本太旧的关系吧,也许更新一下 gtk 就可以。Red Hat linux 8.x、9
2. 如果要在Eclipse中安装 CDT 撰写 C/C++程序的使用者,可以安装eclipse 2.11版。在本文撰写时 CDT 只支持eclipse 2.1.x 版。
3.用 Eclipse 平台进行 C/C++ 开发
参照这两篇文章
http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-ecc/index.shtml
查看全文
列出目录树的shell程序
下面的短小的shell程序可以列出目录树, 充分利用了sed强大的模式匹配能力.
目录树形式如下:
.
`----shellp
`----updates
`----wu-ftpd-2.4
| `----doc
| | `----examples
| `----src
| | `----config
| | `----makefiles
| `----support
| | `----makefiles
| | `----man
| `----util
摘自<>
#!/bin/sh
# dtree: Usage: dtree [any directory]
dir=${1:-.}
(cd $dir; pwd)
find $dir -type d -print | sort -f | sed -e "s,^$1,," -e "/^$/d"
-e
"s,[^/]*/([^/]*)$,`----1," -e "s,[^/]*/,|
,g"
简单的 Eclipse 3.0.1 的汉化
Eclipse官方网站:http://www.eclipse.org/
Eclipse3语言包:Language Pack: 3.0.x
Eclipse 是一款很强大的 IDE,本站曾经也发过两篇关于使用它配置 PHP 调试环境的文章,现在已经出了 3.0.1 版本和中文语言包了,所以本文简单介绍一下它的汉化方法。
下载 Eclipse 3.0.1 和语言包:
Eclipse 3.0.1:http://download.eclipse.org/downloads
语言包:点击这里。 建议下载 Platform SDK Language Pack。
解压缩 eclipse-SDK-3.0.1-win32.zip 到 N:eclipse,这里 N 表示盘符,目录结构如下:

在 eclipse 目录中新建一个名为 language 和 links 的目录,并将下载下来的语言包 NLpack-eclipse-platform-SDK-3.0.x-win32.zip 解压缩到 language 目录中,解压缩后目录结构如下(结构错了就不行了):

在 links 目录里新建一个文本文件,命名为 language.link ,并在文件里写入下列信息:
path=N:eclipselanguage
其中 N 为您所使用的盘符,记得反斜杠要使用 转意,设置 path 指向 language 目录,保存即可。
启动 Eclipse 3.0.1,已经是中文的了:
希望用得顺心,嘿嘿。
--深空于 2004年10月24日中午 网站:http://www.openphp.cn
Nokia S60编程环境的建立
一、环境的建立
现使用VC++6.0+Symbian6.1SDK,编译样例程序HELLOWORLD在PC模拟器上运行正常,打包成*.sis安装在我的诺基亚3650手机运行正常。现将过程简述如下,希望对初学者有所帮助!
1、操作系统:WIN2000专业版自带SP2,有网友说没必要升级,但我升级到了SP4(Service Pack 4),请到微软下载!
2、安装Micorsoft Visual C++6.0,下载地址:http://www.big666.com/down.asp?id=1866&no=1,说是原版却是汇天中文版,反正也能使!升级到vs5下载地址:
http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/VS6sp5.exe,
必安的一个小文件MDAC2.8,微软的数据库引擎就象borland的bde,下载地址:
http://download.microsoft.com/download/c/d/f/cdfd58f1-3973-4c51-8851-49ae3777586f/MDAC_TYP.EXE
3、安装JAVA运行库(Java 2 Runtime Environment,j2re)下载地址:
http://www.hongkongpost.gov.hk/product/download/ecert_software/img/j2re-1_3_1_01-win-i.exe
请不要使用1.41的版本,我开始用这个,可SISAR就说我没安装JAVA运行库,您也别浪费时间去试了!
4、安装ActivePerl5.8,下载地址:
http://count.skycn.com/softdown.php?id=1211&url=http://cbbnhttp.skycn.net/down/ActivePerl-5.8.0.806-MSWin32-x86.msi
5、安装S60SDK,1.2版本下载地址:
http://nds1b.forum.nokia.com/nnds/ForumDownloadServlet?id=3378&name=nS60%5Fsdk%5Fv1%5F2%2Ezip
我是这个地址,但得先注册,您也可到forum.nokia.com一步步找,很简单!
6、最后开始整合,步骤是:
拷贝6.1Series60Series60ToolsApplicationWizard下的两个文件AvkonAppWiz.awx和AVKONAPPWIZ.HLP到CommonMsDev98Template下面。
运行一下VC,new 一个Project试一下,如果Project选项中有Series 60 AppWizard,就说明一切正常!
最后要说明的是以所有安装都必须在一个分区。我的都在C,分区小的话用partition magic重划一下。
二、初步试用。我就以SDK自带HELLOWORLD为例子。
1、在模拟器上运行程序。找到C:Symbian6.1Series60Series60Exhelloworldgroup文件夹,用记事本建立三个bat文件内容分别为:
a、M.bat内容 bldmake bldfiles
b、MWin.bat内容 abld build wins udeb
c、M3650.bat内容 abld build armi urel
说明:第一个批处理文件功能是生成Make文件,第二个批处理文件功能是生成可在模拟器上运行的代码,第三个批处理文件功能是生成可在目标机器(诺基亚3650、7650)上运行的代码。
先执行a.bat然后再执行MWin.bat,然后打开Emulator (debug),在功能区的最后一个图标就是helloworld。运行一下,发现这个程序的功能不能再简单了吧!
2、在你的手机(诺基亚3650/7650)上运行程序。
a、请先运行上一步M3650.bat。
b、找到C:Symbian6.1Series60Series60Exhelloworldsis,将helloworld.pkg复制成h.pkg(h可为其它),用记事本打开它,将最后两行内容:
"......epoc32releasethumburelHelloWorld.APP"-"C:systemappsHelloWorldHelloWorld.app"
"......epoc32releasethumburelHelloWorld.rsc"-"C:systemappsHelloWorldHelloWorld.rsc"
替换成:
"......epoc32releasearmiurelHelloWorld.APP"-"C:systemappsHelloWorldHelloWorld.app"
"......epoc32releasearmiurelHelloWorld.rsc"-"C:systemappsHelloWorldHelloWorld.rsc"
c、在这个文件夹用记事本建立一个MS.bat文件内容为makesis h.pkg ,并执行它!这时生成h.sis,传到手机上安装试试吧!
查看全文
几道C语言面试题(华为)
Void test1()
{
char string[10];
char* str1="0123456789";
strcpy(string, str1);
}
Void test2()
{
char string[10], str1[10];
for(I=0; I<10;I++)
{
str1[i] ='a';
}
strcpy(string, str1);
}
Void test3(char* str1)
{
char string[10];
if(strlen(str1)<=10)
{
strcpy(string, str1);
}
}
2. 找错
#define MAX_SRM 256
DSN get_SRM_no()
{
static int SRM_no;
int I;
for(I=0;I{
SRM_no %= MAX_SRM;
if(MY_SRM.state==IDLE)
{
break;
}
}
if(I>=MAX_SRM)
return (NULL_SRM);
else
return SRM_no;
}
3. 写出程序运行结果
int sum(int a)
{
auto int c=0;
static int b=3;
c+=1;
b+=2;
return(a+b+C);
}
void main()
{
int I;
int a=2;
for(I=0;I<5;I++)
{
printf("%d,", sum(a));
}
}
4.
int func(int a)
{
int b;
switch(a)
{
case 1: 30;
case 2: 20;
case 3: 16;
default: 0
}
return b;
}
则func(1)=?
5:
int a[3];
a[0]=0; a[1]=1; a[2]=2;
int *p, *q;
p=a;
q=&a[2];
则a[q-p]=?
6.
定义 int **a[3][4], 则变量占有的内存空间为:_____
7.
编写一个函数,要求输入年月日时分秒,输出该年月日时分秒的下一秒。如输入2004年12月31日23时59分59秒,则输出2005年1月1日0时0分0秒。 查看全文
在 Linux 上实现基于 Socket 的多进程实时通信
套接口(Socket)为目前 Linux 上最为广泛使用的一种的进程间通信机制。但是它不能直接用来多进程之间的相互实时通信。本文提出一个基于 Socket 的多进程之间通信的实现方法,并给出样本程序的实现和说明。
套 接口(Socket)为目前Linux上最为广泛使用的一种的进程间通信机制,与其他的Linux通信机制不同之处在于除了它可用于单机内的进程间通信以 外,还可用于不同机器之间的进程间通信。但是由于Socket本身不支持同时等待和超时处理,所以它不能直接用来多进程之间的相互实时通信。
本 文提出一个基于Socket的多进程之间通信的实现方法。原理是建立一个进程专门用来做为通信服务器(server)来中转各个进程之间的通信。它首先启 动一个用来监视连接要求的listening Socket,并把它的描述(Descriptor)号加入到一个事先定义好的fd_set的集合中,这个fd_set的集合用来存放listening Socket和后来生成的通信Socket的描述号。Server运用system call select来实时检查是否有数据到达这个集合中的任何一个socket,如果有数据到达listening Socket,则这一定是客户端发起的连接请求,于是生成一个新的通信Socket与该客户端连接,将生成的Socket描述号加入到fd_set的集合 中,将客户端的ID号和与之对应的Socket的描述号记录在ID登记表中。如果有数据到达某个通信Socket,则这一定是某个客户端发起的通信请求, 读出数据并取出收信客户端ID号,在ID登记表中找到与之对应的Socket描述号,将数据通过对应Socket传送到收信客户端。
其他各进程作为客户端(client)。客户端的动作是首先建立通信Socket连接服务器端,然后通过通信Socket进行送信和收信。
下面给出具体的程序实现和说明,
首先给出Server端的程序,在这里假设有两个客户端要进行实时通信,ClientA向ClientB发送字符1,ClientB向ClientA发送字符2。
|
在上面的程序中,Server生成listening Socket(server_sockfd),初始化Socket监视集合(watchset),并将listening Socket放入Socket监视集合中。
|
在上面的程序中,Server运用系统调用函数 select来实时检查是否有数据到达Socket监视集合中的任何一个socket。
|
在 上面的程序中,Server运用系统调用函数FD_ISSET来检查是否有客户端的连接请求到达Listening Socket, 如果返回值大于0,Server生成一个新的通信Socket (new_cli_fd)与客户端连接。将新生成的通信Socket放入Socket监视集合中(FD_SET)。将客户端的信息(ID号和Socket 描述号)保存在注册表cli_info_t中
|
在上面的程序中,如果有数据到达某个通信Socket,Server则读出数据并取出收信客户端ID号。在ID登记表中找到收信客户端对应的Socket描述号。并将数据通过对应Socket传送到收信客户端
给出客户端 ClientA的程序
ClientB的程序只需将 char dst_module_id='B'; 改为char dst_module_id='A';
char ch='1'; 改为char char ch='2';既可。
|
下面是样本程序的执行结果
|
周欣,北京邮电大学计算机系硕士毕业, 现在日本从事软件开发,通过 jones_zhou@yahoo.com.cn 可以和他联系。 查看全文
基于Visual C++6.0的DLL编程实现
自从微软推出16位的Windows操作系统起,此后每种版本的Windows操作系统都非常依赖于动态链接库(DLL)中的函数和数据,实际上Windows操作系统中几乎所有的内容都由DLL以一种或另外一种形式代表着,例如显示的字体和图标存储在GDI DLL中、显示Windows桌面和处理用户的输入所需要的代码被存储在一个User DLL中、Windows编程所需要的大量的API函数也被包含在Kernel DLL中。
在Windows操作系统中使用DLL有很多优点,最主要的一点是多个应用程序、甚至是不同语言编写的应用程序可以共享一个DLL文件,真正实现了资源"共享",大大缩小了应用程序的执行代码,更加有效的利用了内存;使用DLL的另一个优点是DLL文件作为一个单独的程序模块,封装性、独立性好,在软件需要升级的时候,开发人员只需要修改相应的DLL文件就可以了,而且,当DLL中的函数改变后,只要不是参数的改变,程序代码并不需要重新编译。这在编程时十分有用,大大提高了软件开发和维护的效率。
既然DLL那么重要,所以搞清楚什么是DLL、如何在Windows操作系统中开发使用DLL是程序开发人员不得不解决的一个问题。本文针对这些问题,通过一个简单的例子,即在一个DLL中实现比较最大、最小整数这两个简单函数,全面地解析了在Visual C++编译环境下编程实现DLL的过程,文章中所用到的程序代码在Windows98系统、Visual C++6.0编译环境下通过。
二、DLL的概念
DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。DLL库不同于静态库,在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.LIB),Visual C++的编译器在处理程序代码时将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件。这个过程称为"静态链接",此时因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行。
在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。
微软的Visual C++支持三种DLL,它们分别是Non-MFC Dll(非MFC动态库)、Regular Dll(常规DLL)、Extension Dll(扩展DLL)。Non-MFC DLL指的是不用MFC的类库结构,直接用C语言写的DLL,其导出的函数是标准的C接口,能被非MFC或MFC编写的应用程序所调用。Regular DLL:和下述的Extension Dlls一样,是用MFC类库编写的,它的一个明显的特点是在源文件里有一个继承CWinApp的类(注意:此类DLL虽然从CWinApp派生,但没有消息循环),被导出的函数是C函数、C++类或者C++成员函数(注意不要把术语C++类与MFC的微软基础C++类相混淆),调用常规DLL的应用程序不必是MFC应用程序,只要是能调用类C函数的应用程序就可以,它们可以是在Visual C++、Dephi、Visual Basic、Borland C等编译环境下利用DLL开发应用程序。
常规DLL又可细分成静态链接到MFC和动态链接到MFC上的,这两种常规DLL的区别将在下面介绍。与常规DLL相比,使用扩展DLL用于导出增强MFC基础类的函数或子类,用这种类型的动态链接库,可以用来输出一个从MFC所继承下来的类。
扩展DLL是使用MFC的动态链接版本所创建的,并且它只被用MFC类库所编写的应用程序所调用。例如你已经创建了一个从MFC的CtoolBar类的派生类用于创建一个新的工具栏,为了导出这个类,你必须把它放到一个MFC扩展的DLL中。扩展DLL 和常规DLL不一样,它没有一个从CWinApp继承而来的类的对象,所以,开发人员必须在DLL中的DllMain函数添加初始化代码和结束代码。
三、动态链接库的创建
在Visual C++6.0开发环境下,打开FileNewProject选项,可以选择Win32 Dynamic-Link Library或MFC AppWizard[dll]来以不同的方式来创建Non-MFC Dll、Regular Dll、Extension Dll等不同种类的动态链接库。
1. Win32 Dynamic-Link Library方式创建Non-MFC DLL动态链接库
每一个DLL必须有一个入口点,这就象我们用C编写的应用程序一样,必须有一个WINMAIN函数一样。在Non-MFC DLL中DllMain是一个缺省的入口函数,你不需要编写自己的DLL入口函数,用这个缺省的入口函数就能使动态链接库被调用时得到正确的初始化。如果应用程序的DLL需要分配额外的内存或资源时,或者说需要对每个进程或线程初始化和清除操作时,需要在相应的DLL工程的.CPP文件中对DllMain()函数按照下面的格式书写。
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
}
return TRUE;
}
参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符);ul_reason_for_call是一个说明动态库被调原因的标志,当进程或线程装入或卸载动态链接库的时候,操作系统调用入口函数,并说明动态链接库被调用的原因,它所有的可能值为:DLL_PROCESS_ATTACH: 进程被调用、DLL_THREAD_ATTACH: 线程被调用、DLL_PROCESS_DETACH: 进程被停止、DLL_THREAD_DETACH: 线程被停止;lpReserved为保留参数。到此为止,DLL的入口函数已经写了,剩下部分的实现也不难,你可以在DLL工程中加入你所想要输出的函数或变量了。
我们已经知道DLL是包含若干个函数的库文件,应用程序使用DLL中的函数之前,应该先导出这些函数,以便供给应用程序使用。要导出这些函数有两种方法,一是在定义函数时使用导出关键字_declspec(dllexport),另外一种方法是在创建DLL文件时使用模块定义文件.Def。需要读者注意的是在使用第一种方法的时候,不能使用DEF文件。下面通过两个例子来说明如何使用这两种方法创建DLL文件。
1)使用导出函数关键字_declspec(dllexport)创建MyDll.dll,该动态链接库中有两个函数,分别用来实现得到两个数的最大和最小数。在MyDll.h和MyDLL.cpp文件中分别输入如下原代码:
//MyDLL.h
extern "C" _declspec(dllexport) int Max(int a, int b);
extern "C" _declspec(dllexport) int Min(int a, int b);
//MyDll.cpp
#include
#include"MyDll.h"
int Max(int a, int b)
{
if(a>=b)return a;
else
return b;
}
int Min(int a, int b)
{
if(a>=b)return b;
else
return a;
}
该动态链接库编译成功后,打开MyDll工程中的debug目录,可以看到MyDll.dll、MyDll.lib两个文件。LIB文件中包含DLL文件名和DLL文件中的函数名等,该LIB文件只是对应该DLL文件的"映像文件",与DLL文件中,LIB文件的长度要小的多,在进行隐式链接DLL时要用到它。读者可能已经注意到在MyDll.h中有关键字"extern C",它可以使其他编程语言访问你编写的DLL中的函数。
2)用.def文件创建工程MyDll
为了用.def文件创建DLL,请先删除上个例子创建的工程中的MyDll.h文件,保留MyDll.cpp并在该文件头删除#include MyDll.h语句,同时往该工程中加入一个文本文件,命名为MyDll.def,再在该文件中加入如下代码:
LIBRARY MyDll
EXPORTS
Max
Min
其中LIBRARY语句说明该def文件是属于相应DLL的,EXPORTS语句下列出要导出的函数名称。我们可以在.def文件中的导出函数后加@n,如Max@1,Min@2,表示要导出的函数顺序号,在进行显式连时可以用到它。该DLL编译成功后,打开工程中的Debug目录,同样也会看到MyDll.dll和MyDll.lib文件。
2.MFC AppWizard[dll]方式生成常规/扩展DLL
在MFC AppWizard[dll]下生成DLL文件又有三种方式,在创建DLL是,要根据实际情况选择创建DLL的方式。一种是常规DLL静态链接到MFC,另一种是常规DLL动态链接到MFC。两者的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的规则DLL所有输出的函数应该以如下语句开始:
AFX_MANAGE_STATE(AfxGetStaticModuleState( )) //此语句用来正确地切换MFC模块状态
最后一种是MFC扩展DLL,这种DLL特点是用来建立MFC的派生类,Dll只被用MFC类库所编写的应用程序所调用。前面我们已经介绍过,Extension DLLs 和Regular DLLs不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化,你可以在此函数中实现初始化,代码如下:
BOOL WINAPI APIENTRY DLLMain(HINSTANCE hinstDll,DWORD reason ,LPVOID flmpload)
{
switch(reason)
{
……………//初始化代码;
}
return true;
}
参数hinstDll存放DLL的句柄,参数reason指明调用函数的原因,lpReserved是一个被系统所保留的参数。对于隐式链接是一个非零值,对于显式链接值是零。
在MFC下建立DLL文件,会自动生成def文件框架,其它与建立传统的Non-MFC DLL没有什么区别,只要在相应的头文件写入关键字_declspec(dllexport)函数类型和函数名等,或在生成的def文件中EXPORTS下输入函数名就可以了。需要注意的是在向其它开发人员分发MFC扩展DLL 时,不要忘记提供描述DLL中类的头文件以及相应的.LIB文件和DLL本身,此后开发人员就能充分利用你开发的扩展DLL了。
四、动态链接库DLL的链接
应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接。在使用DLL之前首先要知道DLL中函数的结构信息。Visual C++6.0在VCbin目录下提供了一个名为Dumpbin.exe的小程序,用它可以查看DLL文件中的函数结构。另外,Windows系统将遵循下面的搜索顺序来定位DLL: 1.包含EXE文件的目录,2.进程的当前工作目录, 3.Windows系统目录, 4.Windows目录,5.列在Path环境变量中的一系列目录。
1.隐式链接
隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中。实现隐式链接很容易,只要将导入函数关键字_declspec(dllimport)函数名等写到应用程序相应的头文件中就可以了。下面的例子通过隐式链接调用MyDll.dll库中的Min函数。首先生成一个项目为TestDll,在DllTest.h、DllTest.cpp文件中分别输入如下代码:
//Dlltest.h
#pragma comment(lib,"MyDll.lib")
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
//TestDll.cpp
#include
#include"Dlltest.h"
void main()
{int a;
a=min(8,10)
printf("比较的结果为%dn",a);
}
在创建DllTest.exe文件之前,要先将MyDll.dll和MyDll.lib拷贝到当前工程所在的目录下面,也可以拷贝到windows的System目录下。如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C"。TestDll.h文件中的关键字Progam commit是要Visual C+的编译器在link时,链接到MyDll.lib文件,当然,开发人员也可以不使用#pragma comment(lib,"MyDll.lib")语句,而直接在工程的Setting->Link页的Object/Moduls栏填入MyDll.lib既可。
2.显式链接
显式链接是应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。不过实现显式链接要麻烦一些。在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态链接库调进来,动态链接库的文件名即是上述两个函数的参数,此后再用GetProcAddress()获取想要引入的函数。自此,你就可以象使用如同在应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary释放动态链接库。下面是通过显式链接调用DLL中的Max函数的例子。
#include
#include
void main(void)
{
typedef int(*pMax)(int a,int b);
typedef int(*pMin)(int a,int b);
HINSTANCE hDLL;
PMax Max
HDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL,"Max");
A=Max(5,8);
Printf("比较的结果为%dn",a);
FreeLibrary(hDLL);//卸载MyDll.dll文件;
}
在上例中使用类型定义关键字typedef,定义指向和DLL中相同的函数原型指针,然后通过LoadLibray()将DLL加载到当前的应用程序中并返回当前DLL文件的句柄,然后通过GetProcAddress()函数获取导入到应用程序中的函数指针,函数调用完毕后,使用FreeLibrary()卸载DLL文件。在编译程序之前,首先要将DLL文件拷贝到工程所在的目录或Windows系统目录下。
使用显式链接应用程序编译时不需要使用相应的Lib文件。另外,使用GetProcAddress()函数时,可以利用MAKEINTRESOURCE()函数直接使用DLL中函数出现的顺序号,如将GetProcAddress(hDLL,"Min")改为GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函数Min()在DLL中的顺序号是2),这样调用DLL中的函数速度很快,但是要记住函数的使用序号,否则会发生错误。
本文通过通俗易懂的方式,全面介绍了动态链接库的概念、动态链接库的创建和动态链接库的链接,并给出个简单明了的例子,相信读者看了本文后,能够创建自己的动态链接库并应用到后续的软件开发当中去了,当然,读者要熟练操作DLL,还需要在大量的实践中不断摸索,希望本文能起到抛砖引玉的作用。
查看全文
在VB中指定MsgBox显示位置
利用钩子函数捕获Windows键盘动作
在科研生产 中对研制、调试操作的记录是非常有必要而且是有很重要价值的。通过对记录信息的分析,可以在事故发生后准确的分析出事故的起因、操作是否存在失误等许多重 要线索。通常需要记录的信息是多种多样的,如环境温度记录、软件运行记录、文件访问记录等等。这里将以键盘信息记录为例来讲述类似的实验信息自动记录的一 般实现方法。
由于需要记录当前系统下所有应用程序的键盘录入记录,因此必须采取某种特殊的技术来实现本进程(监视程序)对外部进程键 盘操作信息的获取。这种技术便是本文将要论述的核心--系统全局钩子。本文下面将对Win32平台下全局钩子的运行机制进行介绍并给出了一个具体的由VC ++6.0编写的捕获键盘动作的键盘钩子示例程序。
系统钩子和DLL
钩子的本质是一段用以处 理系统消息的程序,通过系统调用,将其挂入系统。钩子的种类有很多,每种钩子可以截获并处理相应的消息,每当特定的消息发出,在到达目的窗口之前,钩子程 序先行截获该消息、得到对此消息的控制权。此时在钩子函数中就可以对截获的消息进行加工处理,甚至可以强制结束消息的传递。
在本程序 中我们需要捕获在任意窗口上的键盘输入,这就需要采用全局钩子以便拦截整个系统的消息,而全局钩子函数必须以DLL(动态连接库)为载体进行封装,VC6 中有三种形式的MFC DLL可供选择,即Regular statically linked to MFC DLL(标准静态链接MFC DLL)、Regular using the shared MFC DLL(标准动态链接MFC DLL)以及Extension MFC DLL(扩展MFC DLL)。 在本程序中为方便起见采用了标准静态连接MFC DLL。
键盘钩子程序示例
本示例程序用到全局钩子函数,程序分两部分:可执行程序KeyKook和动态连接库LaunchDLL。首先创建一个MFC AppWizard(DLL)工程,并选择Regular statically linked to MFC DLL(标准静态链接MFC DLL)选项,以建立MFC扩展动态连接库LaunchDLL.dll。之后,在相应的头文件中添加宏定义和待导出函数的声明:
| #define DllExport __declspec(dllexport) …… DllExport void WINAPI InstallLaunchEv(); …… class CLaunchDLLApp : public CWinApp { public: CLaunchDLLApp(); //{{AFX_VIRTUAL(CLaunchDLLApp) //}}AFX_VIRTUAL //{{AFX_MSG(CLaunchDLLApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; |
同时在实现文件中添加全局变量Hook和全局函数LauncherHook()、SaveLog():
| HHOOK Hook; LRESULT CALLBACK LauncherHook(int nCode,WPARAM wParam,LPARAM lParam); void SaveLog(char* c); |
最后,完成以上提到的这几个函数的具体编码实现:
| CLaunchDLLApp theApp; …… DllExport void WINAPI InstallLaunchEv() { Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)LauncherHook,theApp.m_hInstance,0); } |
在此我们实现了Windows的系统钩子的安装,首先要调用SDK中的API函数SetWindowsHookEx()来安装这个钩子函数,其原型是:
| HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId); |
其中,第一个参数指定钩子的类型,常用的有WH_MOUSE、
WH_KEYBOARD、WH_GETMESSAGE等,在此我们只关心键盘操作所以设定为WH_KEYBOARD;第二个参数标识钩子函数的入口地址,
当钩子钩到任何消息后便调用这个函数,即当不管系统的哪个窗口有键盘输入马上会引起LauncherHook的动作;第三个参数是钩子函数所在模块的句
柄,我们可以很简单的设定其为本应用程序的实例句柄;最后一个参数是钩子相关函数的ID用以指定想让钩子去钩哪个线程,为0时则拦截整个系统的消息,在本
程序中钩子需要为全局钩子,故设定为0。
| LRESULT CALLBACK LauncherHook(int nCode,WPARAM wParam,LPARAM lParam) { LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam); if(nCode==HC_ACTION) { if(lParam & 0x80000000) { char c[1]; c[0]=wParam; SaveLog(c); } } return Result; } |
虽然调用CallNextHookEx()是可选的,但调用此函数的习惯是很值得推荐的;否则的话,其他安装了钩子的应用程序将不会接收到钩子的通知而且还有可能产生不正确的结果,所以我们应尽量调用该函数除非绝对需要阻止其他程序获取通知。
| void SaveLog(char* c) { CTime tm=CTime::GetCurrentTime(); CString name; name.Format("c:Key_%d_%d.log",tm.GetMonth(),tm.GetDay()); CFile file; if(!file.Open(name,CFile::modeReadWrite)) { file.Open(name,CFile::modeCreate|CFile::modeReadWrite); } file.SeekToEnd(); file.Write(c,1); file.Close(); } |
当有键弹起的时候就通过此函数将刚弹起的键保存到记录文件中从而实现对键盘进行监控记录的目的。编译完成便可得到运行时所需的键盘钩子的动态连接库和进行静态链接时用到的lib库。
下面开始编写调用此动态连接库的主程序,并实现最后的集成。另外创建一个单文档应用程序,把所需的动态链接库头文件、lib库复制到工程目录中,将动态 链接库复制到Debug目录下。然后链接DLL库:在"Project","Settings…"的"Link"属性页内,在 "Object/librarymodules:"中填入"LaunchDLL.lib"。再通过"Project","Add To Project","Files…"将LaunchDLL.h添加到工程中来,最后在视类的源文件KeyHook.cpp中加入对其的引用:
| #include "LaunchDLL.h" |
这样我们就可以象使用本工程内的 函数一样使用动态连接库LaunchDLL.dll中的所有导出函数了。接下来在视类重载虚函数OnInitialUpdate(),并添加代码完成对键盘钩子的安装:
| InstallLaunchEv(); |
到此为止其实已经完成了所有的功能,但 由于本程序是作为一个后台监控软件运行,因此还应当采取其他措施以隐藏其程序界面。这只需在应用程序类CkeyHookApp的InitInstance ()函数中将m_pMainWnd->ShowWindow(SW_SHOW)改为m_pMainWnd->ShowWindow (SW_HIDE)即可。
小结
编译运行程序,运行起来之后并无什么现象,但通过Alt+Ctrl +Del在关闭程序对话框内可以找到我们刚编写完毕的程序"KeyHook",随便在什么程序中通过键盘输入字符,然后打开记录文件,我们会发现:通过键 盘钩子,我们刚才输入的字符都被记录到记录文件中了。系统钩子具有相当强大的功能,通过这种技术可以对几乎所有的Windows系统消息进行拦截、监视、 处理。这种技术广泛应用于各种自动监控系统中。本文所述程序在Windows 2000 Professional + SP4下由Microsoft Visual C++ 6.0编译调试通过。 查看全文
利用钩子函数捕获Windows鼠标动作
我们知道,Windows系统是建立在消息传递机制基础上的,几乎所有的程序活动都由消息来驱动。Windows的钩子机制可以看作是一个消息中转 站,控制系统发出消息的处理和传递,利用钩子,我们可以截获系统发给应用程序的消息,经过处理后决定是否将消息再发给下一个应用程序。
利用钩子的这一特性,我们可以创建一个监控程序,用来收集和控制系统发出的消息。
■编制Windows钩子程序
编制Windows的钩子程序,需要用到几个SDK中的API函数。下面列出这几个函数的原型及说明:
HHOOK SetWindowsHookEx( int idHook,HOOK_PROC lpfn,HINSTANCE hMod,DWORD dwThreadID);
参数说明如下:
idHook:钩子的类型
lpfn:钩子处理函数地址
hMod:包含钩子函数的模块句柄
dwThreadID:钩子的监控线程
函数说明:函数将在系统中挂上一个由idHook指定类型的钩子,监控并处理相应的特定消息。
BOOL UnhookWindowsHookEx(HHOOK hhk);
函数说明:函数将撤销由hhk指定的钩子。
LRESULT CallNextHookEx( HHOOK hhk, int nCode,WPARAM wParam,LPARAM lParam );
函数说明:函数将消息向下传递,下一个钩子处理将截获这一消息。
由于钩子的处理涉及到模块及进程间的数据地址问题,一般情况是把钩子整合到一个动态链接库(DLL)中,并设立一个全局数据共享数据段,以存贮一些全局变量,保留上次钩子消息事件发生时的状态。全局共享数据段可以用如下的格式定义:
#pragma data_seg("PublicData")
HHOOK hhook=NULL;
//全局共享数据
#pragma data_seg()
本文的范例程序演示了如何编制一个鼠标钩子(WH_MOUSE)程序,其它类型的钩子程序的编写过程与范例程序类似。
■范例程序的建立与代码分析
建立钩子程序时需要把钩子处理整合到动态链接库中,所以例程中需要建立两个Project。
1.建立钩子处理动态链接库
(1) 选择MFC AppWizard(DLL)创建一个新Project,命名为“Spy”。
(2) 选择MFC Extension DLL类型。
(3)创建一个新的头文件,命名为“Hook.h”,修改它的代码如下:
extern "C" LRESULT CALLBACK MouseProc(int code,
WPARAM wParam,LPARAM lParam); //钩子处理函数
extern "C" BOOL WINAPI StartHook();
//启动钩子函数
extern "C" BOOL WINAPI StopHook();
//撤销钩子函数
extern "C" int WINAPI GetResult();
//取得鼠标单击次数的函数
(4)修改Spy.cpp程序代码如下:
#include "stdafx.h"
#include 〈afxdllx.h〉
#include "spyhook.h"
……
//省略部分机器生成代码
#pragma data_seg("PublicData")
//定义全局数据段
HHOOK hhook=NULL;
//钩子句柄
HINSTANCE pInstance=NULL;
//钩子模块句柄
UINT MouseClick=0;
//记录鼠标单击次数的变量
#pragma data_seg()
……
//省略部分机器生成代码
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason = = DLL_PROCESS_ATTACH)
{……
//省略部分机器生成代码
new CDynLinkLibrary(SpyDLL);
pInstance=hInstance;
//取得模块句柄
}
else if (dwReason = = DLL_PROCESS_DETACH)
{
TRACE0("SPY.DLL Terminating!n");
AfxTermExtensionModule(SpyDLL);
}
return 1;
}
extern "C" LRESULT CALLBACK MouseProc(int code,WPARAM wParam,LPARAM lParam)
//钩子处理函数
{
if (code 〈 0)
//若code〈0,则直接调用CallNextHookEx返回
return CallNextHookEx(hhook, code, wParam, lParam);
if(wParam= =WM_LBUTTONDOWN)
{MouseClick++;
//记录鼠标单击次数
}
return CallNextHookEx(hhook, code, wParam,lParam);
}
extern "C" BOOL WINAPI StartHook()
//启动钩子函数
{
hhook=SetWindowsHookEx(WH_MOUSE,MouseProc,pInstance,0);
//挂上钩子
if(hhook!=NULL)
return TRUE;
else return FALSE;
}
extern "C" BOOL WINAPI StopHook()
//撤销钩子函数
{
return UnhookWindowsHookEx(hhook);
//撤销钩子
}
extern "C" int WINAPI GetResult()
//返回鼠标单击次数
{
return MouseClick;
}
(5)修改Spy.def程序代码如下:
LIBRARY "SPY"
DESCRIPTION 'SPY Windows Dynamic Link Library'
EXPORTS
StartHookb @1
StopHook @2
GetResult @3
(6)编译Project,生成Spy.dll文件和Spy.Lib文件。
2.建立使用钩子的应用程序
(1) 生成一个单文档的可执行文件(EXE)的Project。
(2) 修改资源中的主选单,增加一个选单项“监控”,下有三个子选单项,分别为“启动”、“撤销”和“取出”。
(3) 在Project中加入Spy.Lib文件和Hook.h文件。
(4) 分别修改“启动”、“撤销”和“取出”选单项的Command响应函数如下:
#include "hook.h"
……//省略部分机器生成代码
void CMainFrame::OnStartSpy()
//“启动”选单项的响应函数
{
StartHook();
}
void CMainFrame::OnReleaseSpy()
//“撤销”选单项的响应函数
{
StopHook();
}
void CMainFrame::OnGet()
//“取出”选单项的响应函数
{
int Result=GetResult();
char buffer[40];
wsprintf(buffer,"在程序运行期间,你共单击鼠标%d次",Result);
::MessageBox(this-〉m_hWnd,buffer,"Message",MB_OK);
}
编译这个Project,并把Spy.dll放到生成的可执行文件目录下,便可运行程序。
运行时,选择“监控”选单中的“启动”选单项,钩子便开始工作,监视鼠标的活动情况;选择“撤销”选单项,系统便撤销钩子;选择“取出”选单项,程序便报告在监控期间,用户单击鼠标左键的次数。
Eclipse迎来新时代,全面支持C/C++开发
著名的开源组织Eclipse Foundation于近日发布了CDT 2.0 (C Development Tool 2.0),标志着Eclipse全面支持C/C++的软件开发,为开发人员提供了又一个C/C++的集成开发环境。
Eclipse是IBM捐献并积极支持的开源项目,它凝聚了来自世界各地的优秀软件开发人员不断的贡献和创新,仅以两年的发展历史,Eclipse就先后 夺得Jolt最佳IDE奖、JDJ编辑推荐IDE等殊荣。Eclipse成功之处包括其灵活且统一的插件机制,它授予了独立软件供应商(ISV)开发兼容 Eclipse插件的能力,并使得Eclipse自身的功能可无限扩充。市面上支持Eclipse的插件由去年的200个增长到现在的500多个,涵盖数 据库连接、语法矫正、代码生成、可视化编辑,等多个领域。IBM的Websphere Studio Application Developer 5.x (一个企业级的Java集成开发环境) 就是由Eclipse加上300多个插件构成的。
Eclipse另一买点是可在多个操作系统上运行,具有跨平台的特性。无论你是在Windows上还是在Linux的世界里, 你都可使用Eclipse,并享受一致的操作体验。 这一特点对C/C++开发人员尤其重要。很多C/C++的项目需要在Linux或Unix上运行,但在Eclipse的CDT出现之前,Linux和 Unix下并没有真正意义上的C集成开发环境。许多开发人员"退而求其次",先在 Windows里用Visual Studio来编写C程序,然后导入到Linux或Unix平台上调试,这样的做法非常不便。现在Eclipse提供了跨平台的C集成开发环境,C程序员 可直接在Linux或Unix上使用它,这样编写、编译、调试都可在同一个平台上执行。
Eclipse由四个部分组成---Eclipse Platform,JDT, CDT, 和PDE。Eclipse Platform提供了一个通用的开发平台,JDT (Java Development Tool)支持Java开发,CDT (C Development Tool)支持C开发,PDE (Plugin Development Environment)为编写插件提供了便捷的开发环境。
新版的CDT 2.0和Eclipse 3.0几乎同时推出,CDT2.0提供了许多方便C/C++开发的新特性:
Globalization (多国语言支持)
CDT包含了多个语言包,支持Brazilian Portuguese, French, German, Italian, Japanese, Korean, Spanish, Simplified Chinese 简体中文, 和 Traditional Chinese 繁体中文。
Automatic Project Settings Discovery (自动化的项目设定发现)
在C/C++ Make Project > Discovery Options的项目设置对话筐里,可设定自动生成项目的defines和include路径。
Multiple Binary Architectures Per Project
如果需要编译多个Binary格式,可在Binary Parser里选择适当的格式。
Include Paths and Symbols
用C/C++ Include Paths and Symbols来设定项目以支持搜索,索引和其它源码导航功能。
Source Folders
在 C/C++ Project Paths 项目属性对话框里设定哪些文件和目录是source, output或library。
C/C++ File Types
在 C/C++ File Types 里定义特别文件尤其是C++ 没有扩展名的头文件。
Build Console Colours
可在Window > Preferences > C/C++ > Build Console里设定颜色,从而使Console(控制台)里输出的结果更方便查错。
C/C++ Content Assist
有了"C/C++编码助手"编写C代码容易得多了! "C/C++编码助手"可自动补全所有的class和structure成员,local和global变量,pre-processor defines, 和 pre-processor commands。
Rename Refactoring
C/C++程序员现在也可享受"重构" (Refactor) 的好处了。在 Refactor > Rename 的弹出式菜单里可选对 class,type names, methods, functions,和member names进行一次性安全的重命名。
Open Type
Navigate > Open type (Ctrl-Shift-T) 打开一个对话框,在此对话框里可过滤 C/C++ classes, structures, unions, typedefs, enumerations 和 namespaces.
C/C++ Browsing Perspective
可在 C/C++ Browsing Perspective 里浏览一个项目中的 class 和 structure members。
Makefile Editor
Makefile Editor 提供语法高亮显示, 代码自动补全,和content outlining功能。
Mixed Source/Assembly
Disassembly View 可同时显示 assembly code 和 source !
Global Variables
全局变量可在 Variables View 浏览。
通用功能
除了CDT2.0本身的功能,使用Eclipse的C程序员也可Eclipse Platform提供的通用功能,比如: 内建的CVS版本控制,本地历史记录追踪,插件 / 补丁管理,一站式的补丁升级,等等。
总结
在短短的两年里,Eclipse已经发展成适用于企业级软件开发的IDE,并足可和商用IDE比如JBuilder、WebSphere Studio、IntelliJ媲美。
现在,Eclipse已经瞄准世界上最大的程序员群体 --- C/C++程序员。Eclipse不再只是Java开发人员独享的IDE了,CDT 2.0提供了C/C++开发环境。Eclipse的宗旨就是为开发人员提供一个统一的开发平台。因此有人说Eclipse不是传统意义上的IDE (集成开发环境),而应该是 UDE (Universal Developement Environment 通用开发环境)。
Eclipse在两年的时间里就有如此成就,未来它还会带给我们什么样的惊喜? 我们可以翘首以待,但何不现在就享受Eclipse带来的开发体验呢?
Eclipse官方网站
http://www.eclipse.org/
CDT网页
http://www.eclipse.org/cdt/
Eclipse插件网站
http://eclipse-plugins.2y.net/eclipse/index.jsp
Eclipse插件中心
http://www.eclipseplugincentral.com/
Linux下的QQ
虽然本人并不喜欢OICQ,但是由于中国网络IM市场多数部分被OICQ占领,所以在非WINDOWS平台上实现QQ的操作还是有必要的。以下所介绍的就是在LINUX(Fedora Core 3)环境下,来实现OICQ的操作。
虽 然在OICQ最初在LINUX下实现的时候并非使用我们现在所介绍的这个软件(LUMAQQ)而是使用由GAIM修改的OPEN QQ,但很多情况下,安 装一个支持OICQ的GAIM,是并非容易的一件事情,它需要许多情况的调试,而且在通常情况下会破坏原由的GAIM的设置,所以自从LUMAQQ被开发 出来之后,其接近OICQ的界面,和方便的设置使得用户很快就选择这款软件。
LUMAQQ是JAVA编译的,所以在安装LUMAQQ需要现安装JRE,当然LUMAQQ主页已经提供了捆绑JRE的LUMAQQ,让用户使用更加的方便。
安装LUMAQQ需以下一些操作。
1)下载LUMAQQ。LUMAQQ的主页上提供了其下载,另外最新的PATH3只是一个补丁文件,所以在下载P3的时候,必须先要下载主程序,如果捆绑JRE的LUMAQQ,则需要重新编译,所以如果不会JRE设置的人,暂时可以不更新LUMAQQ的P3补丁。
2)下载完毕以后。现改变文件的权限
chmod 755 <lumaqq 压缩包>
然后解压
tar zxvf <lumaqq压缩包>
3)配置环境变量
你可以直接用命令来配置环境变量或者使用用户下的配置文件.bashrc
个人建议是如果你是个人机器,那直接在/etc/profile中配置,因为在以后的情况下同样需要java环境,特别一些喜欢或是希望自己以后也可以开发JAVA的人们。
在文件开始部位:
# /etc/profile
# JRE 目录
JAVA_HOME=/opt/jdk1.5.0_01/jre/
export JAVA_HOME
注意大小写
设置完毕之后保存,然后直接执行profile或者是注销。
一切都准备就绪,那只要在LUMAQQ的目录下执行lumaqq就可以了。
LumaQQ官方网站
使用 Eclipse 平台共享代码
级别:中级 |
Pawel Leszek(pawel.leszek@ipgate.pl)
独立顾问
2003 年 8 月
本文概述了 Eclipse 平台如何支持软件项目中的源代码版本控制。首先,我们将简要讨论一下团队代码开发的思想,然后研究 Eclipse 如何使用 CVS 代码资源库。我们还将研究一些源代码管理软件工具,可以通过 Eclipse 插件扩展来支持这些工具。
在团队项目中共享源代码
现今的大多数应用程序是由多人组成的团队开发的。即使只涉及几个开发人员的小项目,也需要对源代码的更改进行严格控制。这就是源代码管理软件的任务。
源代码版本控制软件必须支持两个核心功能:
- 提供一种方法,能够协调对源代码的更改,并能集成这些更改
- 团队所提交工作的历史记录
当 团队成员完成新的工作时,通过将这些更改提交到资源库来共享他们的工作。类似地,当他们希望获得最新可用的工作成果时,就可以根据资源库中的更改,更新自 己的本地工作空间。这意味着项目资源库会因团队成员提交新工作成果而经常发生更改。换句话说,资源库应该表示项目的当前状态。任何时候,团队成员都要能够 根据资源库更新自己的工作空间,并确信它们是最新的。
维护历史记录也很重要,那样就可以将当前工作与先前版本进行比较,如有必要,还可以回复到先前版本。协调团队的工作,以便只存在唯一的当前项目状态定义,以及包含团队已集成的工作,这些对于管理版本控制也是十分必要的。这种协调有可能是最难实现的目标。
最 理想的模型是:团队的任何成员都可以对自己有权访问的任何资源进行更改。因为两个团队成员可以提交对同一资源的更改,所以有可能发生冲突,必须解决这种冲 突。这种模型假定冲突具有唯一性。但遗憾的是,没有任何源代码是孤立地存在的;通常它包含与其它资源隐式或显式的相关性。源代码引用了在其它源代码资源中 描述的构件。但源代码管理软件的工作就到此为止了,因为它并不能取代项目管理。项目管理者必须履行其职责:协调其它成员的工作以及负责进度、项目阶段和发 布日期。此外,源代码管理也不能替代开发人员之间的交流。
Eclipse 平台如何支持代码管理
Eclipse 平台提供了作为团队在软件项目中共享代码和工作的能力。Eclipse 广泛地支持各种代码管理解决方案,这要归功于它的插件体系结构(不过,现已推出了对 CVS 的支持)。Eclipse 平台体系结构的重点在于工作空间。工作空间维护构建和测试软件项目所需的一切。它包含对象(源代码和资源)。
它还保存了用于项目、IDE 和插件的配置设置。工作空间是在开发人员的机器上本地进行维护的,而团队通过外部资源库进行协作,不同开发人员的代码在资源库进行汇集。可以经由因特网通过“客户机-服务器”体系结构访问资源库。
Eclipse 平台提供了对于直接从工作空间进行团队开发操作的支持。这种支持允许开发人员并发地与几个独立的资源库以及不同版本的代码或项目进行交互。工作空间中的资 源允许团队支持组件处理版本和配置管理问题。当然,单个工作空间可以同时访问不同类型的资源库。Eclipse 平台并没有提供它自己的代码管理解决方案;它总是依靠外部系统。Eclipse 平台只对一个(但也是最流行的一个)源代码管理系统提供内置支持:并发版本控制系统(Concurrent Versions System,CVS)。对第三方代码管理应用程序的支持一节中描述了使用第三方插件支持其它资源库。
CVS 是什么?
CVS 诞生于 1986 年,当时作为一组 shell
脚本而出现,但它现在已经发展成了最流行的针对软件开发人员的源代码版本管理解决方案。CVS
是用于代码版本管理的开放源码的客户机/服务器解决方案,它可用于各种平台,包括 Linux 和 Windows
NT/2000/XP。请参阅本文末尾的参考资料,其中有 CVS 客户机、服务器和源代码的下载链接。
通常,CVS 的主要功能是记录源文件的历史。当一组开发人员从事同一个项目时,CVS 将他们彼此隔离开来。每个开发人员都在他/她自己的目录中独立工作,然后使用 CVS 资源库(不时地)合并工作结果。
Eclipse 拥有与 Eclipse 平台 IDE 紧密集成的内置 CVS 客户机,它是作为一个单独透视图(CVS Repository Exploring 透视图)而实现的,用于与 CVS 的交互。用于 CVS 的通用 Eclipse 设置(General Eclipse settings for CVS)位于 Window -> Preferences window -> Team 下。在切换到 CVS Repository Exploring 透视图之后,就可以使用所有 CVS 操作了(转至 Window -> Open Perspective -> Other -> CVS Repository Exploring 菜单 — 请参阅图 1 和图 2)。
图 1. 切换到 CVS Repository Exploring 透视图
首先设置资源库的位置,它将定义用于选定 CVS 服务器/资源库的连接参数。请确保使用 SSH 隧道(extssh)。
图 2. 浏览 CVS Repository Exploring 透视图中的 CVS 资源库
Eclipse/CVS 的源代码工作流
在 CVS 团队协作模型中,团队成员彼此独立地在他们各自的工作台上完成自己的所有工作。最后,他们希望共享其工作。他们通过 CVS
资源库实现这一点。CVS 使用分支(branch)模型来支持彼此独立而又高度相互依赖的多个工作流程(course of
work)。这些分支是开发团队用来共享和集成正在进行中的工作的地方。可以认为分支是一个共享的工作台,当团队成员对源代码进行更改时就更新这个工作台。这个模型允许从事 CVS 团队项目的每个开发人员在进行更改时与其他成员共享其工作,以及在项目进展期间访问其他成员的工作。
一个称为 HEAD 的特殊分支用来表示资源库中的主要工作流程(HEAD 通常被称为主干)。当团队成员将资源提交给该分支时,会影响这些相关性。 确保相关性的完整性是很重要的,因为该分支表示了当前项目的状态。当然,任何时候,团队成员都可以使用该分支的内容作为新工作的基础。
那些规则不仅适用于 CVS:无论使用哪种版本控制软件,团队项目中都有一些用于源代码管理的常见步骤。下面是一个使用 Eclipse 内置的 CVS 支持的示例工作流:
1. 启动新的团队项目
每个新的空 Eclipse 项目都可以通过 CVS(或受支持的任何其它源代码管理系统)进行共享。开发人员也可以通过将其现有的代码迁移到资源库来共享它。要进行共享,单击项目主文件夹,在显示的上下文菜单中使用 Team -> Share Project 选项,如图 3 所示。
另一个选项是通过从选定的 CVS 资源库分支导入代码来创建新的工作台项目。只要选择适当分支(或 HEAD),然后选择从 CVS Repository Exploring 透视图中的上下文菜单中选择“Checkout As Project”选项,如图 4 所示。
2. 使用代码并进行更改
开发人员通过 Eclipse 工作台在本地使用代码,包括的工作有创建新资源、修改现有资源、编写注释,并在他们使用后在本地保存这些内容。
3. 使本地更改与 CVS 资源库同步
如果一个项目开发人员准备提交他/她的工作,那么首先要执行更新操作。这会针对引入的更改核对资源库,并将这些更改添加到该开发人员的本地工作台。这样确保了开发人员知道这些更改可能会影响他/她将要提交的工作的完整性。使用项目上下文菜单中的 Compare With... 选项将本地版本与资源库中存储的代码进行比较(请参阅图 5)。
下一步是解决最后出现的任何冲突,并设法再次编译代码。如果一切正常,那么从项目上下文菜单使用 Team -> Commit... 选项执行提交操作,如图 6 所示。这会使所有更改都集成到资源库中。
4. 管理资源库
CVS 允许开发人员将更改隔离在开发的某些独立路径之内,这些路径称为分支。当一个开发人员更改某个分支上的文件时,这种更改不会出现在主干或其它分支上。
那些分支被命名为子版本(subversion)或代码分叉(code fork)。稍后,由合并操作将更改从一个分支迁移到另一个分支(或主干)。然后提交这些修订。这样就有效地将更改复制到了另一个分支上。使用项目上下文菜单的 Team -> Branch... 选项,Eclipse 使开发分支之间的迁移变得容易。
当然,当开发团队维护大型资源库时,有必要控制项目内的提交和合并操作。Eclipse/CVS 集成提供了一种特殊的视图:CVS Repository History(请参阅图 7)。它给出了关于团队成员在资源库中所执行更改的快速预览。
图 7. 在 CVS Resource History 窗口中查看带注释的修订历史记录
Eclipse 平台提供了几个支持代码管理的实用程序。最有用的是补丁功能。它将出自两个来源(譬如本地工作台和资源库)的代码进行比较,然后创建一个包含代码差异的类似 UNIX 的补丁文件(请参阅图 8)。可以将该文件发送给开发人员以将源代码升级到最新版本。
5. 断开项目与 CVS 的连接
当项目开发已经结束,并且团队希望冻结源代码时,可以从 HEAD 资源库删除该项目的最终版本。断开项目与 CVS 的连接将在该项目及其资源上禁用资源库操作,并删除与该项目相关联的 CVS 信息(这一操作是可选的)。
可以通过项目上下文菜单中的 Team -> Disconnect 选项执行断开连接操作。通过选择这个选项,会打开 Confirm Disconnect from CVS 对话框。在将该项目与资源库的连接断开之后,该团队必须确定如何处理 CVS 信息。第一个选项是“Delete the CVS meta information”;它将禁用 CVS 团队菜单操作并从文件系统中删除 CVS 文件夹及其内容。第二个选项是“Do not delete the CVS meta information”;它将禁用 CVS 团队菜单操作,但保留 CVS 元信息。
对第三方代码管理应用程序的支持
CVS
有几个重要的限制:它不能确定单个文件或整个文件集范围内同时进行的更改,它也不能检测文件之间的逻辑冲突。其冲突概念纯粹是文本意义上的,当对于同一基
本文件的两个更改时间上非常非常接近,从而使合并命令受到干扰时,就会发生冲突。CVS
也不能提供任何类似于消息传递这样的交互式协作工具。幸运的是,CVS 并不是 Eclipse 平台所支持的唯一的源代码管理软件。
开发人员可以通过插件扩展 Eclipse 平台的功能,而且目前(到 2003 年 3 月 4 日为止)已有 16
个可用于团队开发软件的插件。所有插件都是由 Eclipse
社区或商业软件供应商创建的。这些插件中的大多数添加了对第三方、商业源代码管理系统的支持。最有价值的插件是那些支持流行的企业代码管理系统(如
Merant PVCS 和 Rational ClearCase)的插件。例如,CVS-SSH2 插件允许通过 SSH2 会话访问 CVS,而
Microsoft Visual SourceSafe(VSS)团队提供程序插件添加了对 MS VSS 产品的支持(也可以在诸如 Linux
这样的非 Windows 平台上使用)。
但是,我本人所偏爱的插件是 Koi(请参阅参考资料以 获取链接)。尽管它并非严格用于源代码控制,但这个创新的工具给协作开发注入了许多新的活力。其当前版本支持工作台到工作台的消息传递、共享标记、冲突更 改通知、共享日历和事件通知。Koi 将 XML-RPC 用作其客户机-服务器体系结构中的通信模型。客户机是与“协作服务器”通信的单个 Eclipse 平台实例,而协作服务器也是一个 Eclipse 插件。Koi 使用以 JDBC 访问的关系数据库作为数据存储。可在参考资料中找到指向完整的、经过分类的 Eclipse 插件注册表的链接。
- 请参加 eclipse.org
上的 Eclipse 平台社区。Eclipse 平台源代码遵循 Common Public License。Eclipse.org 还有一个
Eclipse 项目的术语和描述词汇表,以及技术文章和新闻组。Eclipse 平台白皮书(可在 Eclipse.org 主页获取)详细描述了
Eclipse 的主要组件和功能。
- 从 eclipse.org 下载 KOI 插件。
- 查看 Eclipse 插件的完整的、经过分类的注册表。
- 从 CVS 主页或 LORIA 站点下载 CVS 客户机、服务器和源代码。
- 请参阅 developerWorks 文章“Working the Eclipse Platform”,以了解关于 Eclipse 平台的背景知识。
- 请参阅 developerWorks 文章“Getting started with the Eclipse Platform”,这篇文章介绍了用 Eclipse 平台以及使用 Eclipse 插件编辑、编译和调试应用程序。
- 请参阅 developerWorks 文章“开发 Eclipse 插件”,这篇文章介绍了如何开发 Eclipse 插件。
- 从 developerWorks 的这些文章中获取关于 Eclipse 的更多信息:
- 在 developerWorks 开放源码项目专区查找更多有关 Eclipse 和开放源码参考资料。
Pawel Leszek 是 Studio B 的一位作家,他是一位专长于 Linux/Win/Mac OS 系统体系结构和管理的独立软件顾问和作家。他具有许多操作系统、编程语言和网络协议方面的经验,尤其是 Lotus Domino 和 DB2 方面。Pawel 还在 LinuxWorld 上发表过一系列文章,他是 PC World 波兰版的 Linux 专栏作家。Pawel 和他的妻子以及可爱的小女儿住在华沙。欢迎提问并提出意见;您可以通过 pawel.leszek@ipgate.pl 与 Pawel 联系。 查看全文
CDMA增值业务平台BREW的研究与应用
BREW(Binary Runtime Environment for Wireless,无线二进制运行环境),是高通公司推出CDMA网络 "无线互联网发射平台" 上增值业务开发运行的基本平台。它提供一个高效、低成本、可扩展和熟悉的应用程序执行环境(AEE),着重开发可无缝植入任何实际手持设备的应用程序。与建立在对内存空间、处理器速度和相关硬件有较高要求的操作系统之上的高端产品不同,BREW 在现有的设备类型上运行。传统上,人们热衷于能否利用高速ASIC(特定用途集成电路)技术实现新的应用功能,甚至在低端设备上,要使用更多的功能则需要无缝集成。现在,BREW提供的功能环境就好像PC机上的操作系统一样,可以通过服务提供商下载指定类型的应用程序或游戏来使用。同时,通过BREW接口功能,供应商可以提供成套的完整的资讯、商务、娱乐功能。在将来的版本中,BREW内核类将能提供诸如蓝牙技术、全球定位系统(GPS) 和基于数据业务的电话等服务。
BREW提供了一套应用程序接口(API),制造商和开发人员可以随时对运行环境进行扩展,提供应用程序需要的各种附加性能模块,如"无线互联网发射平台"中包含的多媒体、多种连接方式、位置服务、用户界面、网络等功能套件。
开发应用
BREW 为应用程序开发者提供了一个功能丰富且使用方便的环境,使其能够利用美国高通公司的移动基站调制解调器(MSM) ASIC 的已有及新增的功能开发新的软件,以适应增值业务发展的需要。BREW 的面向对象可充分扩展的应用程序执行环境,允许使用C 或C++ 开发小程序和共享模块。同时,它还支持Java和XML 等语言。
BREW 提供了一套完善的对象技术,使开发者可以非常方便开发基于图形的应用服务:
* 应用程序服务,支持简单的、基于事件的AEE
* 内核服务支持,对文件、网络服务、内存和屏幕的访问
* 增强型服务,例如增强图像性能(互动的游戏)、声音播放器(优质的音乐)、GPS 和语音服务
* 综合服务,使应用程序开发者可以利用诸如浏览器、Outlook所支持的服务
从运行环境和效率上看,BREW提供以下支持:
* BREW可有效地利用RAM 和持久存储器。BREW 可以在需要时加载或卸载使用的对象或内存
* BREW应用程序环境支持人们熟悉的与Microsoft Windows、 Macintosh 或UNIX X-Windows 类似的事件驱动结构
* 本地化BREW小程序非常方便
* 所有文本按Unicode 处理,并以所选语言可支持的最有效的方式储存。BREW 还支持OEM的本地文本格式
* 业务模块可以在对象代码级集成,便于设备开发商和第三方生产商为BREW 平台添加应用模块
* BREW提供了内核类可与设备平台进行对接
在应用开发上,BREW为各种手持设备快速、高效、经济地开发和配置新的应用程序提供了方便,BREW SDK开发包提供基于C/C++、Java等编译环境的运行库和面向对象的类结构,包含了各种有效的系统调用、用户接口、多媒体集成和网络套接字等类对象资源,开发者对BREW的开发就好像在Windows平台上编程,有种类繁多、功能强大的库函数调用一样,开发者不必关心低级平台数据结构和设备驱动程序,因为应用程序和设备平台可以完全通过适当定义的类对象进行交互。而且,它还支持在程序中直接使用字符串、图片、声间、对话框等自定义资源,从而达到交互、生动的效果。目前,BREW应用主要集中在移动文本通信(电子邮件、SMS)、信息服务(新闻、天气、影视、搜索等)、定制服务(个性化代理、时尚)、位置服务(M2M、定位导航)、多媒体娱乐(数据流视频、互联网音频)和游戏(离线、在线)等方面。
业务模块开发流程
BREW开发增值业务是以模块为单位,每一模块可能含一个或多个小程序(Applet),模块的调用(以Windows平台为例,以下同)是从module_main入口开始,提供以Windows动态库类型的小程序为运行单位。业务模块的开发可以独立和同时开发,从而最大限度地缩短开发时间,回避复杂的集成问题。
BREW 中的每个类或小程序必须拥有一个唯一的ClassID,在BREW SDK中,提供了ClassID编程器---生成后缀为MIF的文件,它包含支持的类、支持的小程序以及小程序标题。启动时,BREW 会在设备屏幕上列举MIF文件,并保存从MIF 列举收集来的信息,以便在请求类时使用。
创建实例
BREW 用于支持小程序和模块创建的机制是ISHELL_CreateInstance 方法。该机制是BREW 模型的核心,也是BREW 支持的最强大的API 之一。调用该方法时BREW 将在支持的类列表中搜索指定的32 位已注册的ClassID。该列表包含内核BREW API支持的条目,另外还包含添加到系统的所有类和小程序,系统启动时会通过MIF 列举进行检测。
类通过BREW 模块支持的IMODULE_CreateInstance方法来创建。BREW 将根据需要加载模块,加载后BREW 将使用其IModule 实例创建请求的类。一个模块的所有对象在创建时必须增加其IModule 的引用计数,而在释放时减少IModule 的引用计数。模块在该模块IModule 类的引用计数变为零之前,模块会保持加载的状态,一旦引用变为零,BREW 将自动释放与该模块相关的所有内存。这种方法的象Windows编程中使用COM 对象一样;创建实例的过程基本上是统一的,程序员一般必干预此过程,这样有利于开发和运行的效率。
创建和中止小程序
在BREW 模型下,小程序是支持IApplet 接口方法的类。这样BREW 便可以使用相同的简单接口管理所有的小程序。
BREW 在两种情况下创建小程序:
* 应ISHELL_StartApplet 方法的要求创建小程序。该方法可以创建小程序,小程序生成以后,将立即发送EVT_APP_START 事件,通知小程序已处于激活的状态并可以调用其它用户接口类如绘制屏幕、弹出对话框等
* 为处理已注册的通知、警报等创建小程序,小程序生成后会立即收到特定的通知事件
中止小程序通过由BREW系统自动调用Release方法完成,只要在Release方法中加入释放自定义的内存和资源即可。
处理小程序事件
事件处理是BREW编程中最重要的过程,来自无线网络、BREW系统、OEM驱动程序、用户接口输入的所有事件将通过ISHELL_SendEvent 方法发送给小程序,事件的发送可以同步,也可以异步进行。一般情况,发送给小程序的事件包括键区、对话和控件更改事件。
通常,小程序仅需处理少数事件,这些事件可以是EVT_APP_START、EVT_APP_STOP、EVT_KEY和 EVT_COMMAND。如果小程序不处理事件,其HandleEvent方法必须返回FALSE。这样可以使BREW对该事件进行任何必要的特殊处理。
通过对事件的响应,小程序将自动调用对应的方法如绘制屏幕、显示图片、播放MP3、弹出对话框等。通常的处理方法中包含了以下可供调用的类对象:外壳服务、时间/计时器、通知、内存管理、文件管理、数据库管理、网络和套接字、HTTP、下载和结算、显示、图像(显示、转换、动画)、图形、声音播放器(播放MIDI 和MP3 文件)、声音(产生铃声警告声和播放音频文件)、标准帮助功能库和用户控件如对话框、日期控件、菜单控件、文本编辑控件、时间控件、静态文本控件。
测试
BREW SDK提供了一个电话模拟器,供程序开发人员设计、定制用户界面,配置新设备和测试应用软件,并可以动态监视业务程序的内存使用。它基本上可以模拟真实环境的测试状态和效果。
结束语
综上所述,不管是对于应用软件开发商、设备制造商、移动运营商还是最终用户,BREW平台所提供的功能和应用都是远远超出了传统的增值服务所带来的效应。
韩国KTF于2001年11月开始提供基于BREW平台的商用服务,统计数字表明,市场反响相当强烈,无论是业务内容还是业务质量,在用户眼中的吸引力都不断增强,赢利潜力非常可观。就中国联通而言,一旦全方位地发展中国CDMA的产业布局,其垄断的增值业务客户网络,将对现有GSM或 GPRS网络造成巨大的冲击。
查看全文
帮你找回误删的文件
我在删除文件的时候有一个习惯,就是按Shift+Delete直接将其删除,总觉得这样可以省去清空回收站的麻烦,但是不久前我一个不小心把某个文件夹中的所有有用文件彻底删除了,发现时真是追悔莫及。怎么办?经过多方求助,终于找到两个软件EasyRecovery6.0中文版和FinalData
OEM版。这两个软件通过搜索引擎查找即可发现有许多网站都提供下载。
使用方法
在具体应用时,FinalData和EasyRecovery使用起来都很直观,特别是EasyRecovery6.0在使用时都有相关的提示与说明。而且在网站上关于这两个软件使用方法的介绍也非常多,FinalData,在http://news.onlinedown.net/info/13071.htm上有一篇文章介绍得很详细,我就是照文章说的去操作的,在此我只简单介绍一下我是如何使用EasyRecovery6.0中文版的。
1、启动EasyRecovery进入主界面后,选择数据修复项会出现如图的界面(见图1)。

2、在右侧选择任何一种数据修复方式都会出现相应的用法提示,如我使用DeletedRecovery项来查找并恢复已删除的文件时,就会在界面右侧出现相应的使用提示(见图2)。

3、选择你想要恢复的文件所在驱动器进行扫描,也可以在文件过滤器下直接输入文件名或通配符来快速找到某个或某类文件。如果要对分区执行更彻底的扫描可以勾选“完全扫描”选项。
4、扫描之后,你曾经删除的文件及文件夹会全部呈现出来,现在需要的就是耐心地寻找、勾选,因为文件夹的名称和文件的位置会发生一些变化,好在文件名没怎么变(如图3)。

5、如果不能确认文件是否是想要恢复的,可以通过查看文件命令来查看文件内容(见图4)。

6、选择好要恢复的文件后,它会提示你选择一个用以保存恢复文件的逻辑驱动器,此时应存在其它分区上。所以最好准备一个大容量的移动硬盘,这一点在误格式化某个分区时尤为重要(图5)。

7、点击下一步进行扫描后,会出现恢复摘要,你可以打印出来也可以保存为文件(如图6)。

8、当恢复完成后要退出时,它会跳出保存恢复状态的对话框,如果进行保存,则可以在下次运行EasyRecovery时通过执行ResumeEasyrecovery命令继续以前的恢复。这一点在没有进行全部恢复工作时非常有用(如图7)。

注意事项
通过这次教训,我对提高恢复误删文件的成功率也很有感受。
首先,提高恢复误删文件的成功率的关键是:一定不要往原来存放该文件的分区写入新数据。大家都知道,在Windows中,虽然把文件彻底删除了,但其实文件在磁盘上并没有消失,只是在原来存储文件的地方作了可以写入文件的标记,所以如果在删除文件后又写入新数据,则有可能占用原来文件的位置而影响恢复的成功率。
其次,不要高兴得太早。当看到丢失的文件名又一次出现在眼前时真是异常兴奋,但是,当你打开有些文件时才知道其实都是乱码,特别是文档资料,明明查看文件大小不是0,而且文件名完好,以为文件可以完全恢复,谁知再打开看却是一堆乱码,真是欲哭无泪。所以我要提醒大家一定要将恢复的文件一一验明正身才可进行恢复操作,否则再想重新做一次恢复就难了。
另外,一定不要在目标分区执行新的任务。这一点从概念上容易理解,但实际要做到却不是那么容易的。因为Windows会在各个分区多多少少生成一些临时文件,加上还有在启动时自动扫描分区的功能,如果设置不当或操作上稍不留意,可能已经写入了新文件你自己都不知道。所以在确认文件完全恢复成功前不要对计算机作不必要的操作(包括重新启动),
特别是当你发现误删除了文件而必须安装恢复软件时,一定不要把恢复软件安装在恢复文件所在分区。例如你要恢复的是C盘中被误删的数据,而安装软件时默认路径也是C盘,此时你若一路回车安装的话,可能就要追悔莫及了。这一点FinalData考虑得就比较周到,在选择了安装路径后会跳出个对话框提醒你注意安装路径。
以上是我使用EasyRecovery和FinalData两款恢复软件的心得,在这次拯救过程中,因为不放心一款软件的恢复效果,我将这两款软件全都用上了,通过比较我发现两款软件在恢复文件上各有优势:EasyRecovery在恢复误格式化、误删除的文档特别是Excel文件时效果很好,而FinalData在恢复图片文件和Zip文件时效果较好。
虽然通过恢复解决了一些问题,但解决问题总不如不出问题,最可靠的办法是养成良好的习惯,定时备份你的宝贵文件,以免到时吃后悔药。
Getting Started with the BREW™ SDK
Getting Started with the BREW™
SDK
By Murray
Bonner
If you wish to perform the steps outlined in this article, you require the
following items: To view the minimum system requirements and obtain specific, SDK installation
instructions, view the SDK 1.1 readme file. Note that I assume you have read What is BREW?, the previous article in this
series. Throughout this example, you need to know that file naming is important.
Specifically, the application's module information file (.mif) must have the
same name (i.e. prefix) as its .dll. In essense, with BREW you need to pick a
name and stick with it! The significance of the .mif file suffix will become
apparent as you read through this article. The next article will delve deeply
into the creation of the .dll that runs on the BREW Emulator™. Version 1.1 of the SDK includes a BREW Application Wizard™ that is not
available in the version 1.0 release. This application wizard sets most of the
applicable project options and produces the minimal skeleton code for a BREW
Application, assuming you intend to do your development in C. The project
settings and starter code are SDK 1.0 compliant. In the US, there are currently
4 BREW phones available: 2 equipped with version 1.0 of the BREW Application
Execution Environment (AEE) and 2 with version 1.1. To ensure compatibility with
all these phones, and those yet to be released, you will likely want to use
version 1.0 of the SDK for development projects that you intend to
commercialize. Should you decide on this course of action, you can use SDK 1.1
to generate your base project, then copy your application-specific files to a
safe place, uninstall version 1.1 and download and install version 1.0 of the
SDK for the remainder of your development. In this way, you can ensure that your
application is version 1.0 compliant and therefore capable of running on current
and future phones. Once you have installed the SDK, open Visual C++ and click File
> New. The New dialog should open with the Projects
tab selected. As shown in Figure 1, select BREW Application Wizard,
ensure that the path to yourBREWdirExamples is entered in the
Location textbox, then enter "helloBREW" as the Project Name.
Click OK to start the BREW Application Wizard. This should bring up the dialog
pictured in Figure 2. For the simple application currently under construction,
We don't need support for any of the items identified in this dialog. Thus, we
can leave all of the checkboxes blank. Had we needed support for any of these
items, it is important to realize that merely selecting the corresponding
checkboxes in this dialog may not be sufficient. All that these checkboxes do is
ensure that the proper interface header files are included in the source file
generated by the wizard. The application must have the corresponding privilege
level specified on the General tab of the BREW MIF Editor™. The MIF
Editor is discussed below and a screenshot of its default view is given in
Figure 4. We'll discuss these privilege levels in detail when we cover the
related interfaces in later articles. For now, click Next to proceed to
the next step in the Application Wizard. In step 2 of the wizard, a note reminds us that we need to create a
Module Information File (.mif) for our BREW application. Click the
button provided by the wizard to start the BREW MIF Editor. On the Applets tab of the MIF Editor's main dialog, click the
New Applet button to bring up the ClassID Generation dialog
shown in Figure 3 (the terms applet and
application are used interchangeably throughout this article).
Note that the class ID must be unique. A quick perusal of the header files
"AEEClassIDs.h", "AEEUsageAppIDs.h", and "AEESampleAppIDs.h" in the
yourBREWdirinc directory shows that 0x1234ABCD does not conflict
with any of the IDs included with the SDK. For a commercial application, we
would need to obtain a globally unique ID from the BREW Developer
Extranet™. For now, select Locally and type 1234ABCD, or any other
non-conflicting ID, in the ClassID textbox. Click the Generate
button and click Yes in response to the Are you sure you want to
generate a ClassID locally? prompt. In response to the Generate command, the MIF Editor creates a BREW
ID (.bid) file. This file simply contains a #define for the class ID generated
locally within the MIF Editor. In the next article, we'll ensure that
"helloBREW.bid" is #included in the "helloBREW.c" source file. Figure 4 shows
the Applets tab of the BREW MIF Editor. Except for the fact that we
have not yet supplied a file for the Icon, your MIF Editor instance
should appear as in Figure 4. Leave the MIF Editor open; we'll come back to it
shortly. Three bitmaps need to be included in the .mif file: one approximately 85 x 40
pixels, one 26 x 26 pixels, and a thumbnail image 16 x 16 pixels. You can create
these bitmaps (.bmp) at any time using Microsoft Paint™ or the resource editor
within Visual Studio®. Figure 5 shows the 85x40 pixel image I created using the
latter tool. Obviously, you can use whatever images you please. Once you've finished the 3 bitmaps, save them and return to the MIF Editor
where you can specify your 26x26 pixel image as the Icon. Next, click
the Advanced button on the MIF Editor's Applets tab. The
dialog displayed provides spaces to specify an Image and a
Thumbnail Image. The Image is your 85x40 pixel bitmap and the
Thumbnail Image is your 16x16 pixel bitmap. This example is intended
for the Sharp Z800 phone which has a 128x144 pixel display and a maximum
Image size of 108x72 pixels. Note that this maximum size applies only
in this MIF Editor context. The dimensions of images based on the SDK's IImage
interface are governed only by the device's physical screen size. Be aware that
screen size and maximum Image dimensions vary from phone to phone.
Detailed phone specifications are available to authenticated BREW developers via
the BREW extranet. To gain an understanding of what is required to become an
authenticated BREW developer, see the Qualcomm® BREW website. As an aside, you can create large images that end up displaying as animations
on both the emulator and the phone. In this MIF Editor context, this is
accomplished by simply creating a single bitmap consisting of several,
horizontally arranged, identically-sized frames. Thus the total width of the
bitmap can be greater than the device's display width, with the understanding
that only one frame of the animation will be displayed at any given time. Note
that, in order for this to work, the bitmap's width must be an exact multiple of
its height. Now that we've created a basic module information file, we can close the MIF
Editor and continue our exploration. Remember that it is essential for the .mif
to have the same name (prefix) as the application's .dll. Note that the
"helloBREW.mif" file just created must be copied to the
...yourBREWdirExamplesMIF256Color directory in order for the AEE
to find it and properly initialize the helloBREW application. This will become
especially important next time, when we add our own source code to that
generated by the BREW AppWizard and get the application running on the BREW
Emulator™. Most applications require string and image resouces, not to mention some kind
of user interface consisting of various screens. The BREW Applet Resource (.bar)
file serves as your application's central repository for such items. Later in
this series, we will work with image and user interface resources. For this
introductory application, all we need is a simple resource file that contains
two strings that we'll load and display at runtime. Start the Resource Editor by
clicking the shortcut installed in your BREW program group. Figure 6 shows how
the resource editor looks after the 2 strings have been entered. Initially the
right pane of this dialog is empty. To familiarize yourself with all the ins and outs of the resource editor,
read the corresponding guide included with the SDK documentation. For now, right
click in the left pane and select New String..., or simply use the
keyboard shortcut, ALT-S. The dialog shown in Figure 7 is displayed. Use Figure
6 to fill in the contents of this dialog box for each of the required strings.
Once the strings have been entered save the BREW Resource Intermediate (.bri)
file as "helloBREW.bri" by selecting File > Save or clicking on the
diskette icon on the tool bar. Note that you open the .bri file in the resource
editor to make any changes. Whenever you create or edit an application's
resources, you must click the blue 'Q' icon on the tool bar after you are done.
Doing so creates two files: "helloBREW.bar" and "helloBREW_res.h". You must copy the "helloBREW_res.h" file to the
...yourBREWdirexampleshelloBREW directory and #include it in
"helloBREW.c". The "helloBREW.bar" file needs to be copied to the
...yourBREWdirExamplesen256Color directory. As it runs on the
emulator, the helloBREW application will access the string resources from
"helloBREW.bar" on an "as required" basis. On a phone, at least in most
non-trivial cases, an application will never need simultaneous access to all of
its resources. Thus bulky strings, images, and UI elements can be relegated to
the the phone's embedded file system (EFS) instead of consuming precious RAM.
Additionally, the resource file concept eases the process of application
internationalization. In this article, three important BREW SDK tools have been introduced: the
BREW Application Wizard, the BREW MIF Editor, and the BREW Resource Editor. The
BREW Application Wizard created a skeletal BREW project that can be used as a
baseline for our BREW application. The BREW MIF Editor created a module
information file (.mif) that contains essential information such as our
application's unique class ID, its category, and the images associated with each
of the 3 icons required by most applications. The BREW Resource Editor was used
to create our application's resources. These resources were then compiled into a
BREW Applet Resource (.bar) file that serves up resources whenever the
application requests them. Next time, we will disect the "helloBREW.c" source
file as generated by the application wizard, add our own code to flesh out the
application's simple functionality, and run the application using the BREW
Emulator™. Also, we'll see how to debug a BREW application using the Visual C++
debugger and the BREW Emulator. © Copyright 2002, Golden Creek Software Inc.Part I - Preliminaries
BREW Application Wizard


The MIF Editor



The Resource Editor


Conclusion
Linux桌面激情之旅—JDS
如今,Linux的发展壮大让众多想要进占桌面市场的厂商看到了希望,于是众多业界巨头都纷纷行动起来。鉴于中国广大的市场潜力, Sun与Linux软件厂商──中标软件公司合作,将以Sun的桌面型套件Java Desktop System(JDS)为平台开发桌面Linux应用。 那么JDS到底为何物,它真的能够担起振兴桌面Linux的重任吗?
很显然,到目前为止,企业市场是Linux桌面套件最有潜力的用户。相比较而言,家庭及个人用户有太多媒体影音处理及娱乐方面的需求. 这部分功能就目前而言,Windows做得还是比较成功的。但是作为商业用户,一般只需要Office、电子邮件、日程管理及浏览器就可以了。对企业而 言,Linux最大的好处在于价格便宜、安全性高、稳定性好。特别是上一次蠕虫大暴发的时候,很多企业用户都遭受了重大打击,由此对企业桌面系统的安全性 更加看重。当时,我们部门里的所有Windows机器无一幸免,很多用户更是在不知情的情况下丢失了大量有用的数据。
最近我安装了JDS,使用一段时间后有一些感想,写下来与大家分享。在介绍之前,先来看一下我机器的硬件配置情况:CPU为赛扬566,内存320MB,主板是Intel i810,显卡为板卡合一。
系统的安装
JDS的安装盘共有3张(对于一个桌面系统而言是不是太多了),从光盘启动系统进行安装以后,我的第一感觉是它简直与SuSE太像了(显然JDS是在SuSE上进行再开发的结果),如果不是界面右上角的Sun图标提醒我,我还以为使用的就是SuSE 9.0(见图1)。
图1 与SuSE非常类似的安装界面
随着安装的继续,我感觉有所不同。安装程序会让用户选择所安装的StarOffice办公套件,我们可以选择是适用于东亚语言的套件,还 是世界所有国家语言的套件(如图2)。我选择的当然是前者。接下来,安装程序会对系统进行自动检测,然后为用户定义一个默认的配置,如果要更改配置,则可 以直接点击相应的项目。这一步骤在SuSE 9.0中是有的,不过在JDS的安装过程中,实际上这一步骤中我们并没有什么可选的余地。以软件为例,整个过程中可以选择的只有安装东亚版本的 StarOffice,还是世界版本的StarOffice。
图2 选择所要安装的办公套件
就安装过程而言,与其它的Linux发行版乃至Windows相比,我认为JDS的优点是安装非常简单。整个过程中除了选择语言之外,用户可以不做任何选择,只是点击接受即可完成安装。此外,整个安装过程非常直观,界面结构非常合理。这主要是秉承了SuSE的特点。
JDS主要缺点是可定制性(或者说是灵活性)比较差,当然这也是可以理解的,因为可定制性与易用性本身就是矛盾的。应该说,JDS还是在 二者之间找到了一个比较好的平衡点。此外就是拷贝、安装软件包的速度奇慢(有一次,我都以为死机了,因为安装过程和机器半天没有动静),如果说可定制性差 是为了提升易用性的话,安装软件包的速度慢就没有什么合理的解释了。整个安装过程用了大约3个半小时。我考虑到所使用的机器比较旧,又在一台CPU为P4 2.4GHz、光驱为8倍速DVD的新机器上进行了安装,结果速度还是非常慢,花费了约3个小时的时间。总体而言,与SuSE 9.0相比,JDS的安装过程要多花差不多一倍的时间。
桌面外观
与安装过程相比,JDS的启动过程要快得多,我想这是因为它没有启动大量服务器软件的缘故。启动进入桌面以后,刚才等待系统安装时的烦燥 和怨气顿时烟消云散。整个桌面看起来非常清爽,界面使用的是Sun最常使用的蓝紫色调,给人一种非常踏实的感觉。桌面右下角是一个通过几个简单线条组合而 成的一个Java标识:一杯冒着热气的咖啡(如图3)。就桌面外观而言,我觉得这是我见过最好的桌面之一,无论布局还是颜色搭配,整体感觉是沉稳中透着几 分灵气。
图3 漂亮的桌面
JDS使用的桌面环境是GNOME 2.2,不过这是一个被Sun重新设计过的桌面。缺省情况下,桌面上只有“This Computer”、“文档”、“网上邻居”、“废纸篓”和“帮助”5个图标。这几个图标很容易就可以让人将其与Windows下的“我的电脑”、“我的 文档”、“回收站”等图标联系在一起,事实上,它们实现的功能也是基本相同的。此外,面板切换工具也被放到了最右边,主选单无论是在外观上,还是在选单项 上都与Windows XP非常类似。从整个桌面的环境来看,我们可以看出Sun的良苦用心是希望能够让Windows用户快速适应JDS环境。从我个人感觉来看,我觉得Sun 还是基本上做到了这一点。
中文字体
作为办公的桌面系统,中文的显示和中文字体的数量是一个非常重要的指标。SuSE 9.0的中文化问题就受到了很多用户的批评,而Red Hat 9.0虽然中文显示不错(缺省情况下使用的是Sans字体),不过其所附带的中文字体却少得可怜。
JDS操作系统中,使用的默认字体是Windows中的sans,中文字体的显示效果已经非常完美。此外,它还附带了仿宋体、黑体、楷体 等一些常用的中文字体(如图4),并且这些字体在StartSuite 7.0中也可以使用。当然,与Windows下相比,这些字体的数量还是不够丰富,但在Linux系统中,这已经难得可贵了。
图4 丰富字体和漂亮的中文显示
办公软件
JDS中使用的办公软件是StarOffice Suite 7.0,开放源码版本的OpenOffice正是源自于该套件。这套久负盛名的办公软件表现果然不同凡响,虽然整个界面与OpenOffice并无太大的 差别,不过使用起来感觉更加流畅,各个办公组件与微软Office的兼容性也非常令人满意。图5、6、7是我使用StarOffice Suite中的字处理、电子表格、演示应用程序,打开MS Office中相应的应用程序制作文档的情形。因为JDS本身带了很多中文字体,感觉使用StarOffice制作文档也非常顺手。
很显然,既然说JDS主要是针对企业办公市场的,那么办公软件自然也就是重中之重。凭借Sun在StarOffice上的多年经营,应 该说其在自己的Linux平台上使用了这样一个优秀的办公软件,一下就增色不少,并且在众多欲进军企业桌面市场的Linux厂商中显得特别引人注目。
图5 文字处理软件
图6 电子表格软件
图7 幻灯制作软件
1.浏览器
与其它众多Linux发行版一样,JDS使用的浏览器也是Mozilla,版本号是1.4。在Red Hat 9.0中,使用的Mozilla是1.2版本。Mozilla 1.2最大的问题就是没有安装Java Virtual Machine、ShockWave和RealPlayer插件程序,这使得我们在浏览一些网站时,会出现一些无法显示的方框(比如上 www.sohu.com时这个问题就比较严重)。当然用户可以通过手工下载,并且安装相应的插件来解决这些问题,但毕竟还是比较麻烦,并且安装过程也不 是十分顺利。而JDS中的这个Mozilla,不仅外观非常简洁、美观,而且所有的插件都已经安装完毕,在浏览一些需要各种插件的站点时,显示没有任何瑕 疵,感觉非常好(如图8)。很显然,Sun对这个浏览器进行了大量的优化工作。
图8 JDS中的浏览器
2.电子邮件
不管在什么Linux发行版中,Evolution都以自己优越的表现成为了广大用户的首选。JDS的电子邮件客户端使用的也是 Evolution,版本是1.4.5。从我使用的感觉来看,这个经过Sun修改后的Evolution,外观上几乎与微软的Outlook Express一模一样(如图9)。在功能上它增加了只有在Outlook中才有的日历功能,并把它放置在了左边列表框的列表中,使用起来非常方便。
图9 Evolution中的日历功能
总的来说,JDS中的这个邮件客户终端是一个介于微软的Outlook和Outlook Express的产品,其界面是大家所熟悉的Outook Express的界面,但其功能中又包含有Outlook中的部分功能。
3.内容共享
在我所使用过的Linux发行版中(包括Red Hat 9.0、SuSE 9.0和Mandrake 9.1),在网络的内容共享方面,做得都不尽如人意。我在此所说的尽如人意就是希望在内容共享方面,Linux发行版能够达到或接近Windows中的 “网上邻居”的水平。Linux各发行版在实现内容共享时无一例外地要求用户对Samba要有一定的了解,而JDS在这方面有了很大的进步。在JDS系统 安装完成之后,会在桌面上放置一个“网上邻居”的图标。通过双击该图标,然后再点击进入“Windows网络”我们就可以浏览整个局域网内的所有共享资源 了(如图10)。
图10 使用JDS中“网上邻居”浏览局域网内资源
不过在使用过程中,我发现这个功能还是有一些不完善的地方。比如,我尝试以图形化的方式共享Linux系统中的某一目录,但始终没有成 功,这不能不说是一个缺憾。此外,在一段时间的使用中,我碰上了多次“网上邻居”程序崩溃的情况。也许以后JDS会对这些问题做出改进。不管怎么说,在内 容共享方面,JDS还是有了很大的进步,至少我们已经可以很轻易地来查看Windows中的共享内容了。
多媒体应用
现在的桌面应用中,多媒体应用是一项非常重要的内容。而在多媒体的应用中,图像的浏览和编辑、媒体文件的播放又是使用最为普遍的功能。
1.图像浏览和编辑
JDS使用的是GNOME桌面环境,而GNOME的Nautilus文件管理器本身就内置了图像浏览的功能。将Nautilus的“查看 方式”更改为“视图图标”,该文件管理器就会在文件夹内显示图像的缩略图;双击相应的文件,就可以以正常的大小来查看该图像。此外,JDS还附带了 GNOME图像查看器,不过我个人认为这个程序还不如Nautilus好用。
JDS附带的图像编辑软件是GIMP 1.3版,非常好用。说实在的,使用了GIMP之后,我都有点开始担心Photoshop的前途了(如图11)。
图11 图像编辑
2.媒体播放
在媒体播放方面,JDS自带有CD播放器、Media Play、录音机和影碟播放器,各个播放器使用起来感觉还不错,见图12。尤其是CD播放器,当把音乐碟插入光驱时,它就会自动进行播放。在媒体播放方面 JDS有一个最大的不足,就是无法播放MP3文件。我不知道这一功能是不支持还是被隐藏了,反正我是没有找到。也许和Red Hat一样,Sun也顾忌到了MP3存在的一些许可方面的问题,故而没有提供这一功能。当然,不管是什么发行版,我们都可以自己安装一些相应的软件,来播 放MP3文件。但作为一个商业的桌面操作系统,如果还要让用户来完成这一功能,显然是非常不合理的。
图12 JDS中的媒体播放器
3.光盘刻录
作为办公人员,经常对所保存的文档进行备份也是一项重要的工作。从我的使用来看,JDS的表现可以说非常让人激动。要在其中刻录光盘,只 需打开Nautilus,然后在“转到”选单中选择“CD生成器”,这里在Nautilus的“位置标识符”就会显示为“burn:///”,把所要刻录 的文件和文件夹拖到这个位置,然后点击快捷选单栏上的“写入CD”,或者从文件选单选择“写入CD”即可进行刻录。应该说这一功能已经简单到了极至,惟一 遗憾的是除此之外,JDS并没有提供其它更专业的选择(比如Xcdroast软件)。
4.系统管理
JDS的系统配置工具做得非常不错,我们可以从一个统一的入口对其进行配置。从桌面上的“This Computer”,再点击“首选项”,然后再进入相应的配置模块进行配置。这里的“首选项”实际上就相当于Windows系统中的控制面板,并且进入这 一界面的方法也比较类似。从这个位置开始,可以对系统里几乎所有的方面进行配置(如图13)。
图13 系统配置
当然,如果有人喜欢使用YaST2的话,也可以通过在命令行中输入yast2来启动该配置工具。JDS保留了这个SuSE引以为豪的配置工具,只不过删除了其中一些配置选项。
5.帮助系统
一个应用软件或一个操作系统的好坏,其所提供的帮助系统是一个非常重要的指标。JDS中的帮助系统是我所使用过的Linux中做得最好 的。不仅是因为它将绝大部分的内容翻译成了中文,而且是将这些帮助材料进行了很好的组织,使我们可以在一个统一、直观的界面中进行查看,并且在需要时可以 快速地找到相应的帮助内容。
小结
总体而言,JDS虽然也有一些缺憾,但我认为它是我到目前为止使用过最好的Linux桌面。Sun几乎对常用的所有应用程序都进行了优化和改进,使其看起来和整个桌面环境结合更加紧密,也更加符合广大电脑用户的使用习惯。
当然,我这里的评价都是基于企业桌面应用而言。因为很显然,对于个人电脑用户而言,我所使用的这个JDS版本有很多方面都不能满足需求 (无论是应用程序的数量,还是可以实现的功能方面)。JDS之所以有非常不错的表现,我个人认为在很大程度上是因为它继承了SuSE的很多优点,而同时又 在一些方面进行了改进。
根据Gartner的报告,2005年Linux在桌面市场占有率将达到10%(这已经是一个比较乐观的预测)。而对于Linux桌面这个潜在的市场,除Sun以外,还有很多巨头摩拳擦掌,跃跃一试。
从我的使用来看,除了StarOffice以外,JDS系统还是具有了太多SuSE的特征。因此,一旦SuSE也针对中国市场的桌面用户 进行更好的优化以后,JDS的吸引力将会大打折扣。毕竟,产品的差异化才是致胜的法宝,同质化的竞争只会把参与各方拖入到价格战的泥潭。当然,需要注意的 是,Sun本身在硬件、软件、服务、系统集成等方面的强大实力,将对其Linux桌面战略产生非常积极的影响。
下面是我对整个系统印象打的一个分,仅供参考。
安装过程(80分):整个安装过程的易用性非常好,只可惜安装耗时太久,此外过于追求易用性也使得其可定制性受到了影响。
易用性(95分):除了内容共享方面需要改进之外,其它的方面做得已经非常不错。
功能(95分):对于企业用户而言,其所实现的功能实际上已经比较完善。
总体得分(90分):我认为它已经可以满足企业应用的需求,并且在安全性、TCO等方面具有得天独厚的优势。
中国Linux论坛《linux入门版》FAQ
希望朋友们看到有关linux入门方面比较不错的文章请跟以下这个贴子:
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=158189
这里已有"无涯子=muyu"老版主提供的一篇入门级的文章 http://www.yesky.com/20010829/194313.shtml
二、linux常见问题解答
1.什么是LINUX?
LINUX是一个可独立运作的POSIX兼容操作系统,它也包含了SYS V和BSD的功能。
它完全是独之发展的,所以其中没有任何有版权问题的代码。LINUX可以在符合GNU
Public License的情况下自由传播。它的核心是由芬兰人Linus Torvalds
(torvalds@kruuna.helsinki.fi)所写。
2.LINUX的版本
Linux的版本号分成两部分:内核和发行套件版本。很多人常常把内核的版本号
和发行套件版本号弄混了,实际上内核的版本号是Linus领导下的开发小组开发的内核
的版本号。(通常,内核版本序号是偶数表示是稳定的版本,奇数序号是不稳定的测试版本)
3.LINUX的标准发音
ftp:/Linux.cis.nctu.edu.tw/pub/kernel/SillySound/english.au,这是Linux
本人的Linux发音的声音文件,应该是最权威的。
4.怎样自己制作boot disk
rdev /vmlinuz /dev/hda1 (其中/dev/hda1 是系统根挂接点的分区)
dd if=vmlinuz of=/dev/fd0
5.LILO出错信息意义
没有信息 ======> LILO没有安装或者安装LILO的分区没有被激活
LI ======> LILO第一部分被加载,第二部分出错。一般由于LILO定位错误
或者使用了错误的boot.b文件。
LIL ======> LILO第二部分开始加载,但是没有从map文件中成功读取descriptor tables。
LIL? ======> LILO第二部分在错误的地方加载,原因同"LI"。
LIL- ======> descriptor table 错误,或者是改变了boot.B文件却没有重新安装LILO。
LILO ======> LILO的所有部分都安装完毕。
10101010 ======> 如果用户的分区情况改变却没有重新安装LILO,LILO开机时就会出现1010现象。
这时用软盘开机重新运行LILO就可以修复,用户超频的时候也有可能出现这种情况。
6.如何反安装LILO
用DOS启动,执行FDISK /MBR就可以重写主引导记录,覆盖LILO。
or 在Linux下执行 lilo -u /dev/hda (其中/dev/hda 是lilo安装的位置)
7.如何在LINUX下看WIN95长文件名
确定核心支持VFAT文件系统,然后改/etc/fstab中的选项,
例如:mount -t vfat /dev/hda1 /dos这样就可以看win95长文件名了。
8.显示彩色目录及文件列表
用ls --color -F,--color指示用彩色显示,-F会在文件/目录名后加一个字符来指示它的类别。
建议初学者用man ls看看ls的详细使用信息。
比如 -l 列出文件/目录的绝大部分信息(长格式显示);
-a 列出所有文件;包括首字符为"."的隐含文件;
-N 不处理文件名直接显示,这样在中文环境下就可以显示中文文件名了。
还要注意ls与其它命令搭配使用可以生出很多技巧(最简单的如"ls -l | more")。
为了方便起见,你可以编辑/etc/bashrc或自己家目录(home)下的.bashrc,加入一行:
alias ls="ls --color -F -N" 重新运行一下bash会立即生效,
如果加在/etc/bashrc里则对所有使用bash shell的用户有效。
如果使用的是其它的shell,则去找对应的配置文件。注意不是/etc/aliases文件,
那是sendmail 的别名配置文件。
ls显示的颜色是可以修改的,请参考"Colours with Linux terminals",里面有个shell
脚本可以显示所有的ANSI颜色。你可以去看一下/etc/DIR_COLORS或$HOME/.dir_colors,
要注意两个文件的作用范围不同。
9.复制子目录及子目录下的所有文件
在用cp时加上-r参数,如"cp -r /mnt/floppy/* /usr/local/"要参考的重要参数是-f -s。
10.文件/目录改名
简单地用move命令移到新名字下即可。例如"mv /usr/oldname /usr/newname"。
11.怎样删除一个目录下的所有文件和子目录及子目录下的所有文件
rm -rf /tmp/example
12.怎样显示文件的类型
用file命令,比如"file /bin/mount","file xxx.gz","file netscape","file initrd.img"等等。
相关的配置文件在/etc/magic或者 /usr/share/magic
13.查找命令文件的路径
比如你要查找mount命令的具体路径,可以用type mount 、whereis mount,
这个命令还可以找出与这个命令文件相关的文件如manuals page。
14.查找文件
使用find命令,比如:
find /usr -name XF86* 在/usr目录下(包含子目录)查找名字前四个字母为XF86的文件
find . -name netscape -print 在当前目录下(包含子目录)查找名为netscape的文件
find /home -nouser 在/home目录下查找没有用户属主的文件(用户帐号被删除但有遗留文件)
find /var -newer test 在/var目录下查找比test文件日期更新的文件
find命令有很多参数,注意用man命令查看。
更快速的查找文件是使用locate,第一次使用locate之前用updatedb来更新文件/目录名数据库。
它把文件/目录信息写到数据库中,以后查找起来就特别的快。updatedb放在crontab中而且缺省
配置是在半夜自动执行。locate存在轻微的安全性问题,因为普通用户可以用它来取得自己不
能访问的目录/文件的部分信息。
15.快速调出历史命令
可以用上下光标键来调出历史命令,然后用左右光标键移动并可编辑命令行。
详细情况请见下面贴子(有其它想法可跟其贴!)
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=155520
16.关于rpm的小技巧
1)安装rpm包时显示进度:用-vh参数,如rpm -ivh ipchains-1.3.6-1.i386.rpm,用glint或xrpm则不必。
2)直接通过ftp来安装rpm包:如rpm -i ftp://ftp.xxx.xxx
3)校验所有的rpm包,查找丢失的文件:rpm -Va
4)查找一个文件属于哪个rpm包:例如:rpm -qf /usr/bin/who
5)列出一个rpm包的描述信息:例如:rpm -qpi mon-0.37j-1.i386.rpm
6)列出一个rpm包的文件信息:例如:rpm -qpl mon-0.37j-1.i386.rpm
17.使用软盘/光盘等移动介质
因为Linux下没有A盘D盘的概念。你需要把软盘/光盘设备上的文件系统安装到
Linux目录树上的一个点上,称之为安装点(mount point),通常是一个目录。
安装Linux后会有个缺省的安装点/mnt,在它下面还有/mnt/floppy和/mnt/cdrom。
你可以用mount -t ext2 /dev/fd0 /mnt/floppy <--把Linux文件系统格式的软盘安装上来
单用mount而不跟任何参数可以显示已经安装的文件系统,或者查看/etc/mtab文件.
初学者还经常问到如何格式化磁盘,在Linux里概念有些不同, 称之为制作文件系统
(make filesystem)应该用mkfs命令,由于现在的Linux都使用ext2格式,最好直接使用
mke2fs,比如mke2fs /dev/fd0、 mke2fs /dev/hdb2等等。
如果要对软盘低级格式化,则可以用fdformat,而硬盘在出厂时已经格式化,无须低级
格式化(那是危险的)。检查文件系统则用e2fsck,如e2fsck -av /dev/fd0。
18.列出一个目录占用的空间
du或du -s或du -k ,du -S | sort -n 可以迅速发现哪个目录是最大的。
用df可以看到已安装的文件系统的空间大小及剩余空间大小。
quota -v查看用户的磁盘空间信息,如果你用quota限制了用户空间大小的话。
19.命令补起(TAB键的妙用)
很多shell都有这个功能:
1. 只需输入文件或目录名的前几个字符, 然后按TAB键,如无相重的,完整的文件名立即自动
在命令行出现;如有相重的,再按一下TAB键,系统会列出当前目录下所有以这几个字符开头的
名字.例如cd /mnt/cd 自动补起为 cd /mnt/cdrom。
2. 在命令行下,只需输入例如"m",再连续按两次TAB键,系统将列出所有以"m"开头的命令,
(包括自定义的Bshell命令函数),对查找某些记不清楚的命令特有用.
例如输入"ftp",将查到ftp, ftpcount, ftpwho, ftpshut等本不熟悉的命令。
20.让grep搜寻文件及所有子目录下的文件里的内容
例如搜寻ZhXwin下所有C原代码中的"Chinput"(试试取消下行的-q参数):
find /download/ZhXwin -name *.c -exec grep -q -s Chinput {} ; -print
查找所有文件则可以用:find . -type f -exec grep -s chinese {} ; -print 。
如果喜欢图形界面,KDE带的kfind很不错。
21.查看启动时的log信息
首先去查看/etc/syslog.conf文件,找到对应的文件。
通常在SlackWare下为/var/adm/messages,在Redhat下为 /var/log/messages。
这些文件可能会很大,要注意备份和删除。
22.产生一个以当日日期为后缀的文件
file=`date '+%m%d'` | touch todayis.$file
注意定义file变量中的"`"不是" '",而是左上角数字键1傍边那个(左单引号)。
23.利用Find命令改变所有权
想要改变当前目录下所有文件的所有权,可以这样:
find . -exec chown OWNER.[GROUP] {} ; (Solaris)
find . -exec chown -R OWNER.[GROUP] {} ; (Linux)
24.取消^M字符
当你FTP一些DOS文件到unix下时,你经常会看见每行文件后面有个讨厌的^M 字符,
有两个简单的方法可以取消它。用"vi"打开此文件,在Command mode下敲入::%s/^V^M//g ,
或者,在UNIX SHELL下敲入: sed 's/^V^M//g' foo > foo.new。
25.KDE是什么?
KDE是 K桌面环境,是由 Matthias Ettrich 在 1996年启动的一个计划。KDE的目标是
在 Unix操作系统和用户间建立良好的接口。简而言之,KDE将Unix带至桌面!
26.KDE是自由软件?
是, KDE是遵守GNU的自由软件。在LGPL下所有KDE库都允许开发KDE桌面的程序,
所有KDE应用程序得到GPL许可,KDE使用 Qt C++ 跨平台工具包,有各自的授权。简而言之,
Qt的授权允许你免费使用Qt来开发 X Windows下的软件,只要你的原始代码也自由地被使用。
如果你希望你的原始代码不允许修改,你必须获得Qt的商业授权。你能从Troll Tech web site
找到更多有关Qt信息 和它的授权.如果你怀疑授权,请与Troll Tech web site接触。
KDE和 Qt是可以通过 CD方式免费获得,运行时无任何费用。
27.在KDE中的K代表什么?
不表示任何东西。简单地说是 K桌面环境,就象X窗户系统中的X.。
28.KDE能在哪一个平台上工作?
KDE是所有Unix的桌面环境。大部分KDE开发者使用Linux,KDE平滑地跑在各式各样的系统上。
如果你使用的是Unix变体或不使用GNU开发工具如gcc,你也许要修改源代码。
可运行KDE的系统有Linux Solaris FreeBSD IRIX HP-UX。
29.KDE是窗口管理程序吗?
不, KDE不是窗口管理程序。KDE包含一个采用非常先进技术的窗口管理程序称KWM,
KDE是成熟的完整的桌面环境(IDE)。KDE提供完全桌面环境,包括文件管理程序、窗口管理程序、
帮助系统、配置系统、不可数的工具和正在增加的应用程序。
30.KDE是CDE, Windows 95或 MacOS克隆吗?
不, KDE不是克隆。特别地,KDE不是CDE或Windows克隆。在KDE开发者已经和正在收集所有
存在的桌面环境的最好特性的时候,KDE是真正的,唯一的环境。
31.Linux发布里有 KDE吗?
是的,主要的Linux分布都已经包含KDE。
32.如何检查正在使用的 KDE的版本?
看 KDE控制中心。如果没有 KDE的版本号,它肯定是1.0。另一个差别是在面板 'K'字,
在1.0中,它是黑白的3D K,在1.1中,它是在轮子上面的白色K。
33.KDE需要Qt
对KDE1.0,你需要Qt库1.33或更高的版本。对KDE1.1,你需要Qt库1.42或更高的版本。
但是不要下载Qt 2.0或更高版本。如果你想自己编译 KDE,你也需要头文件。
在 http://www.troll.no/dle有免费资源。你需要的libgr一般包括在大部分发布内。
请务必确认你本地的loopback设备正确设置。
34.Qt是什么?
Qt是建造使用者接口的C++基类库。它提供大多数widgets、菜单、按钮、sliders等等。
Qt是一个跨平台库,写的代码可在Unix编译,也可在Windows编译。
35.为什么KDE用Qt?
Qt是一个非常复杂工具包,他提供所有的现代用户接口。Qt由C ++写成,允许使用
object oriented development,…据我们看来没有比它更好的工具可以…。
所有KDE开发者同意如果没有Qt在如此短的时间不可能建造kde。
36.CVS是什么?
它是Concurrent Versions System的缩写字。它是版本控制系统,以RCS (修订版控制系统)
为基础,但是提供更多机能。它用于维护项目的原始代码。它将保持多个版本的东西,允许远程存
取最近原始代码。
37.怎样快速退出Xwindow?
Xwindow基本不会出现真正的死机(起码我没见过),如果出现无法运行的情,可以用ctrl+alt+
backspace退出窗口返回到命令行模式。
38.怎样转换虚拟终端?
在字符模式下用alt+左方向键(或右方向键)可以顺序切换各个虚终端,也可以用alt加F1到6
直接切换到各个虚终端。 在X Window模式下可以用ctrl+alt+F1(F1-F6)切换到各个虚终端,
ctrl+alt+F7切换回窗口。
39.在X Window做文字处理应使用哪个软件?
在命令行模式下输入kedit命令就可启动字处理软件,其功能类似于Win98的写字板。
三、 有关在linux中执行halt关机命令后出现的一些困惑见下:
Q: halt命令后,系统执行到system halted 时死在那里了,这是什么原因啊?
(or "我的linux是RedHat7.0,每次关机总关不掉主机电源,该怎么办呀?"也可参看下面的)
A: 实际上按照你所说的情况,不算是死机。因为你看到了system haled.....这表明是完全退出了linux操作系统!
就象我们在WIN98里一样(没有支持高级电源管理的情况下,会出现一个"你现在可以安全关闭计算机了"),
而linux默认没有这个提示而已,这时你可以按一下主机上的电源按钮来关机关掉电源!一切OK。
不过你为了达到你所希望的,你可以用以下命令: halt -p 或者poweroff 。
也可以通过修改:/etc/rc.d/init.d/halt中的有关"halt" 为"halt -p" 。
这样你只要用halt就可以在关机时关掉主机上的电源
如果你有其它的想法和不同的观点可以跟以下的贴子:
1,http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=163283
2.http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=138471
四、用软盘启动linux的朋友,在丢了或损坏了软盘时,而Lilo 没在 MBR上,Linux 还能启动吗?
请有这方面需要的朋友看下面这个贴子,或跟其贴!
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=162862
五、有关环境变量的查看、设定、删除
1. 查看环境变量的设定值
语法:setenv 查看所有环境变量的设定值。
语法:echo $NAME 显示指定的环境变量NAME的设定值。
例如:
echo $PRINTER 显示环境变量PRINTER 的设定值。
2. 设定环境变量
语法:setenv NAME word
例如:
setenv PRINTER sp 设定环境变量PRINTER 为sp。
3. 删除环境变量
语法:unsetenv NAME
例如:
unsetenv PRINTER 删除环境变量PRINTER的设定值。
六、linux下是否有病毒的讨论见下:(欢迎谈谈个人看法!)
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=160462
七、关于启动xwindow时如何自行选择gnome或kde?
方法有以下几种:
1.redhat7.1安装时默认启动为命令操作状态,启动时默认为gnome,可是有时候想用kde,
在用户根目录下编辑.xinitrc,加上一条命令startkde即可。
如果还要用gnome的话,只要把.xinitrc删掉就可以了。
2.可以直接修改$HOME/.xinitrc
如果启动gnome
.xinitrc文件内容应该这样写:
exec gnome-session
如果启动KDE
.xinitrc文件内容应该这样写:
exec startkde
3.use command:
switchdesk GNOME
4.在terminal运行:
switchdestop kde
或者
在x-windows下运行:
switchdestop
然后选一个wm
八、怎样使linux启动进入时不直接进入X-WINDOWS界面?
改/etc/inittab文件,将有"id:5:initdefault:"这一行中的,把数字5改成3即可
九、linux 与SVR4 or 4.3BSD有何关系? 请见以下贴子:
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=162987
十、在linux中如何设置系统时间? 参照以下文章:
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=159079
十一、关于swap分区的大小讨论! 参照以下文章:
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=158857
十二、在没有正常关机的情况下,而后开机时报告文件系统错误,要运行什么fsck?如何使用fsck?
你在shell命令提示符下:打 fsck命令。格式是:fsck /dev/hda? (针对ext2格式的文件也可以用e2fsck)
它还可以带一些参数见下: (详细请用: man fsck)
fsck的参数
-f
即使磁盘看起来无需检查也强制执行。默认情况下,只有当文件系统"肮脏"时才需要进行检查。或者说,只
有当文件系统没有正确卸载(dismount)、或者使用了一定的时间、系统重新启动一定次数后才需要进行检查。
-p
整理文件系统,自动修正所有可以安全地更正且不会导致数据丢失的问题。
-y
对所有问题回答yes。它的效果是:自动修正所有发现的问题,即使那些可能导致数据丢失的问题也要修正。
-b block
指定文件系统备用superblock的位置。在极其罕见的情况下,即当主superblock被损坏而文件系统主要部分仍
完整的情况下,该选项的作用将是非常大的。备用superblock通常位于8193、13685等位置,创建文件系统时
mkfs将输出该信息。
有一点很重要,那就是在检查完文件系统后,如果对该文件系统做了任何纠正,就应该立即重新启动系统(当
然,一般情况下,不能在文件系统被安装时检查它)。例如,如果e2fsck报告对文件系统的错误作了些纠正的话,
就应该立即用shutdown-r命令确保重新启动系统,这使得当e2fsck修改了文件系统后,系统能重新同步读文件
系统的信息。 与fsck相关的内容欢迎参加下面贴子讨论:
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=newbie&Number=154205
如何在Windows下关闭网络端口,保护电脑
第一步,点击“开始”菜单/设置/控制面板/管理工具,双击打开“本地安全策略”,选中“IP 安全策略,在本地计算机”,在右边窗格的空白位置右击鼠标,弹出快捷菜单,选择“创建 IP 安全策略”(如右图),于是弹出一个向导。在向导中点击“下一步”按钮,为新的安全策略命名;再按“下一步”,则显示“安全通信请求”画面,在画面上把“激活默认相应规则”左边的钩去掉,点击“完成”按钮就创建了一个新的IP 安全策略。
第二步,右击该IP安全策略,在“属性”对话框中,把“使用添加向导”左边的钩去掉,然后单击“添加”按钮添加新的规则,随后弹出“新规则属性”对话框,在画面上点击“添加”按钮,弹出IP筛选器列表窗口;在列表中,首先把“使用添加向导”左边的钩去掉,然后再点击右边的“添加”按钮添加新的筛选器。
第三步,进入“筛选器属性”对话框,首先看到的是寻址,源地址选“任何 IP 地址”,目标地址选“我的 IP 地址”;点击“协议”选项卡,在“选择协议类型”的下拉列表中选择“TCP”,然后在“到此端口”下的文本框中输入“135”,点击“确定”按钮(如左图),这样就添加了一个屏蔽 TCP 135(RPC)端口的筛选器,它可以防止外界通过135端口连上你的电脑。
点击“确定”后回到筛选器列表的对话框,可以看到已经添加了一条策略,重复以上步骤继续添加 TCP 137、139、445、593 端口和 UDP 135、139、445 端口,为它们建立相应的筛选器。
重复以上步骤添加TCP 1025、2745、3127、6129、3389 端口的屏蔽策略,建立好上述端口的筛选器,最后点击“确定”按钮。
第四步,在“新规则属性”对话框中,选择“新 IP 筛选器列表”,然后点击其左边的圆圈上加一个点,表示已经激活,最后点击“筛选器操作”选项卡。在“筛选器操作”选项卡中,把“使用添加向导”左边的钩去掉,点击“添加”按钮,添加“阻止”操作(右图):在“新筛选器操作属性”的“安全措施”选项卡中,选择“阻止”,然后点击“确定”按钮。
第五步、进入“新规则属性”对话框,点击“新筛选器操作”,其左边的圆圈会加了一个点,表示已经激活,点击“关闭”按钮,关闭对话框;最后回到“新IP安全策略属性”对话框,在“新的IP筛选器列表”左边打钩,按“确定”按钮关闭对话框。在“本地安全策略”窗口,用鼠标右击新添加的 IP 安全策略,然后选择“指派”。
于是重新启动后,电脑中上述网络端口就被关闭了,病毒和黑客再也不能连上这些端口,从而保护了你的电脑。
Adobe Acrobat Standard 6.0.0升级到6.0.1的补丁
Adobe Acrobat Standard 6.0.0升级到6.0.1的补丁
本补丁程序将 Adobe Acrobat 6.0 Standard 升级为 6.0.1 版,且修复了多个程序缺陷,其中包括支持 Microsoft Office 2003、增强了对不同扫描仪的支持、提高了与一些屏幕阅读器的兼容性(例如,屏幕阅读器与表单的交互),是一个更便于使用的 eBook 激活系统(包括在多个设备上激活)。本补丁程序还修复了在查看使用 Adobe(R) Photoshop(R) Album 创建的 PDF 文件时出现的问题,提高了与使用旧版本的 Acrobat 和在 Mac OSX 系统上创建的 PDF 文件的兼容性。
Reflector使用手记
早就听说Reflector这个强大的类库分析与反编译工具,不过一直没有很好的利用起来。最近使用Reflector解决了一个实际开发问题,现将其总结出来。
需求导入:项目是一个GIS项目,在项目中使用到了ESRI公司的Application Development Framework中的一个WebControls控件,此控件的功能过于复杂,并且引用到了ArcGIS Server的很多COM组件。由于项目根本就没有使用ADF的任何服务器技术,但是也不得不跟着引用一些COM组件,更麻烦的是还得安装ADF(此组件可是有将近200M的庞然大物)。
项目经理需要我解决这种问题并且必须尽快解决,我当时也相应的考虑到了两个方案:
- 重新写一个类似的控件,此控件只做项目中用到的一些功能,至于其它功能以后再扩展;
- 利用ESRI的WebControls控件,去掉对COM的所有引用,因为项目没有使用WebControls控件的任何服务器技术,也就无需COM引用
由于时间有限,所以决定采用第二种方案,一开始使用ILDASM分析了Web Server控件的一些类,发现过于类过于庞大。偶然想起了Reflector工具(我以前使用过Reflector工具分析过源代码,不过好久没用),以下是整个解决过程:
- 打开Reflector工具并且下载了一个FileDisassembler插件,FileDisassembler插件用于输出程序集的反编译结果到文件中。打开Reflector工具,并导入FileDisassembler插件。导入好后加载程序集将反编译结果输出到指定的文件夹中;
Reflector下载地址:http://www.aisto.com/roeder/dotnet 下载时必须输入用户名和Email地址,用户名中必须有空格;
FileDisassembler插件的下载地址:http://www.denisbauer.com/
- 使用VS.NET新建一个项目,根据文件夹结构新建相应的文件夹,导入所有的源文件和资源文件。使用FileDisassembler导出的资源文件为全名称,在实际的项目中必须根据namespace更改资源文件名且必须将“生成操作”更改为“嵌入的资源”,可以使用ILDASM查看metadata来决定资源文件名及所在的文件夹,编译并更改一些错误;
- 当编译好后,找到所有与COM有关的内容将其注释掉(因为以前使用过CCW/RCW技术),并做相应的更改,每更改一个class后,编译一次,直到去掉其相关引用为止;
- 更改完成后,需要对其进行重构,主要重构以下方面:
- Rename,因为Reflector工具反编译时其变量名会根据类型来命名,如text1,text2,num1等;
- 去掉goto语句,如果代码中有swtich语句时,Reflector工具会使用goto语句,严重影响程序逻辑其可读性;
- Extract Method,将过于长的method执行分解操作;
当重构完成后,应用到项目中,并更改相应的Register语句,test,run,结果是successful,从而也在最短的时间内完成了项目经理所交给我的任务。
先行说明:在reflect时,请遵守ESRI公司的End User Licenses。
查看全文Visual C++ .NET Code Samples
自动封杀非法连接FTP的IP
由于提供了FTP下载而又限制了线程,所以总发现有人不断用多线程进行尝试,这样会大大增加服务器的负荷,这种事“损人不利己”!
为了惩罚这种人,决定写个SHELL,在crond里每1分钟运行一次,自动统计非法线程的IP和线程数量,然后自动将他的IP地址写到iptables里,来惩罚一下他们!
在此,非常感谢“零二年的夏天”!他给了我很大的帮助!!!
这下可以惩罚一下那些贪得无厌的人了……
vi /usr/local/sbin/fuckgo
代码:
#! /bin/bash
fuck_who()
{
netstat -an|grep
"210.51.184.197:21"|grep -v LISTEN|grep -v ESTABLISHED|awk '{print $5;}'|awk
-F'=' '{print $1;}'|sort|uniq -c|awk '{print $1"="$2;}'
}
for _un in $(fuck_who)
do
if [ $(echo $_un|awk -F'=' '{print
$1;}') -gt 9 ]
then
iptables -I INPUT -s $(echo
$_un|gawk -F'=' '{print $2;}') -p tcp --dport 21 -j DROP
fi
done
vi /etc/crontab
添加
代码:
00-59/1 * * * * root /usr/local/sbin/fuckgo
/etc/rc.d/init.d/crond restart
蓝色是总连接数,橙色是有效连接数
当蓝色超过橙色很多时,证明有人在贪得无厌地进行多线程尝试
从图上可以看出,蓝色瞬间值很高,但转瞬而逝,不会持续很久,因为那个人的IP已经进入了iptables“黑名单”
为了避免误杀(因为有很多是动态IP地址),用crond每天凌晨4点执行一下fuckclean,来清除一天来被封杀过的IP
当然,如果该IP违规,fuckgo会以每1分钟一次的频率扫描,发现之后再次封杀,再次解开就只能等第二天凌晨4点了
vi /usr/local/sbin/fuckclean(呵呵,这回是我自己写了)
代码:
#! /bin/bash
clean_who()
{
iptables -vL|grep "DROP"|grep
ftp|awk '{print $8;}'
}
for _un in $(clean_who)
do
iptables -D INPUT -s $_un -p tcp
--dport 21 -j DROP
done








