LINUXQQ狂人时代

Main menu:

Archive for 4月, 2009

DNS正向区域

TTL    86400
@               IN SOA  dns1.wonxun.com  root.wonxun.com (
                                        42              ; serial (d. adams)
                                        3H              ; refresh
                                        15M             ; retry
                                        1W              ; expiry
                                        1D )            ; minimum
                IN NS           dns1
www             IN A            123.123.123.
mail            IN A            123.123.123.

dns1         IN A            123.123.123.12
~

SOA资源记录

SOA资源记录

 
发布时间:2007.03.29 17:50     来源:赛迪网技术社区    作者:metal

SOA资源记录是一个常常让大家困惑的问题,现在我来详细对它进行说明。

 

SOA(start of authority)记录定义了DNS授权区域的起始点。

 

下面先给出一个具体的例子:

 

@ IN SOA server.lpicn.org. admin.lpicn.org. (

2003062201 ; Serial

28800 ; Refresh

7200 ; Retry

604800 ; Expire

86400) ; Minimum TTL

 

例子第一行的“@”表示当前起始点。起始点的含义是,数据文件是为哪个区域创建的,该区域就是当前的起始点。这样的话,这个数据文件中的所有记录都遵从这里的SOA规定,除非它们另有说明(比如ttl说明)。对于其他类型的记录,这里的@也可换成一个主机名如aa,但SOA记录只能用@。因为SOA记录中定义了区传送的时间参数,这必须对应于整个数据文件而不是某条记录。

 

第一行中的“IN SOA”说明这是一条SOA记录。

 

第一行中的“server.lpicn.org.”表示该数据文件记录在哪一台主机中,如果这台主机是本区域的,那么必须在该区域文件中定义这台主机。注意这里的最后一个“.”是有意义的,假设这个数据文件是为”lpicn.org.”区域创建的话,那么,如果不写点,而写成”server.lpicn.org”,则相当于写成”server.lpicn.org.lpicn.org.”,这里的内容可参考dns数据文件的语法规定。

 

第一行中的“admin.lpicn.org.”给出了负责维护域名服务器的管理员的邮件地址,它相当于“admin@lpicn.org”,这里把“@”换成了“.”;

 

我们可以注意到,在第2至5行的数字外面还套了一对括号。其实是这样的,本来这里所有的数字都是应该写在同一行的,然而,为了看上去方便,我们将之分为5行。使用括号,可以将跨越多行的数据定义在一起,视为一个整行数据处理。

 

5行数据的前四行都是针对主辅服务器间的区传送而言的。

 

数据的第一行是序列号,进行区传送时,检查主服务器上的序列号有无变大(比较的方法是辅服务器利用上次从主服务器获得的数据和这次的进行比较),如果变大了,就进行传送,否则不传送。这个序列号可以是小数,如果是小数,也必须按一定的规则转变为整数进行比较。规则是这样的:小数点右边的乘以1000,然后直接把小数点右边的连接到前面乘法运算后的结果之后,如200.1相当于2000001,100.01相当于10000001,这样200.1倒反而比100.01来得小了,所以这种方法很不直观,不推荐使用,但要看的懂,有时还是有用的,因为它可以缩短数字的长度。一种我们推荐的方法是使用如下形式:“年月日第几次”,如2003年6月22日第1次修改用“2003062201”,第二次修改用2003062202,…。当序列号变得很大,需要重新变小时,为了能让区传送继续,一种方法是删除所有辅服务器上的对应区域文件并重启服务,这样来强制执行区传送。

 

数据的第二行是辅服务器检查主服务器是否同步的间隔时间。

 

数据的第三行是辅服务器在区传送失败后,等待再次进行区传送的时间间隔。

 

数据的第四行规定,如果不能保证辅服务器与主服务器同步,最长可以使用辅服务器数据的时间,时间到了之后,仍不能进行传送的话,辅服务器将丢弃对应的数据。

 

数据的第五行是最小TTL(time-to-live)时间,这是针对缓存而言的,与区传送没有关系。 生存期(TTL)为所容许的名字服务器对数据缓存的时间长度,一旦生存期到了,名字服务器必须丢弃缓存数据并从授权的名字服务器中重新获取新的数据。这样可以确保域数据在整个网络上的一致性。

 

缓存不仅保存成功查询信息,也保存失败查询信息。我们常有体验,在访问一个叫abcd.efg.com的站点时,如果查询失败,那么,在短时间内重新访问这个站点,会立刻返回这个主机不存在的信息,就是这个道理。在BIND8.2以前的版本中,两种缓存的生存期使用同一个值,而新版本中分别设定值。对于老版本,名字服务器的数据库文件的SOA最后一项就是TTL;而新版本(Bind8.2及以后版本)数据库文件的SOA最后一项是失败信息缓存的生存期,文件的第一行则多了个$TTL,为成功信息的缓存生存期。

 

最后一点说明,上面的时间在较老的版本都是以秒为单位,新版本中默认以秒为单位,也可根据需要自己指定单位,具体请查阅相关文档。但需注意,对于区传送的时间参数,如果设定为很短时间,比如两秒,则不一定能按照该时间进行,一般会比设定的长一点。

 

希望上面的内容能够对大家有所帮助。

 

 

 

apahe+tomcat 301

  1. 用Apache的.htaccess来做301域名转向,很牛!   
  2. 由于本人在国外注册的域名在国内访问有点慢,所以需要用国内的免费dns服务器(有免费的,为什么不用?呵…暂时没必要去组一个DNS服务器出来),但这些DNS服务器不支持域名转向,于是只能用别的方法了——这方法很牛:连后面了具体网址,甚至跟了rewrite都可以转向!    
  3. 把代码分享给大家    
  4.   
  5. 1、开启apache支持.htaccess,方法:   
  6. 在Apache的配置文件httpd.conf中,找到   
  7. <Directory />   
  8.     Options FollowSymLinks   
  9.     AllowOverride None   
  10. 把其中的AllowOverride None改为AllowOverride All,然后重启apache。   
  11.   
  12. 2、在网站的根目录下新建一个.htaccess的文件,并把.htaccess文件的权限改成644  
  13.   
  14. 3、把下面的三行内容复制到这个文件中   
  15.   
  16. RewriteEngine on    
  17. RewriteCond %{HTTP_HOST} ^aidong.org [NC]    
  18. RewriteRule ^(.*)$ http://www.aidong.org/$1 [L,R=301]   
  19.   
  20. 记得把域名改成你自己的…   

整理一下杂七杂八的postfix+extmail的mail服务器架设维护笔记

整理一下杂七杂八的postfix+extmail的mail服务器架设维护笔记

前提: 做好DNS的A记录,MX(Mail Exchange mail交换记录)
如:upkiller.com 192.168.1.123
    mx=mail.upkiller.com
    mail.upkiller.com=192.168.1.123

检查:
nslookup upkiller.com
nslookup -type=MX upkiller.com
输出结果:
upkiller.com       MX preference = 1, mail exchanger = mail.upkiller.com
mail.upkiller.com internet address = 192.168.1.123

mail server的备份:可以设置多个邮件交换记录,设置MX优先级,安装多台的主机实现
如:
;Host Address (A记录)
mail1.upkiller.com
mail2.upkiller.com

;Mail Exchanges (MX记录)
upkiller.com IN MX 1 mail1.upkiller.com
upkiller.com IN MX 2 mail2.upkiller.com

邮件传递顺序,优先MX记录,如没有MX记录,尝试将邮件传给该域的A记录ip地址。
—————————————————————————-
SMTP状态码:

2xx 答应要求
4xx 遇到暂时性的错误
5xx 发生永久性问题

——————————————————————————
一 ,安装cyrus-sasl-2.1.22(Simple Authentication and Security Layer)

简单的验证和安全层,smtp发信认证。

 

ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-sasl-2.1.22.tar.gz
tar -zxvf cyrus-sasl-2.1.22.tar.gz
./configure –prefix=/usr/local/sasl2
–disable-gssapi
–disable-anon
–disable-sample
–disable-digest
–enable-plain
–enable-login
–enable-sql
–with-mysql=/usr/local/mysql
–with-mysql-includes=/usr/local/mysql/include/mysql
–with-mysql-libs=/usr/local/mysql/lib/mysql
–with-authdaemond=/usr/local/courier-authlib/var/spool/authdaemon/socket
make
make install
rm /usr/lib/libsasl

关闭原有的sasl链接新的(重要):
mv /usr/lib/libsasl2.a   /usr/lib/libsasl2.a.OFF
mv /usr/lib/libsasl2.la   /usr/lib/libsasl2.la.OFF
mv /usr/lib/libsasl2.so.2.0.19   /usr/lib/libsasl2.so.2.0.19.OFF
mv /usr/lib/sasl2   /usr/lib/sasl2.OFF

rm /usr/lib/libsasl2.so
rm /usr/lib/libsasl2.so.2
ln -sv /usr/local/sasl2/lib/*   /usr/lib
postfix 2.3以后的版本会分别在/usr/local/lib和/usr/local/include中
搜索sasl库文件及头文件,故还须将其链接至此目录中:
ln -sv /usr/local/sasl2/lib/*   /usr/local/lib
ln -sv /usr/local/sasl2/include/sasl/*   /usr/local/include
创建运行时需要的目录并调试启动
mkdir -pv /var/state/saslauthd
/usr/local/sasl2/sbin/saslauthd -v //看看版本是不是2.1.22    
/usr/local/sasl2/sbin/saslauthd -a shadow pam -d //正常不会报错

启动并测试
/usr/local/sasl2/sbin/saslauthd -a shadow pam
/usr/local/sasl2/sbin/testsaslauthd -u root -p password //正常显示0: OK “Success”成功

配置库文件搜索路径,让postfix能找到sasl:
echo “/usr/local/sasl2/lib” >> /etc/ld.so.conf
echo “/usr/local/sasl2/lib/sasl2″ >> /etc/ld.so.conf
ldconfig -v
ldconfig -v | grep sasl2 //看看有没有什么错误

加入开机自启动:
echo “/usr/local/sasl2/sbin/saslauthd -a shadow pam” >> /etc/rc.local

错误FAQ:
1,authentication mechanisms: getpwent pam rimap shadow

    echo “/usr/local/sasl2/lib” >> /etc/ld.so.conf
    echo “/usr/local/sasl2/lib/sasl2″ >> /etc/ld.so.conf
    ldconfig -v

———————————————————————–

二,安装postfix-2.4.5:(Mail Transport agent(MTA)邮件传输代理)

http://www.postfix.org
ftp://ftp.cuhk.edu.hk/pub/packages/mail-server/postfix/index.html

下载:postfix-2.4.5.tar.gz源码包

rpm -e sendmail –nodeps //删除sendmail

//添加postfix用户组和帐号

groupadd -g 2525 postfix
useradd -u 2525 -g postfix -s /sbin/nologin -d /dev/null postfix
groupadd -g 2526 postdrop
useradd -g postdrop -u 2526 -s /bin/false postdrop

tar -zxvf postfix-2.4.5.tar.gz

配置postfix编译参数支持sasl,mysql验证:

make -f Makefile.init Makefiles \
‘CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include/mysql -DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I/usr/local/sasl2/include/sasl’ \
‘AUXLIBS=-L/usr/local/mysql/lib/mysql -lmysqlclient -lz -lm -L/usr/local/sasl2/lib   -lsasl2′
(这里要注”这间要有一个空格)
make
make install

安装最后的选项:
install_root:[/]   (默认)
tempdir:[/home/postfix-2.4.5] /tmp
config_directory: [/etc/postfix] (默认)
daemon_directory:[/usr/libexec/postfix] /usr/local/postfix/libexec
command_directory:[/usr/sbin] /usr/local/postfix/sbin
queue_directory:[/var/spool/postfix] (默认)
sendmail_path: [/usr/sbin/sendmail] (默认)
newaliases_path: [/usr/bin/newaliases] (默认)
mailq_path: [/usr/bin/mailq] (默认)
mail_owner: [postfix] (默认)
setgid_group: [postdrop]   (默认)
html_directory: [no] (默认)
manpages: [/usr/local/man] /usr/local/postfix/man (默认)   
readme_directory: [no]

编译postfix错误FAQ:
cannot find -lmysqlclient
严格检查输入是否有误:),’AUXLIBS前面要有空格,或是把mysql库加入搜索路径:
echo /usr/local/mysql/lib/mysql >> /etc/ld.so.conf
ldconfig

最后:
生成别名二进制文件,这个步骤如果忽略,会造成postfix效率极低:
/usr/bin/newaliases

检验postfix是否支持sasl认证,如果输出为以下结果,则支持:
/usr/local/postfix/sbin/postconf   -a
cyrus
dovecot
/usr/local/postfix/sbin/postconf -m | grep mysql
mysql

没有的话需重新编译postfix。
————————————————————
启动错误FAQ:

1,postsuper: fatal: scan_dir_push: open directory defer:Permission denied
postfix/postfix-script: fatal: Postfix integrity check failed!

进入postfix-2.4.5源码目录重新make install一遍即可

———————————————————————-
三,配置基本postfix:
修改main.cf配置文件:
vi /etc/postfix/main.cf

myhostname = mail.upkiller.com     //主机名称
mydomain = upkiller.com      //域名
myorigin = $mydomain            //组织名称,邮件标头上面的 mail from 的那个地址
inet_interface = all       //监听的网卡接口
mydestination = $myhostname,localhost.$mydomain,localhost,$mydomain //指定postfix系统要接收到哪个域名的邮件
mynetworks = 127.0.0.0/8           //允许不使用smtp发信认证的网段

配置main.cf说明:

1,参数行和注释行是不能处在同一行中,参数不要加引号,=号两边的空格可有可无
2,被引用的参数并不一定要先定义,即顺序颠倒也无所谓。
3,如果参数同时拥有一个以上的值,参数之间可以用逗号,空格|tab,或换行字符隔开。
4,如果参数太多无法放同一行,可以将它们放在不同的行中,只需要在每行前多置一个
    tab|空格即可;postfix会把第一个字符为(空格|tab)的行视为前一行的延续。
5,修改后立即生效,重载配置postfix reload,最好可以postfix stop;postfix start

启动postfix测试:

/usr/local/postfix/sbin/postfix check   //检查postfix的完整性(没有消息就是good)
/usr/local/postfix/sbin/postfix start
netstat -tnl | grep :25

建立收信测试帐号:
adduser upkiller
passwd upkiller

发信测试:
nc localhost 25
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail from:root@upkiller.com
rcpt to:upkiller@upkiller.com
data
subject:Postfix mail test!
postfix test!
.
quit
开启另一tty用upkiller登陆:
mail
“/var/spool/mail/upkiller”: 1 message 1new
>N 1 root@upkiller.com Thu Seq 20 05:12 15/547 “Postfix mail test!”

cat /var/spool/mail/upkiller //储存upkiller用户的mail文件
测试成功。

———————————————————————
四,开启cyrus-sasl认证功能:

vi main.cf

#====================SASL========================  
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_invalid_hostname,
reject_non_fqdn_hostname,
reject_unknown_sender_domain,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
reject_unauth_destination,
permit
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $domain
smtpd_sasl_security_options = noanonymous
smtpd_sasl_application_name = smtpd
smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
#编辑smtpd.conf
vi /usr/local/lib/sasl2/smtpd.conf

内容:
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN

重新启动postfix:
/usr/local/postfix/sbin/postfix stop
/usr/local/postfix/sbin/postfix start

测试:
adduser upkiller
passwd upkiller

//取base64编码
perl -MMIME::Base64 -e ‘print encode_base64(”upkiller”)’
dxBraWxsZXI=

nc localhost 25

220 mail.upkiller.com ESMTP Postfix (2.4.5)
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN (看见这二行即成功)
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
dXBraWxsZXI=
334 VXNlcm5hbWU6
dXBraWxsZXI=
235 2.0.0 Authentication successful
mail from:root@upkiller.com
rcpt to:upkiller@upkiller.com
data
subject:smtp authentication test!
test ok
.
quit
错误FAQ:

tail -f /var/log/maillog

1,fatal: SASL per-connection initialization failed
warning: /usr/local/libexec/postfix/smtpd: bad command startup
解决方法:
sasl2没装好,和旧的冲突,重新安装sasl2把sasl2装在/usr/local/sasl2下再关闭旧的
文件,连接新的,确保系统能找到的include和lib文件都是新编的,
再重编译postfix即可

2,NIS domain name not set NIS lookups disabled
提示没有启动NIS
alias_maps = $alias_database
强制postfix只使用本地的aliases资料库。
————————————————————-
五,让postfix支持mysql的虚拟域和虚拟用户:

1、编辑/etc/postfix/main.cf,添加如下内容:

vi /etc/postfix/main.cf
#================ Virtual Mailbox Settings =====================#
# 指定用户邮箱所在的根目录
virtual_mailbox_base = /var/mailbox
#指定postfix如何去检索邮箱,这里是采用mysql
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
#指定postfix如何去检索虚拟域
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_alias_domains =
#指定postfix如何去检索虚拟别名
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
#邮件账号uid, 即postfix组id号(即/var/mailbox目录所有者的帐号)
virtual_uid_maps = static:2525
virtual_gid_maps = static:2525
#如果没有安装maildrop,则此处为virtual
virtual_transport = virtual
maildrop_destination_recipient_limit = 1
maildrop_destination_concurrency_limit = 1

#================ QUOTA Settings =============================#(邮箱限额)

#每封信的最大(10M),postfix的默认值是10M, 但这指的是邮件正文和编码后附件的总和
#, 经过#base64编码,附件的大小会增加35%左右, 因此这里设定可接受邮件的大小为14M  
message_size_limit = 14336000
virtual_mailbox_limit = 20971520
virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
#指定postfix如何获得用户的quota信息(每个用户的邮箱大小)
virtual_mailbox_limit_maps =
mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
# 是否允许覆盖默认邮箱的大小
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = Sorry, the user’s maildir has overdrawn his diskspace quota, please Tidy your mailbox and try again later.
virtual_overquota_bounce = yes

2、添加为支持虚拟域和虚拟用户所用到的配置文件:

vi /etc/postfix/mysql_virtual_alias_maps.cf //虚拟别名:

user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = alias
select_field = goto
where_field = address
additional_conditions = AND active = ‘1′

vi /etc/postfix/mysql_virtual_domains_maps.cf //虚拟域

user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = domain
select_field = domain
where_field = domain
additional_conditions = AND active = ‘1′

 

vi /etc/postfix/mysql_virtual_mailbox_limit_maps.cf //虚拟邮箱容量

user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = mailbox
select_field = quota
where_field = username
additional_conditions = AND active = ‘1′
vi /etc/postfix/mysql_virtual_mailbox_maps.cf //虚拟邮箱

user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = mailbox
select_field = maildir
where_field = username
additional_conditions = AND active = ‘1′

 

//新建虚拟用户邮箱所在目录,postfix用户所有:
mkdir -pv /var/mailbox
chown -R postfix:postfix /var/mailbox
//开启smtp也从mysql中验证帐号:
vi /usr/local/lib/sasl2/smtpd.conf (/usr/lib/sasl2连接到该目录)
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: PLAIN LOGIN
sql_engine: mysql
sql_hostname: localhost
sql_user: extmail
sql_passwd: extmail
sql_database: extmail
sql_select: SELECT password FROM mailbox WHERE username=’%u@%r’ and
domain=’%r’ and active=’1′

(%u表示登录的用户名,%r表示smtpd_sasl_local_domain = $myhostname 的值)
重启postfix

 

//打开mysql的查询日志功能
vi /etc/my.cnf
[mysqld]
log=/var/log/mysqld/log.log

创建日志文件并设置权限
mkdir /var/log/mysqld
touch /var/log/mysqld/log.log
chown -R mysql:mysql /var/log/mysqld  

//重启mysql
service mysqld stop
service mysqld start

//测试postfix连接mysql数据库查询认证
//取base64编码
perl -MMIME::Base64 -e ‘print encode_base64(”upkiller”)’
dxBraWxsZXI=

nc localhost 25

220 mail.upkiller.com ESMTP Postfix (2.4.5)
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN (看见这二行即成功)
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
dXBraWxsZXI=
334 VXNlcm5hbWU6
dXBraWxsZXI=
235 2.0.0 Authentication successful
tail -f /var/log/mysqld/log.log
提示如下日志:
connect postfix@localhost on postfix
SELECT password FROM mailbox WHERE username=’upkiller@upkiller.com’ and
domain=’upkiller.com’ and active=’1′

tail -f /var/log/maillog

验证错误提示:
SASL login authentication failed: authentication failure
成功:connect from localhost.localdomain
把原先系统的cyruss-sasl删除,再重新编译cyrus-sasl和postfix:
rpm -e `rpm -qa | grep cyrus-sasl` –nodeps
一般都是没有安装和配置好courier authentication.

再做其它各种查询测试:
//邮箱
postmap -q ‘maps’ mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
SELECT maildir FROM mailbox WHERE username=’maps’

//别名
postalias -q ‘alias’ mysql:/etc/postfix/mysql_virtual_alias_maps.cf
SELECT goto FROM alias WHERE address=’alias’

——————————————————————————–

六,安装Courier authentication library:
新版本的imap不再包含authentication library,必须先安装 Courier authentication library
http://kent.dl.sourceforge.net/sourceforge/courier/
下载:
http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/c/co/courier/courier-authlib-0.59.3.tar.bz2

解压编译安装:
tar jxvf courier-authlib-0.59.3.tar.bz2
cd courier-authlib-0.59.3
./configure –prefix=/usr/local/courier-authlib \
–sysconfdir=/etc \
–without-authpam \
–without-authldap \
–without-authpwd \
–without-authshadow \
–without-authvchkpw \
–without-authpgsql \
–with-authmysql \
–with-mysql-libs=/usr/local/mysql/lib/mysql \
–with-mysql-includes=/usr/local/mysql/inculde/mysql \
–with-redhat \
–with-authmysqlrc=/etc/authmysqlrc \
–with-authdaemonrc=/etc/authdaemonrc \

#优化
     CFLAGS=”-march=i686 -O2 -fexpensive-optimizations”  
     CXXFLAGS=”-march=i686 -O2 -fexpensive-optimizations”
make
make install

chmod 755 /usr/local/courier-authlib/var/spool/authdaemon
cp /etc/authdaemonrc.dist   /etc/authdaemonrc
cp /etc/authmysqlrc.dist   /etc/authmysqlrc

编辑authdaemonrc(确保只使用mysql认证):
vi authdaemonrc  
authmodulelist=”authmysql”
authmodulelistorig=”authmysql”
daemons=10
DEBUG_LOGIN=2 (打开日志方便调试,调试成功之后再关闭)

编辑/etc/authmysqlrc 为以下内容,其中2525,2525 为postfix 用户的UID和GID:

MYSQL_SERVER localhost
MYSQL_PORT 3306               (指定你的mysql监听的端口3306)
MYSQL_USERNAME   extmail       (extmail数据库的所有者的用户名)
MYSQL_PASSWORD   extmail         (数据库帐户密码)
MYSQL_SOCKET   /tmp/mysql.sock
MYSQL_DATABASE   extmail
MYSQL_USER_TABLE   mailbox
MYSQL_CRYPT_PWFIELD   password
MYSQL_UID_FIELD   ‘2525′
MYSQL_GID_FIELD   ‘2525′
MYSQL_LOGIN_FIELD   username
MYSQL_HOME_FIELD   concat(’/var/mailbox/’,homedir)
MYSQL_NAME_FIELD   name
MYSQL_MAILDIR_FIELD   concat(’/var/mailbox/’,maildir)

注意:确认在这个文件中不能用空格键,只能用tab键。
确认只使用单引号,比如:’/var/mailbox/’,'UID’,'GID’
localhost不能用单引号
确认你的/etc/hosts文件中有localhost
编译时如果支持Ipv6可能导致错误
MYSQL_GID_FIELD 和MYSQL_UID_FIELD是maildrop的UID和GID,而不是MySQL的。
如果想使用md5密码,把MYSQL_CLEAR_PWFIELD password改成MYSQL_CRYPT_PWFIELD password
加入库搜索路径:
echo “/usr/local/courier-authlib/lib/courier-authlib” >> /etc/ld.so.conf
ldconfig -v

加入开机启动:
cp courier-authlib.sysvinit /etc/init.d/courier-authlib
chmod 755 /etc/init.d/courier-authlib
chkconfig –add courier-authlib
chkconfig –level 35 courier-authlib on
手动启动:
/usr/local/courier-authlibn/sbin/authdaemond start
检测是否启动成功:
pstree | grep authdaemond

——————————————–
错误FAQ:

1,MYSQL_SERVER: command not found等一大堆参数错误
原来是
cp /etc/authmysqlrc.dist   /etc/authdaemonrc
时复制文件名错误:(

2,configure: error: –with-authmysql specified but no mysqlclient.so

checking for mysql_config… /usr/bin/mysql_config
checking for mysql_connect… no
checking for mysql_real_connect… no

rm /usr/bin/mysql_config
ln -s /usr/local/mysql/bin/mysql_config /usr/bin/mysql_config
再不行:
ln -s libmysqlclient.so.15 libmysqlclient.so.12
ln -s libmysqlclient.so.15 mysqlclient.so
——————————————————————————–
七,安装Courier-IMAP(提供POP3/IMAP服务):

下载:
http://surfnet.dl.sourceforge.net/sourceforge/courier/courier-imap-4.1.3.tar.bz2

tar jxvf courier-imap-4.1.3.tar.bz2
cd courier-imap-4.1.3
./configure –prefix=/usr/local/courier-imap \
–with-redhat \
–enable-unicode=utf-8,iso-8859-1,gb2312,gbk,gb18030 \
–disable-root-check \
–with-trashquota \
–without-ipv6 \
CPPFLAGS=’-I/usr/local/courier-authlib/include’ \LDFLAGS=’-L/usr/local/courier-authlib/lib/courier-authlib’ \
COURIERAUTHCONFIG=’/usr/local/courier-authlib/bin/courierauthconfig’

make
make install

//建立配置文件
cd /usr/local/courier-imap/etc
ls *.dist | awk -F”.” ‘{print “cp “$0″ “$1″”}’ | sh

//打开pop3,imapd支持,修改MAILPATH
vi /usr/local/courier-imap/etc/pop3d
POP3DSTART=YES
MAILDIRPATH=/var/mailbox
vi /usr/local/courier-imap/etc/imapd
IMAPDSTART=YES
MAILPATH=/var/mailbox

 

//加入开机启动
cp courier-imap.sysvinit /etc/rc.d/init.d/courier-imapd
chmod 755 /etc/rc.d/init.d/courier-imapd
chkconfig –add courier-imapd
chkconfig –level 2345 courier-imapd on
service courier-imapd start
检测:
netstat -tnl |egrep “110|143″
新建虚拟用户邮箱所在的目录,并将其权限赋予postfix用户:
#mkdir –pv /var/mailbox
#chown –R postfix /var/mailbox

接下来重新配置SMTP 认证,编辑 /usr/local/lib/sasl2/smtpd.conf ,确保其为以下内容:
pwcheck_method: authdaemond
log_level: 3
mech_list: PLAIN LOGIN
authdaemond_path:/usr/local/courier-authlib/var/spool/authdaemon/socket

验证:
nc localhost 25 (重复上面的)
tail -f /var/log/mysqld/log.log
如果有下面:
SELECT username,password, “”, ‘2525′, ‘2525′,concat(’/var/mailbox/’,homedir)..
表示重新配置的smtp验证成功了。
———————————————-
调试:pop3

编辑authdaemonrc:
DEBUG_LOGIN=2 (打开日志方便调试,调试成功之后再关闭)
tail -f /var/log/maillog

nc localhost 110
user user1@extmail.org
user user
list
retr 1
quit

——————————————————————–

———————————————————————
安装extman:
tar -zxvf extman-0.2.2.tar.gz
mv extman-0.2.2 /var/www/extsuite/extman
cd /var/www/extsuite/extman
vi webman.cf
SYS_MAILDIR_BASE = /home/domains
此处即为您在前文所设置的用户邮件的存放目录,可改作:
SYS_MAILDIR_BASE = /var/mailbox

SYS_MYSQL_SOCKET = /var/lib/mysql/mysql.sock
此处修改为:
SYS_MYSQL_SOCKET = /tmp/mysql.sock
SYS_DEFAULT_GID = 2525 //即postfix组gid

更改目录的权限:
chown -R postfix.postfix /var/www/extsuite/extmail/cgi/
chown -R postfix.postfix /var/www/extsuite/extman/cgi/

mkdir /tmp/extman
chown -R postfix:postfix /tmp/extman

配置apache:
<VirtualHost *>
         ServerAdmin admin@upkiller.com      //管理员邮件
         ServerName   upkiller.com     //域名
         ServerAlias www.upkiller.com       //别名
         DocumentRoot /var/www/extsuite/extmail/html //网站目录
         ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgi   //脚本执行别名
         Alias        /extmail   /var/www/extsuite/extmail/html     //别名
         ScriptAlias /extman/cgi /var/www/extsuite/extman/cgi
         Alias        /extman /var/www/extsuite/extman/html
         SuexecUserGroup postfix postfix               //切换到postfix帐户运行
        <Directory /var/www/extsuite>         //目录权限
        Options Indexes FollowSymLinks        //允许符号链接,访问不在本目录下的文件
        AllowOverride None                    //禁止读取.htaccess
        Order allow,deny                      //指定先执行Allow访问规则,再执行Deny访问规则
        Allow from all                        //允许访问所有
        </Directory>
</VirtualHost>

——————————————————————————
安装extman的图形日志:

1,在首先在http://search.cpan.org
搜索:Time::HiRes和File::Tail:并下载
http://oss.oetiker.ch/rrdtool/pub/?M=D 下载rrdtool-1.2.23.tar.gz

安装Time::HiRes
tar zxvf Time-HiRes-1.9707.tar.gz
cd Time-HiRes-1.9707
perl Makefile.PL
make
make test
make install

安装File::Tail
tar zxvf File-Tail-0.99.3.tar.gz
cd File-Tail-0.99.3
perl Makefile.PL
make
make test
make install

安装rrdtool-1.2.23
tar zxvf rrdtool-1.2.23.tar.gz
cd rrdtool-1.2.23
(需要libart_lgpl-devel,libpng-devel,tcl-devel,freetype,libpng)

./configure –prefix=/usr/local/rrdtool
make
make install
(如果出現 make[3]: *** [tclrrd.o] 错误 1
make[3]: Leaving directory `/home/cacti/rrdtool-1.2.10/bindings/tcl’
make[2]: *** [all-recursive] 错误 1
make[2]: Leaving directory `/home/cacti/rrdtool-1.2.10/bindings’
make[1]: *** [all-recursive] 错误 1
make[1]: Leaving directory `/home/cacti/rrdtool-1.2.10′
make: *** [all] 错误 2
可以./configure –prefix=/usr/local/rrdtool \
–disable-tcl
也可以
rrdtool-1.2.10 的安裝
# declare
export BUILD_DIR=/tmp/rrdtool

# Install cgilib
cd cgilib-0.5
make CC=gcc CFLAGS=”-O3 -fPIC -I.”
mkdir -p $BUILD_DIR/lb/include
cp *.h $BUILD_DIR/lb/include
mkdir -p $BUILD_DIR/lb/lib
cp libcgi* $BUILD_DIR/lb/lib

# Install zlib
cd zlib-1.2.2
env CFLAGS=”-O3 -fPIC” ./configure –prefix=$BUILD_DIR/lb
make
make install

# Install libpng
cd libpng-1.2.8-config
env CPPFLAGS=”-I$BUILD_DIR/lb/include” LDFLAGS=”-L$BUILD_DIR/lb/lib” CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install

# Install freetype
cd freetype-2.1.9
env CPPFLAGS=”-I$BUILD_DIR/lb/include” LDFLAGS=”-L$BUILD_DIR/lb/lib” CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install

## Install libart_lgpl
cd libart_lgpl-2.3.17
env CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install

# Install rrdtool
cd rrdtool-1.2.10
IR=-I$BUILD_DIR/lb/include
CPPFLAGS=”$IR $IR/libart-2.0 $IR/freetype2 $IR/libpng”
LDFLAGS=”-L$BUILD_DIR/lb/lib”
CFLAGS=-O3
export CPPFLAGS LDFLAGS CFLAGS
./configure prefix=/usr/local/rrdtool –disable-tcl
make
make install)
错误:I found a copy of pkgconfig, but there is no freetype2.pc
cd /usr/src/freetype-2.2.1
find . -name “*.pc
cp builds/unix/freetype2.pc /usr/lib/pkgconfig/
复制mailgraph_ext到/usr/local,并启动之
cp -r /var/www/extsuite/extman/addon/mailgraph_ext   /usr/local  
/usr/local/mailgraph_ext/mailgraph-init   start

启动报错:
Can’t locate RRDs.pm in @INC…..
解决方法:
find /usr -name “RRDs.pm”
ln -sv /usr/local/rrdtool/lib/perl/5.8.5/i386-linux-thread-multi/RRDs.pm    /usr/lib/perl5/5.8.5

再启动:
Can’t locate loadable ojbect for module RRDs
解决:
ln -sv /usr/local/rrdtool/lib/perl/5.8.5/i386-linux-thread-multi/auto/RRDs/RRDs.so    /usr/lib/perl5/5.8.5/i386-linux-thread-multi/

再启动ok
(如果碰到少别的模块都可以用查找链接这种方法解决,找不到就是没安装咯,一个是pm模块,一个是so库)
/usr/local/mailgraph_ext/qmonitor-init   start //启动ok

打开extman后台管理,打开图形日志,没报错就ok啦。

再加入开机启动:

echo “/usr/local/mailgraph_ext/mailgraph-init start” >> /etc/rc.local

———————————————————————–
Extman FAQ:

1,extman默认登录密码:

默认管理帐号为:root@extmail.org   密码为:extmail*123*

2,第一次配置好extmail打开浏览器提示:
Unix::Syslog not found, please install it first! (in cleanup) Undefined subroutine &Ext::Logger::do_closelog called at /var/www/extsuite/extmail/libs/Ext/Logger.pm line 87.
没装perl-Unix-Syslog包,
安装perl-Unix-Syslog-0.100-1hzq.i386.rpm搞定

或是到http://search.cpan.org搜索Syslog下载一个Unix-Syslog-0.100.tar.gz
tar zxvf Unix-Syslog-0.100.tar.gz
cd Unix-Syslog-0.100
perl Makefile.PL
make
make install

3,install_driver(mysql) failed: Can’t locate DBD/mysql.pm in
搜索DBD-mysql-4.005.tar.gz下载,安装,结果提示如下

4,之后提示Internal Server Error:
tail -f error_log
/usr/bin/perl: symbol lookup error: /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/auto/DBD/mysql.so: undefined symbol: DBIc_TRACE_LEVEL

//肯定是DBD-MYSQL版本不兼容问题:
find /usr/lib -name “mysql.so” -exec rm {} \;

http://search.cpan.org/dist/DBD-mysql/下载:DBD-mysql-3.0002_4.tar.gz
perl Makefile.PL
make
make install
(再打开ok)

如果还是显示内部服务器错误,apache的error_log还提示:
suexec policy violation: see suexec log for more details
Premature end of script headers: index.cgi
提示查看su日志:
———————————-
关于suexec的FAQ
1.出现以下错误   command not in docroot
编译的时候加入–with-suexec-docroot     以后虚拟主机运行suexec的目录必须包含指定的目录里,通过suexec -V 可以察看docroot目录是哪儿

2.出现以下错误   user mismatch (daemon instead of www)
编译的时候加入–with-suexec-caller=daemon   默认是www,但一般apache的运行用户是nobody或者daemon,这里我们是httpd2.2.2,用户是daemon,所以指定这个参数,否则suexec不能被运行。

3.出现以下错误   cannot run as forbidden uid (1001/index.cgi)
在虚拟主机配置SuexecUserGroup时,指定的用户和组,必须高于–with-suexec-uidmin –with-suexec-gidmin 指定的用户uid和gid,否则被限制使用。
————————————————
编译Apache的时候要加上:
   –enable-suexec \                     
   –with-suexec-caller=daemon \
   –with-suexec-docroot=/var/www/extsuite/

临时用postfix,再去su:

5,又提示:DBI connect(’database=extmail;host=localhost;mysql_socket=/var/lib/mysql/mysql.sock’,
‘extmail’,…)failed: Can’t connect to local MySQL server

vi /var/www/extsuite/extmail/webmail.cf
改:SYS_MYSQL_SOCKET = /tmp/mysql.sock
vi /var/www/extsuite/extman/webman.cf (同上)
(再打开ok)

6,Can’t open /tmp/extman//sid_8519f707216994462c48dcd98b655843, No such file or directory
mkdir /tmp/extman
chown -R postfix:postfix /tmp/extman

 

7,进入extman无法显示校验码图片:
tail -f error_log
BEGIN failed–compilation aborted at /var/www/extsuite/extman/libs/Ext/GD.pm line 14

http://search.cpan.org/~lds/GD-2.35/

perl Makefile.PL
提示gd装在哪/usr/local/gd2/lib
(选图片支持)

Where is libgd installed? [/usr/lib] /usr/local/gd2

Build JPEG support? [y] y
Build PNG support? [y] y
Build FreeType support? [y] y
Build GIF support? [y] y
Build support for animated GIFs? [y] y
Build XPM support? [y] n
make
make install
错误:cannot find -lpng
ln -vs /usr/local/libpng2/lib/* /usr/lib
错误:cannot find -lfreetype
ln -vs /usr/local/freetype2/lib/* /usr/lib
错误:cannot find -ljpeg
ln -vs /usr/local/jpeg6/lib/* /usr/lib
再重新make clean
perl Makefile.PL (成功)

或是:
extman登录不要校验码:
在 webman.cf 将 SYS_CAPTCHA_ON=0 即可,要重启 Apache
8,新建两个域,各建帐号测试发信:
测试帐号和密码是否正常:
/usr/local/courier-authlib/sbin/authtest user1@rohto.com.cn user1
变更密码;
./authtest -s localhost user1@rohto.com.cn user user1

 

错误FAQ:Can’t chdir to /var/mailbox/rohto.com.cn/user1/Maildir/, No such file or directory
查看extman的:
SYS_MAILDIR_BASE = /var/mailbox
配置是否正确,删除域名再重建,在新建用户的时候会自动在/var/mailbox/下创建该用户的域名和邮件目录
登入extmail进行各种发信测试:

发给自己
发给同域帐号
发给不同域帐号
发给163收信
用163收信给自己

再使用outlook/foxmail进行如上测试:

———————————-
通过日志分析发信过程:
tail -f /var/log/maillog
成功的日志如下:
postfix/pickup[2215]: 5705EA885D: uid=255 from=<user1@upkiller.com>
postfix/cleanup[3267]: 5705EA885D: message-id=<20070922224616.5705EA885D@mail.upkiller.com>
postfix/qmgr: 5705EA885D: from=<user1@upkiller.org>, size=515,nrcpt=1 (queue active)
postfix/virtual[3271]: 5705EA885D: to=<upkiller@163.org>, relay=mx.mail.163.split.netease.com ,delay=0.13,delays=
0.1/0.02/0.0.01,dsn=2.0.0,status=send (delivered to maildir)
postfix/qmgr[2214]: 5705EA885D: removed

发信错误FAQ:

1,不能发送邮件:
warning: do not list domain upkiller.com in BOTH mydestination and virtual_mailbox_domains
明显是指这个域名不在mydestination许可的列表

解决方法:
在有多域的服务器上直接把mydestination选项在/etc/postfix/main.cf注释掉:
2,虚拟域不能发送邮件给自己:
Sep 28 14:01:10 rohto postfix/local[2377]: 07AC332E69: to=<user2@xxxx.com.cn>, relay=local, delay=0.71, delays=0.41/0.16/0/0.14, dsn=5.1.1, status=bounced (unknown user: “user2″)

1)首先确定:
extman/webman.cf文件中:
SYS_DEFAULT_GID = 2525
修改后进入/var/mailbox/domain.com.cn中rm -rf *

2)原来是在main.cf文件中myhostname与mydomain不能一样,要不然
虚拟域和main.cf中设的域名一样就会出现问题:(kao)

myhostname = xxx.com.cn
mydomain = xxxx.com.cn
修改如下:
myhostname = mail.xxx.com.cn
mydomain = xxxx.com.cn
3,两台extmail互发邮件拒绝:
Recipient address rejected: Try again, see http://bl.extmail.org/cgi/why?greylist (in
reply to RCPT TO command)

//接收地址拒绝,再次尝试,查看http://bl.extmail.org/cgi/why?greylist

上面的解释:
您的主机将被greylist临时封锁 (300 秒

这是您第一次发信给收件人,请隔一段时间重试
前后两次发信间隔小于阀值 (300秒)

等待300秒再发送,没有问题。
解决办法:
修改:/usr/local/slockd/config/whitelist

4,无法向其它服务器发送邮件提示:

Host or domain name not found. Name service error for name=163.com type=MX: Host not found, try again
mail服务器resolv.conf未设好

5,向163发信提示:

http://mail.163.com/help/help_spam_16.htm (in reply to end of DATA command)
反病毒

反垃圾
————————————
小技巧:

1,反解不存在的机器将被拦截:
smtpd_client_restrictions = reject_unknown_client ( 如果是postfix 2.3或以上,则是reject_unknown_client_hostname)

2,日志分析技巧:

1)postfix日志成功接收到邮件:(交货到邮件目录)
cat /var/log/maillog |grep “delivered to maildir”
cat /var/log/maillog |grep “delivered to maildir” | egrep -o “(\w+)([@]{1}\w+[.]{1,})(\w+)”

2)取当天日志:
cat /var/log/maillog | egrep “`data | awk “`’{print “”$2″ “$3″”}’`”

3)取指定日期的错误日志:
cat /var/log/maill | grep “^Sep\ 25″ | egrep “reject|warning|error|fatal|panic” | more

C语言笔记 指针类型转换

我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋
值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指
针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向
的类型是一样的。
例十四:
1。 float f=12.3;
2。 float *fptr=&f;
3。 int *p;
在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的
语句吗?
p=&f;
不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一
个指针,指针的类型是float*,它指向的类型是float。两者不一致,直接赋值的
方法是不行的。至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类
型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了
实现我们的目的,需要进行“强制类型转换”:
p=(int*)&f;
如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*和TYPE,
那么语法格式是:
(TYPE*)p;
这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的
类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都
没有被修改。一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结
合过程中,也会发生指针类型的转换。
例十五:
void fun(char*);
int a=125,b;
fun((char*)&a);


void fun(char*s)
{
char c;
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;
}
}
注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函
数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用
语句中,实参&a的结果是一个指针,它的类型是int *,它指向的类型是int。形
参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过
程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可
以这样来想象编译器进行转换的过程:编译器先构造一个临时指针 char*temp,
然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的
类型是char*,它指向的类型是char,它指向的地址就是a的首地址。

我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其
实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象
下面的语句:
unsigned int a;
TYPE *ptr;//TYPE是int,char或结构类型等等类型。


a=20345686;
ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制

ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制)
编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到
了吗?不,还有办法:
unsigned int a;
TYPE *ptr;//TYPE是int,char或结构类型等等类型。


a=某个数,这个数必须代表一个合法的地址;
ptr=(TYPE*)a;//呵呵,这就可以了。
严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYP
E*)的意思是把无符号整数a的值当作一个地址来看待。
上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候
,就会出现非法操作错误。

想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完
全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个
整数当作一个地址赋给一个指针:
例十六:
int a=123,b;
int *ptr=&a;
char *str;
b=(int)ptr;//把指针ptr的值当作一个整数取出来。
str=(char*)b;//把这个整数的值当作一个地址赋给指针str。

好了,现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以
把一个整数值当作地址赋给一个指针。

 

其他相关资料:

#pragma src

#i nclude <reg51.H>
f(){}
f1(){}
f2(){}

main()
{
    {
        int x;
        int *px;

        //下面这些表示虽然很烦,但是生成的代码却及其简洁:

        //将 xdata 型指针 0×4000 赋给 px
        px=(int xdata *)0×4000;

        //表示从 xdata 0×4000处取一个 char 给x
        x=*((char xdata *)0×4000);

        // 表示从 code 0×4000处取一个 word 作为 xdata 型的指针 给
px
        px=*((int xdata * xdata *)0×4000);

        //表示从 code 0×4000处取一个 word 作为 xdata 型的指针,
        //再把这个指针指向的char数据赋给x
        x=**((char xdata * code *)0×4000);

        //表示把函数f()入口地址当作xdata型指针,再把指向的xdata
        //中的int型数据作为code型指针,把指向的code字节
        //赋给x(晕,这样有意义吗?)
        x=**(int code * xdata *)f;

        //把f()入口地址处的ROM中两个code型字节,
        //赋给堆栈指针SP指向的字节(想干什么?编操作系统?)
        *(unsigned int idata *)SP=*(unsigned int code *)&f;

        //表示把f()入口地址处的ROM中两个code型字节,
        //作为一个xdata指针寻址,
        //把指向的数据作为pdata指针寻址,
        //再把把指向的数据作为idata指针寻址,
        //把该地址处的一个字节赋给x (我靠,累死了)
        x= ****(unsigned int data * idata * pdata * xdata * code
*)&f;
       
        //总之,一个括号里面外面的”*”一样多就表示指向的是数据。
    }

    {
        //数组函数
        code void (*ArrFn[])(void) =
        {    &f1,
            &f2,
        };
        //可以像引用数组一样调用函数啦:
        (*ArrFn[0])();
        (*ArrFn[1])();
    }

    {
        //这样将使函数调用0000H处:
        void (*reset) (void);
        reset=0×0;
        (*reset)();
        reset();

        //或者直接这样,仅仅生成一条指令LCALL 1234H
        ((void (code *)(void))0×1234)();
    }

    {
        //这样可以调用RETI指令:
        #define  INT_NUM  30    //空闲中断号
        ((void (code *)(void))(INT_NUM*8+3))();
        //当然需要在外面声明   int_rpt()interrupt INT_NUM {}
    }
    {
        //这样调用RETI指令太变态:
        code unsigned char ret_i=0×32;
        ((void (code *)(void))(&ret_i))();
    }
}
int_rpt()interrupt INT_NUM {}

 

字节对齐

VC字节对齐全攻略

VC中下面几个结构体大小分别是多少呢
struct MyStruct
{
    double m4;
    char m1;
    int  m3;
};

struct MyStruct {
    char m1;
    double m4;
    int m3;
};

#pragma pack(push)//保存对齐状态
#pragma pack(16)  //设置为16字节对齐
struct test
{
   char m1;
   int m3; 
   double m4;    
};
#pragma pack(pop)//恢复对齐状态
如果你的答案不是16,24和16,相信下面的内容对你很有帮助。

1、 sizeof应用在结构上的情况
请看下面的结构:
struct MyStruct
{
double dda1;
char dda;
int type
};
对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?也许你
会这样求:
sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。你知道为什
么在VC中会得出这样一个结果吗?
其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的
起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结
构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的
对齐方式(vc6.0,32位系统)。
类型      对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
Char      偏移量必须为sizeof(char)即1的倍数
Short     偏移量必须为sizeof(short)即2的倍数
int   偏移量必须为sizeof(int)即4的倍数
float 偏移量必须为sizeof(float)即4的倍数
double 偏移量必须为sizeof(double)即8的倍数
各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对
齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边
界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员
变量申请空间后,还会根据需要自动填充空缺的字节。
下面用前面的例子来说明VC到底怎么样来存放结构的。
struct MyStruct
{
double dda1;
char dda;
int type
};
为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个
成员dda1分配空间,其起始地址跟结构的起始地址相同(刚好偏移量0刚好为sizeof(doub
le)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空
间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数
,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用 sizeof(char)=1个字
节;接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址
的偏移量为9,不是sizeof (int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自
动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起
始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方
,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总
的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的
类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整
个结构的大小为:sizeof(MyStruct)=8+1+ 3+4=16,其中有3个字节是VC自动填充的,没有
放任何有意义的东西。
下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况

struct MyStruct
{
char dda;
double dda1;
int type
};
这个结构占用的空间为多大呢?在VC6.0环境下,可以得到sizeof(MyStruc)为24。结
合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。(简单说
明)
struct MyStruct
{
char dda;//偏移量为0,满足对齐方式,dda占用1个字节;
double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8
//的倍数,需要补足7个字节才能使偏移量变为8(满足对齐
//方式),因此VC自动填充7个字节,dda1存放在偏移量为8
//的地址上,它占用8个字节。
int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍
//数,满足int的对齐方式,所以不需要VC自动填充,type存
//放在偏移量为16的地址上,它占用4个字节。
};//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构
//的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof
//(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为
//sizeof(double)=8的倍数。
所以该结构总的大小为:sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节
是VC自动填充的,没有放任何有意义的东西。
VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻
烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
VC 中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存
放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏
移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移
量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况
:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的
变量占用的空间数的倍数;

否则必须为n的倍数。下面举例说明其用法。
#pragma pack(push) //保存对齐状态
#pragma pack(4)//设定为4字节对齐
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢复对齐状态

以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足
我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为 m4分配空间,这时
其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大
于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用
4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如
果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。
(请读者自己分析)

2、 sizeof用法总结

在VC中,sizeof有着许多的用法,而且很容易引起一些错误。下面根据sizeof后面的
参数对sizeof的用法做个总结。
A.参数为数据类型或者为一般变量。例如sizeof(int),sizeof(long)等等。这种情
况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的。例如int类型在16位
系统中占2个字节,在32位系统中占4个字节。
B. 参数为数组或指针。下面举例说明.
int a[50]; //sizeof(a)=4*50=200; 求数组所占的空间大小
int *a=new int[50];// sizeof(a)=4; a为一个指针,sizeof(a)是求指针
//的大小,在32位系统中,当然是占4个字节。
C.参数为结构或类。Sizeof应用在类和结构的处理情况是相同的。但有两点需要注
意,第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存
储位置与结构或者类的实例地址无关。
第二、没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一
个实例在内存中都有唯一的地址。
下面举例说明,
Class Test{int a;static double c};//sizeof(Test)=4.
Test *s;//sizeof(s)=4,s为一个指针。
Class test1{ };//sizeof(test1)=1;
D. 参数为其他。下面举例说明。
int func(char s[5]);
{
cout< //数的参数在传递的时候系统处理为一个指针,所
//以sizeof(s)实际上为求指针的大小。
return 1;
}
sizeof(func(“1234”))=4//因为func的返回类型为int,所以相当于
//求sizeof(int).
以上为sizeof的基本用法,在实际的使用中要注意分析VC的分配变量的分配策略,这
样的话可以避免一些错误