﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-xiaoguozi's Blog-随笔分类-学习笔记</title><link>http://www.cppblog.com/guojingjia2006/category/5747.html</link><description>Pay it forword - 我并不觉的自豪，我所尝试的事情都失败了······习惯原本生活的人不容易改变，就算现状很糟，他们也很难改变，在过程中，他们还是放弃了······他们一放弃，大家就都是输家······让爱传出去，很困难，也无法预料，人们需要更细心的观察别人，要随时注意才能保护别人，因为他们未必知道自己要什么·····</description><language>zh-cn</language><lastBuildDate>Tue, 03 Sep 2013 08:27:24 GMT</lastBuildDate><pubDate>Tue, 03 Sep 2013 08:27:24 GMT</pubDate><ttl>60</ttl><item><title>Nagios插件编写及调试方法</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/09/03/202981.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 03 Sep 2013 01:39:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/09/03/202981.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/202981.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/09/03/202981.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/202981.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/202981.html</trackback:ping><description><![CDATA[<div><p style="text-indent: 2em">前言：  Nagios是相当不错的监控工具，被称作是&#8220;监控之神&#8221;，但同样也有&#8220;难搞死&#8221;头衔。发挥Nagios一切魅力的都是他的插件，正因为丰富多样的插件让 nagios有血有肉。监控的内容不断在变化，插件也不断变化，默认的一些插件可能越来越不能满足需求，这个时候就要自己来写些插件了。</p> <p style="text-indent: 2em">以下就是用我的第一个Nagios插件来说明编写方法和我遇到一些问题调试方法。如果你有耐心可以通篇看完，应该对第一次写的人来说会有很大帮助（如果你看不懂，可能是我写得不清楚 那就没办法了 表达能力有限）</p> <p style="text-indent: 2em">需求：</p> <p style="text-indent: 2em">监控普通磁盘的健康状况（普通磁盘以外还有RAID、阵列的监控是不同方法来做的，这里先不讨论，先从最简单的入手），定期进行检测，并进行报警，报警内容磁盘是否正常，不正常是什么状态。</p> <p style="text-indent: 2em">分析编写过程：</p> <p style="text-indent: 2em">我写脚本的前提都是先从手动成功完成，再到自动化（我想其它人的思路应该都一样的）</p> <p style="text-indent: 2em">1、找到监控磁盘的方法</p> <p style="text-indent: 2em">通过一番查找 smartctl 这个命令是比较不错的&nbsp; centos slackware一般的默认都有这个</p> <p style="text-indent: 2em">smartctl -H /dev/sda&nbsp; 只检测状态</p> <p style="text-indent: 2em">smartctl -i /dev/sda&nbsp;&nbsp; 只检测硬盘信息</p> <p style="text-indent: 2em">smartctl -a /dev/sda 检测所有信息</p> <p style="text-indent: 2em">2、获取检测信息</p> <p style="text-indent: 2em"># smartctl -H /dev/sda</p> <p style="text-indent: 2em">smartctl version 5.38 [x86_64-redhat-linux-gnu] Copyright (C) 2002-8 Bruce Allen</p> <p style="text-indent: 2em">Home page is http://smartmontools.sourceforge.net/</p> <p style="text-indent: 2em">SMART Health Status: OK</p> <p style="text-indent: 2em">关键的最后一行说明磁盘的情况 &nbsp; &nbsp; &nbsp; 截取&nbsp; DISK_HEALTH=`smartctl -H /dev/sda | tail -1 | cut -d: -f2-&nbsp; `</p> <p style="text-indent: 2em">3、 进行关键判断</p> <p style="text-indent: 2em">据我所知道的 smartctl 5.38&nbsp; 是出以上的結果 为OK</p> <p style="text-indent: 2em">而 smartctl 5.39 是出以下結果</p> <p style="text-indent: 2em">=== START OF READ SMART DATA SECTION ===</p> <p style="text-indent: 2em">SMART overall-health self-assessment test result: PASSED</p> <p style="text-indent: 2em">关键词是PASSED</p> <p style="text-indent: 2em">所以要分析判断多种情况</p> <p style="text-indent: 2em">4、脚本编写步骤</p> <p style="text-indent: 2em">1）了解nagios插件编写规范</p> <p style="text-indent: 2em">Nagios的插件可以用脚本（shell、Perl）C编译后的可执行程序，但必须满足以下两件事：</p> <p style="text-indent: 2em">A、既出时有一个返回值</p> <p style="text-indent: 2em">B、至少向标准输出设备（STDOUT）输出一行文件。（但也不能太大，默认是4K，如果想大些，修改源程序吧，方法搜。) </p> <p style="text-indent: 2em">返回值定义：</p> <p style="text-indent: 2em">Plugin Return Code Service State DISK State <br />0 OK OK 或者PASSED <br />1 WARNING 插件警告&nbsp; DISK报警只分OK或者CRITICAL <br />2 CRITICAL&nbsp; DISK检测非OK 或者PASSED <br />3 UNKNOWN&nbsp; 未知状态 </p> <p style="text-indent: 2em">2)插件编写SHELL速成法</p> <p style="text-indent: 2em">在这里我选用我最熟悉的SHELL进行脚本编写 ,</p> <p style="text-indent: 2em">我的速成法就是，直接去nagios exchange 去下比较成熟的比较简单的shell脚本，这样会从一开始借鉴别人好的方法，养成好的习惯，而且只要你有一点SHELL编程经验也可以很快写得像一个老手。（不过不要把自己搞晕了就行）</p> <p style="text-indent: 2em">3）以下是我的check_disk_health.sh</p> <p style="text-indent: 2em">#!/bin/bash<br /># ========================================================================================<br /># disk health&nbsp; plugin for Nagios<br />#<br /># Written by&nbsp;&nbsp;&nbsp; : Ajian<br /># Release&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 1.2.0<br /># Creation date : 2009-07-28<br /># Revision date : 2009-07-30<br /># Description&nbsp;&nbsp; : Nagios plugin (script) to check disk health .<br />#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This script has been designed and written on Linux System.<br />#<br /># USAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : ./check_disk_health.sh [-d (disk)]<br />#<br /># Exemple: ./check_cpu_stats.sh<br />#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./check_cpu_stats.sh -d /dev/sda<br />#<br />#<br /># HISTORY :<br />#&nbsp;&nbsp;&nbsp;&nbsp; Release&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; Authors&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Description<br /># --------------+---------------+----------------------+-----------------------------------<br />#&nbsp; 1.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 2009-07-28&nbsp;&nbsp;&nbsp;&nbsp; | Ajian&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Create the script<br />#&nbsp; 1.2.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 2009-07-30&nbsp;&nbsp;&nbsp; |&nbsp; Ajian&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | modify the script and run well ,fix a bug.<br /># -----------------------------------------------------------------------------------------<br /># NOTICE:<br />#-----------------------------------------------------------------------------------------<br />#&nbsp;&nbsp;&nbsp;&nbsp; You should have the root Permissions ,You can use sudo to realize .<br /># -----------------------------------------------------------------------------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br /># Nagios return codes<br />#定义 nagios返回的状态变量<br />STATE_OK=0<br />STATE_WARNING=1<br />STATE_CRITICAL=2<br />STATE_UNKNOWN=3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br /># Paths to commands used in this script.&nbsp; These may have to be modified to match your system setup.<br /># 定义关键的核心命令smartctl 路径 如果你的系统不是这个地址，请更改。 以下注释的是调试的信息，是自动获取命令路径的方法。<br />SMARTCTL="/usr/sbin/smartctl"<br />#SMARTCTL=`which smartctl`<br />#if [ $? -ne 0 ]; then<br />#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo " smartctl is found in $SMARTCTL ; Go on ... "<br />#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "smartctl the command cannot find"<br />#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_UNKNOWN<br />#fi<br /># Plugin parameters value if not define<br /># 定义默认的检测硬盘<br />CHECK_DISK="/dev/sda"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br /># Plugin variable description<br /># 插件描述信息<br />PROGNAME=$(basename $0)<br />RELEASE="Revision 1.2.0"<br />AUTHOR="(c) 2009 Ajian ()"<br />&nbsp;<br /># Functions plugin usage<br /># 插件的使用方法函数<br />print_release() {<br />&nbsp;&nbsp;&nbsp; echo "$RELEASE $AUTHOR"<br />}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />print_usage() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "$PROGNAME $RELEASE - Disk health check script for Nagios"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "Usage: check_disk_health.sh -d /dev/sdb"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "&nbsp; -d&nbsp; the disk (/dev/sda) "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; not the Hard disk partition(sda2 is wrong)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "&nbsp; -v&nbsp; check the version"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "&nbsp; -h&nbsp; Show this page"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp; echo "Usage: $PROGNAME"<br />&nbsp;&nbsp;&nbsp; echo "Usage: $PROGNAME --help"<br />&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp; exit 0<br />}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br />print_help() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_usage<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "This plugin will check disk health&nbsp; "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo ""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit 0<br />}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;<br /># Parse parameters<br /># 传递参数<br />while [ $# -gt 0 ]; do<br />&nbsp;&nbsp;&nbsp; case "$1" in<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -h | --help)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_help<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_OK<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -v | --version)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_release<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_OK<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -d | --disk)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shift<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CHECK_DISK=$1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #判断磁盘是否存在<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if [ ! -b $CHECK_DISK ];then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "$CHECK_DISK is no exsit,Please change it "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_CRITICAL<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *)&nbsp; echo "Unknown argument: $1"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_usage<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_UNKNOWN<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esac<br />shift<br />done<br />&nbsp;<br />＃根据不同的操作进行不同的操作，这里暂时只支持Linux<br />case `uname` in<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Linux )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #最核心的部分 前面都是些脚本的基本功能 一个框架 因为第一个脚本牵扯到了很多东西，虽然功能很简单，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #但折腾了我不少，在后面的分析中会具体说到 总之注意sudo用法 脚本一开始就有说哦<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DISK_HEALTH=`$SMARTCTL&nbsp; -H $CHECK_DISK | tail -1 | cut -d: -f2- `<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #DISK_HEALTH="OK"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DISK_INFO=`/usr/bin/sudo $SMARTCTL -i $CHECK_DISK | grep "Device:"`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if [ "$DISK_HEALTH" = " OK" ]|| [&nbsp; "$DISK_HEALTH" = " PASSED" ];then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "OK - $CHECK_DISK status is $DISK_HEALTH "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #echo "OK - $CHECK_DISK status is $DISK_HEALTH | $DISK_INFO"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_OK<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "CRITICAL - $CHECK_DISK status is $DISK_HEALTH "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #echo "CRITICAL - $CHECK_DISK status is $DISK_HEALTH | $DISK_INFO"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_CRITICAL<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fi<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo "UNKNOWN: `uname` not yet supported by this plugin. Coming soon !"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit $STATE_UNKNOWN<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esac4)运行脚本</p> <p style="text-indent: 2em">（注意：在最开始自己写的脚本是没有sudo的，以上脚本是已经调试过后的，还需要配置一些其它的东西，慢慢看吧）<br />给与脚本执行权限，手动执行</p> <p style="text-indent: 2em"># ./check_disk_health.sh<br />OK &#8211; /dev/sda status is&nbsp; OK</p> <p style="text-indent: 2em">結果正确了，其实这个时候，高兴得太早了。 我先不说问题、继续正常的一般流程。</p> <p style="text-indent: 2em">5、配置Nagios 调用插件</p> <p style="text-indent: 2em">1）在远程NRPE 被监控服务器上修改nrpe.conf<br /># vim /usr/local/nagios/etc/nrpe.cfg<br />添加 command[check_sda_health]=/usr/local/nagios/libexec/check_disk_health.sh -d /dev/sda<br />（注意这里了，先提醒下，这里是错误的，一般是正确的，是这个脚本的特殊性造成的）</p> <p style="text-indent: 2em">2）在Nagios 监控服务器上添加一些配置</p> <p style="text-indent: 2em">定义服务</p> <p style="text-indent: 2em">define service{<br />use&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Disk-Health<br />host_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DB-56<br />servicegroups&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Disk-Health<br />service_description&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; check sda disk health<br />contact_groups&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; admins<br />check_command&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; check_nrpe!check_sda_health<br />}<br />如果像上面定义一个服务 那么就要注意相关的定义了 ，<br />定义Disk-Health 模版&nbsp; 把硬盘检测定义一个模版会比较好控制，因为硬盘的检测不像其它服务一样需要准确的及时性反正检测得太多可能会造成压力，一般一天检测几次就够了。<br />定义DB-56 主机需要定义<br />定义组 admins<br />以上这些只要安装过nagios 一般都知道的了 只是强调下模版的单独定义</p> <p style="text-indent: 2em">3)通过WEB控制检测 查看結果</p> <p style="text-indent: 2em">結果是失败 报警CRITCTL 但是状态里面的信息都是空的&nbsp; CRITCTL &#8211; /dev/sda status is</p> <p style="text-indent: 2em">6、调试</p> <p style="text-indent: 2em">从Nagios的远程监控来看是失败的，并且没有获取到任务有用的信息。</p> <p style="text-indent: 2em">分析可以看到，说明nrpe调用&nbsp; 这个变量获取到的是为空的信息<br />DISK_HEALTH=`$SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `<br />即是空的 只有一个原因，肯定是没有执行 如果执行了 肯定会有字段 不管这个字段是否相符。<br />但是手动执行是没有问题。<br />经过对smartctl的查看 原来这个命令是只允许root进行调用的。<br />现在需要解决的问题是：非root 用户 如何远程调用含有需要有root权限命令的脚本进行监控。<br />（不要小看这一句话，每一个词都是一个需要攻克的地方）<br />以下是调试步骤：<br />1）非root用户<br />NRPE插件是用nagios这个用户来执行的 所以要得到真实的情况需要<br />A： su nagios&nbsp;&nbsp; 再执行脚本 (这个方法比较好)<br />B： sudo -u nagios ./check_disk_health.sh<br />結果：</p> <p style="text-indent: 2em">sudo -u nagios ./check_disk_health.sh<br />CRITICAL &#8211; /dev/sda status is<br />跟远程的結果是一样的了 没有信息<br />2）需要有root权限<br />需要root权限只有一个办法就是用sudo<br />将DISK_HEALTH=`$SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `<br />改为DISK_HEALTH=`/usr/bin/sudo $SMARTCTL -H $CHECK_DISK | tail -1 | cut -d: -f2- `<br />（最后发现这时加sudo 并不是关键 关键是很行脚本时用sudo ）<br />結果：sudo -u nagios ./check_disk_health.sh<br />Password:<br />需要输入密码&nbsp; sudo不用输入密码的方法<br />修改sudo配置文件<br />执行 visudo<br />添加<br />nagios ALL=(ALL) NOPASSWD:/usr/local/nagios/libexec/check_disk_health.sh<br />建议：最好进行sudo的一些控制，很多网方法就是nagios ALL=NOPASSWD:ALL<br />结果：<br />su nagios<br />/usr/bin/sudo check_disk_health.sh<br />OK &#8211; /dev/sda status is OK<br />那么在nrpe.conf配置文件中需要添加sudo<br />command[check_sda_health]=/usr/bin/sudo /usr/local/nagios/libexec/check_disk_health.sh<br />最开始那个是错误的 注意啊 这个是需要添加/usr/bin/sudo 就是说只要脚本中涉及到提升到root权限的命令那么就要用这个<br />3）远程调用<br />远程调用方法：./check_nrpe -H 192.168.0.56 -c check_sda_health<br />同上如果想模拟真实环境请切换到相应的执行用户 su nagios 再执行以上操作<br />结果：&nbsp;&nbsp; NRPE: Unable to read output<br />这个错误的原因一定要明白，之所以报这个错意思是说NRPE没有获取到任何信息，也说是写脚本之前说的其中第二条规范<br />问题：在没有任何信息的情况下怎么来获取NRPE执行的日志呢<br />就是要确定问题在哪，经过一大番的查找眼睛偶尔看到一个有趣的小方法<br />修复nrpe.conf配置文件 在要检查的命令后面添加&gt;&gt;/tmp/output 2&gt;&amp;1 将错误导出到文件中进行查看<br />command[check_sda_health]=/usr/bin/sudo  /usr/local/nagios/libexec/check_disk_health.sh -d /dev/sda  &gt;&gt;/tmp/output 2&gt;&amp;1<br />重记nrpe服务<br />远程调用 结果当然还是NRPE: Unable to read output<br />查看/tmp/output<br />sudo: sorry, you must have a tty to run sudo<br />有错误就简单了&nbsp; 原来这个是默认不允许sudo 在后端进行<br />visudo<br />注释Defaults requiretty 就OK了<br />结果通过WEB查看也正确了。<br />(注意：注释后 检测仍然会是Unable 不过看/tmp/output就会有正确的結果，所以有正确的結果后，一定要去掉 &gt;&gt;/tmp/outpt 2&gt;&amp;1 信息都导到文件中了 nagios还是得不到任何消息。)</p> <p style="text-indent: 2em">一个脚本执行成功后，就是大批量应用，用生产环境验证，出现问题继续调试。</p> 以上为所有的分析调试方法。如果你看到最后一步了，说明你很有耐心，你也一定会成功的，至于写得好与坏、对与错请尽管说，这不会影响你的成功。呵呵。</div>转自:<div>http://blog.chinaunix.net/uid-20592013-id-2436813.html</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/202981.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-09-03 09:39 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/09/03/202981.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下Nagios的安装与配置</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/09/02/202946.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 02 Sep 2013 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/09/02/202946.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/202946.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/09/02/202946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/202946.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/202946.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、Nagios简介  　　Nagios是一款开源的电脑系统和网络监视工具，能有效监控Windows、Linux和Unix的主机状态，交换机路由器等网络设置，打印机等。在系统或服务状态异常时发出邮件或短信报警第一时间通知网站运维人员，在状态恢复后发出正常的邮件或短信通知。 　　Nagios原名为NetSaint，由Ethan Galstad开发并维护至今。NAGIOS是一个缩写形式: "Nagio...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2013/09/02/202946.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/202946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-09-02 14:26 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/09/02/202946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A collection of color schemes for some famous websites in China</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/08/26/202767.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 26 Aug 2013 01:08:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/08/26/202767.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/202767.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/08/26/202767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/202767.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/202767.html</trackback:ping><description><![CDATA[<div><div id="article_content_panel">      <p>Each website has a color scheme which identifies itself. By  looking at one color, we can know which website it is for. These color  schemes can be identified from their logos, nav-bars, background etc. We  collect some color schemes for some famous Chinese websites.</p> <p><strong>Alibaba (#f90)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #f90;">&nbsp;</div> <p><strong>Baidu (#0000cc)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #0000cc;">&nbsp;</div> <p><strong>Huawei (#e30a12)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #e30a12;">&nbsp;</div> <p><strong>HTC (#69b40f)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #69b40f;">&nbsp;</div> <p><strong>JD (#c91623)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #c91623;">&nbsp;</div> <p><strong>Renren (#105ba3)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #105ba3;">&nbsp;</div> <p><strong>Sina (#e4351e)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #e4351e;">&nbsp;</div> <p><strong>Sohu (#fdd000)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #fdd000;">&nbsp;</div> <p><strong>Taobao (#ff4400)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #ff4400;">&nbsp;</div> <p><strong>Tencent (#0397de)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #0397de;">&nbsp;</div> <p><strong>Tmall (#b10000)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #b10000;">&nbsp;</div> <p><strong>WeChat (#5ba607)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #5ba607;">&nbsp;</div> <p><strong>Xiami (#f39200)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #f39200;">&nbsp;</div> <p><strong>Zhihu (#0078d8)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #0078d8;">&nbsp;</div> <p><strong>163 (#333)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #333;">&nbsp;</div> <p><strong>36Kr (#146fb9)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #146fb9;">&nbsp;</div> <p><strong>360 (#48b701)</strong></p> <div style="eight: 30px; line-height: 30px; display: inline-block; vertical-align: middle; width: 600px; background-color: #48b701;">&nbsp;</div> <p>We will upgrade more in the future.......</p>     </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/202767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-08-26 09:08 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/08/26/202767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>工具集</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/05/10/200145.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 10 May 2013 01:17:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/05/10/200145.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/200145.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/05/10/200145.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/200145.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/200145.html</trackback:ping><description><![CDATA[<div><div news_content"=""> 				<p>作为一个软件开发者，你不可避免地需要用到各种工具来设计、理解、编辑任何程序，本文作者按类型总结了10类开发者须知的工具。CSDN摘译如下：</p> <p>免责声明：&#8220;最好&#8221;的软件工具通常属于主观看法，也许你并不同意我的观点，但是也可以从中获取所需。 </p> <p><strong>1. 版本控制工具</strong> </p> <p>无论你是在100人的团队，还是一个人做设计、开发，<a href="http://zh.wikipedia.org/wiki/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6" target="_blank">版本控制工具</a>都能让你从中获益。 </p> <p>通过版本控制工具，你可以保留同一文件中在不同时期的版本，这对图表和二进制文件都适用，尤其适合文本类型文件。 </p> <p>主流版本控制工具可以分为两种：集中式和分布式。集中式版本控制工具需要一个服务器存储仓库，你可以在合适的时候把代码提交到服务器上。而分布式版 本控制工具（DVCS）则不需要中心服务器：每个仓库的使用者都有自己的本地缓存，将更新从一个本地仓库传递到另一个的过程非常简单只需要从源系统 push或者从目标系统pull即可。 </p> <p>目前最流行的开源版本控制工具要数<a href="http://subversion.apache.org/" target="_blank">Subvision</a>（SVN）、<a href="http://git-scm.com/" target="_blank">Git</a>以及<a href="http://mercurial.selenic.com/" target="_blank">Mercurial</a>（hg）了，其中SVN是集中式版本控制工具，Git和Mercurial则是分布式的。 </p> <p>值得注意的是，有很多知名网站提供仓库托管服务，比如bitbucket.org、SourceForge、GoogleCode以及Github等等，这些网站都提供免费托管服务，但在具体服务支持与收费上各不相同。 </p> <p><strong>2. 文件比较工具</strong> </p> <p>无论你是想要与版本控制系统合并代码，还是仅仅想要比较两个文件的不同，文件比较工具都是非常有用的。其中diff是一个非常有名的命令行比较工具，我也喜欢<a href="http://www.scootersoftware.com/" target="_blank">Beyond Compare</a>这款图形界面比较工具&#8212;&#8212;可惜它并非免费，但是并不贵而且简单、强大。除此之外，常见文件比较工具还有<a href="http://www.sourcegear.com/diffmerge/" target="_blank">SourceGearDiffMerge</a>（免费、跨平台=Windows/OS X/Linux)，<a href="http://www.grigsoft.com/wincmp3.htm" target="_blank">Compare It!</a>（收费、仅支持Windows），<a href="http://www.deltopia.com/compare-merge-sync/macosx/" target="_blank">DeltaWalker</a>（较贵、仅支持OSX）以及<a href="http://www.ultraedit.com/products/ultracompare.html" target="_blank">UltraCompare</a>（较贵、跨平台）。 </p> <p><strong>3. 编辑器</strong> </p> <p>处理文本文件的难以取决于你使用的软件。重量级的编辑器，如Eclipse、NetBeans、Visual  Studio都属于是IDE（integrateddevelopment  environment，集成开发环境），如果你需要做特定的工作，他们都非常强大。但有时候你仅仅想要简单、快速地编辑文件，系统自带的编辑器 （Windows下的Notepad和Machine下的TextEdit）虽然轻量但是不够强大。这里介绍几个中量级的编辑器：Windows平台的<a href="http://notepad-plus-plus.org/" target="_blank">Notepad++</a>、Mac平台的<a href="http://www.barebones.com/products/textwrangler/" target="_blank">TextWrangler</a>都是不错的免费编辑器，还有<a href="http://www.gnu.org/software/emacs/" target="_blank">GNUemacs</a>、Vim这样强大、可扩展的自由软件。 </p> <p><strong>4. 构建工具</strong> </p> <p>如果你使用IDE进行开发，仅仅单击&#8220;Build&#8221;即可以为你编译程序的源代码。但是注意：编译软件时常常有很多细节的编译选项，而使用IDE时常常被深藏在复杂的菜单中。我认为，专业的程序员应该使用可定义的构建工具，选择正确的编译选项达到最优效果。 </p> <p><strong>5. 脚本工具</strong> </p> <p>有时候你需要快速整合多个软件以达到某个目的，这时很难选择C或者C++这样需要编译的编程语言，因为它们在执行前需要先编译成可执行的文件。此时，更好的解决方案是脚本语言，它们通常集成在操作系统中，编写一个脚本甚至可以在多台计算机中运行。 </p> <p>常见现代脚本语言有Python、Ruby、Groovy、awk、Perl等等。不论你更喜欢那种，我建议你选择其中一款。我很喜欢Python，不仅因为它简单、鼓励好的编程规范，而且拥有强大的调试工具&#8212;&#8212;基于Eclipse的<a href="http://www.pydev.org/download.html" target="_blank">PyDev</a>。借助PyDev，你可以设置断点、并端部执行你的脚本。 </p> <p><strong>6. 数值分析工具</strong> </p> <p>除非你打算做一些及其简单的项目，或者为嵌入式系统进行逻辑编程，你常常会需要对数据有一个直观地了解&#8212;&#8212;图表、或者曲线图，又或者仅仅想要解一个方程，这时候你会需要数据分析工具，比如<a href="http://www.mathworks.com/products/matlab/" target="_blank">MATLAB</a>、<a href="http://www.wolfram.com/mathematica/" target="_blank">Mathematica</a>、<a href="http://www.ptc.com/product/mathcad/" target="_blank">MathCAD</a>，它们都非免费，甚至价格昂贵，但是价格强大。 </p> <p>如果你的需求简单，<a href="http://www.scilab.org/" target="_blank">SciLab</a>、<a href="http://www.gnu.org/software/octave/" target="_blank">Octave</a>、<a href="http://www.scipy.org/PyLab" target="_blank">PyLab</a>这些MATLAB的免费&#8220;克隆&#8221;版本也提供了某些MATLAB的基本功能，语法也与MATLAB相近或相同。其中PyLab用Python实现，如果你懂Python，或许可以将其利用到科学计算领域。 </p> <p><strong>7. 文档工具</strong> </p> <p>工程环境中，你常常需要和他人分享想法，很多软件都可以做到这点，比如使用微软的Visio可以提供流程图、表，Word来编辑文档，PowerPoint来做演示。但它们都非免费，有时候你更需要免费或者更特化的文档工具。</p> <span style="line-height: 1.45em;"><ul><li><span style="line-height: 1.45em;"><strong>图形可视化工具</strong>&#8212;&#8212;我常用的是基于命令行的</span><a href="http://graphviz.org/" target="_blank" style="line-height: 1.45em;">graphviz</a><span style="line-height: 1.45em;">，以及拥有交互界面的</span><a href="http://www.yworks.com/en/products_yed_about.html" target="_blank" style="line-height: 1.45em;">yEd</a><span style="line-height: 1.45em;">。 &nbsp; &nbsp;</span></li><li><span style="line-height: 1.45em;"><strong>流程图</strong>&#8212;&#8212;使用图形表达思路。</span><a href="http://sdedit.sourceforge.net/example/index.html" target="_blank" style="line-height: 1.45em;">Quick Sequence Diagram Editor</a><span style="line-height: 1.45em;">很基本，但是足以帮助你达到绘制这些图形的目的。 &nbsp; &nbsp;</span></li><li><span style="line-height: 1.45em;"><strong>排版工具</strong>&#8212;&#8212;你可以使用</span><a href="http://en.wikipedia.org/wiki/WYSIWYG" target="_blank" style="line-height: 1.45em;">WYSIWYG</a><span style="line-height: 1.45em;">工具，也可以选择非WYSIWYG软件，又或者TeX、LaTeX，随个人喜好。 &nbsp; &nbsp;</span></li><li><span style="line-height: 1.45em;"><strong>代码自文档工具</strong>&#8212;&#8212;</span><a href="http://en.wikipedia.org/wiki/Doxygen" target="_blank" style="line-height: 1.45em;">Doxygen</a><span style="line-height: 1.45em;">很常见，可以将代码中的注释转化成文档，</span><a href="http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html" target="_blank" style="line-height: 1.45em;">JavaDoc</a><span style="line-height: 1.45em;">则是转为Java设计的文档工具。 &nbsp; &nbsp;</span></li></ul></span> <p><strong>8. 终端以及通信工具</strong> </p> <p>有时候你会需要通过串口进行通信，这时你就需要终端工具了，在Web浏览器出现之前，这更为常见。曾经与Windows绑定的<a href="http://en.wikipedia.org/wiki/Hilgraeve" target="_blank">HyperTerminal</a>不够强大，不建议使用，而且微软在Vista之后也不再集成它。我个人更喜欢<a href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html" target="_blank">PuTTYtel</a>和<a href="http://www.ayera.com/teraterm/" target="_blank">TeraTermPro</a>。其它通信工具如FTP及其安全变种SFTP、SCP方面我最喜欢<a href="http://cyberduck.ch/" target="_blank">Cyberduck</a>，现在支持Mac和Windows。 </p> <p><strong>9. 软件QA（质量保障）工具</strong> </p> <p>对于开发者来说，为避免bug你肯定需要QA工具。我不是很清楚这方面，但是知道大概可以分以下几类：</p> <span style="line-height: 1.45em;"><ul><li><span style="line-height: 1.45em;"><strong>静态分析工具。</strong>它是一种分析软件的工具，既可以分析软件源代码，也可以分析编译后的文件。最出名的莫过于面向C语言的</span><a href="http://en.wikipedia.org/wiki/Lint_%28software%29" target="_blank" style="line-height: 1.45em;">lint</a><span style="line-height: 1.45em;">，lint会像老是一样在你代码的错误之处标出红线，标出你的错误。Java语言有</span><a href="http://en.wikipedia.org/wiki/FindBugs" target="_blank" style="line-height: 1.45em;">FindBugs</a><span style="line-height: 1.45em;">对应，能够帮助衡量代码复杂度&#8212;&#8212;通常好的程序设计函数比较小，如果某个函数超过20-30行代码，你可以考虑将其分解了，这样也更便于设计和调试。 &nbsp; &nbsp;</span></li><li><span style="line-height: 1.45em;"><strong>单元测试和代码覆盖率。</strong>大 型软件测试通常极难，这是公认的；但是使用&#8220;单元测试&#8221;测试更小的软件模块却简单得多。但是单元测试同样也有不擅长的领域，比如嵌入式系统，虽然可以通过 交叉编译在PC上寻找bug，但并不能保证在嵌入式机器上效果一致。单元测试也有一定的技巧，比如可以编写可重复利用的测试脚本。代码覆盖工具我仅见过同 事使用</span><a href="http://www.qa-systems.com/cantata.html" target="_blank" style="line-height: 1.45em;">Cantata++</a><span style="line-height: 1.45em;">，但并不便宜。 &nbsp; &nbsp;</span></li><li><span style="line-height: 1.45em;"><strong>代码&#8220;美化器&#8221;。</strong>如果你和同事使用相同的编码风格，更容易寻找出简单的语法错误。通常我们都有各自的编程习惯，但是可以通过软件达到统一编程风格的效果&#8212;&#8212;比如自动缩进、tab空格转换等等。我使用过</span><a href="http://uncrustify.sourceforge.net/" target="_blank" style="line-height: 1.45em;">Uncrustify</a><span style="line-height: 1.45em;">，以及其GUI工具</span><a href="http://universalindent.sourceforge.net/" target="_blank" style="line-height: 1.45em;">UniversalIndentGU</a><span style="line-height: 1.45em;">。 &nbsp; &nbsp;</span></li></ul></span> <p><strong>10. 基本命令行工具</strong> </p> <p>虽然GUI对于计算机交互是革命性的改进，但还有很多事用命令行做起来更加简单，比如使用脚本能够轻易组合多个程序。如果你使用OS X或者Linux，那计算机上一般已经预装了<a href="http://en.wikipedia.org/wiki/Template:Unix_commands" target="_blank">UNIX命令行工具</a>，Windows用户可以<a href="http://unxutils.sourceforge.net/" target="_blank">下载相应的二进制文件</a>。 </p> <p>其它，诸如<a href="http://www.7-zip.org/" target="_blank">7zip</a>、<a href="http://www.cpuid.com/softwares/cpu-z.html" target="_blank">CPU-Z</a>、<a href="http://systemexplorer.net/" target="_blank">System Explorer</a>之类的软件虽然没有放在这个列表中，但也都是非常实用的工具。 </p> <p>原文链接：<a href="http://www.embeddedrelated.com/showarticle/128.php" target="_blank">EmbeddedRelated.com</a> </p>				 				</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/200145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-05-10 09:17 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/05/10/200145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Meteor：让实时Web App成为主流</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Mar 2013 01:41:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198709.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198709.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198709.html</trackback:ping><description><![CDATA[<div><p>     <a href="http://www.meteor.com/" target="_blank">Meteor</a>是一个新鲜出炉的现代网站开发平台，目前发布的是开发<a href="http://www.meteor.com/faq/preview" target="_blank">预览版</a><a href="http://www.meteor.com/faq/preview" target="_blank">0.5.8</a>，代码以GPL协议开源。大家可以去     <a href="https://github.com/meteor/meteor" target="_blank">GitHub</a>上关注它。Meteor本质上是Node.JS应用的开发，继承了Ruby on Rails、Node.JS、MongoDB     API等框架的基础特性，模糊了服务器端和客户端，弱化网络连接质量造成的影响。</p> <p>如果简单定义&#8220;现代网站&#8221;是一个实时交互、超高性能、具备非凡体验的网站，那么  Meteor就是一个可为开发者以简单高效而且充满乐趣的方式进行现代网站开发的平台，以往开发周期需要几周到几个月的项目，现在可能只需要几个小时或者 一个周末的时间就可以完成。Meteor构建的应用体验，会让人觉得浏览器的刷新按钮和地址栏是多余的。</p> <p>Meteor在2012年4月首次发布，该消息一经发布，便迅速占据了Haceker News头条宝座，并且成为Hacker News上最热门的文章之一。本文是作者Sacha     Greif使用Meteor开发的心得体会，他认为Meteor会让实时Web App在未来成为主流。     <br /> </p> <p>下面是对原文的翻译：</p> <p>在过去6个月里，我使用Meteor做了点东西（     <a href="http://telesc.pe/" target="_blank">Telescope</a>，Meteor开源的主要应用程序之一），我觉得有必要分享一下我的感受。</p> <p style="text-align: center; ">     <a href="http://cms.csdnimg.cn/article/201303/14/514120de6fe3f.jpg" target="_blank">         <img src="http://cms.csdnimg.cn/article/201303/14/514120de6fe3f.jpg" border="0"  alt="" />     </a>     <br /> </p> <p>首先声明：在和Meteor代码打交道的每一天里，我的大部分时间都在使Telescope变更加可用，而不是去深入挖掘Meteor，所以我不敢 自称是Meteor方面的专家，而之所以能很快上手，很大一部分原因是因为它是一个非常好用且高效的框架，即使在你不精通的情况下也能开发出非常出色的应 用。</p> <p><strong>简单 智能</strong> </p> <p>Meteor的一大特色就是可以轻松构建高品质的实时Web应用程序，相信很多程序员都是因为这一特性而熟知Meteor的。当开始使用Meteor时，会让你的生活变得很简单。</p> <p>     <a href="http://docs.meteor.com/#quickstart" target="_blank">安装Meteor</a>也非常简单，只需一行命令即可。随即便创建第一个应用程序，就连部署也都非常简单，由于Meteor提供免费的托管，因此你可以在线部署，供世界各地的人来浏览。</p> <p style="text-align: center; ">     <a href="http://cms.csdnimg.cn/article/201303/14/5141220800ca2.jpg" target="_blank">         <img src="http://cms.csdnimg.cn/article/201303/14/5141220800ca2.jpg" border="0"  alt="" />     </a>     <br />     </p>     <p>此外，使用Meteor编写的应用程序运行速度也非常快。例如，当你的项目引用JS或CSS文件时，这些文件将会被自动加载，而Meteor也提供了内置的用户管理，自动完成UI部件的加载。</p>     <p><strong>Meteor九大特性</strong>     </p>          <ol><li>纯JavaScript</li><li>实时页面更新</li><li>干净、强大的数据同步</li><li>&nbsp;延迟补偿</li><li>代码热推送</li><li>敏感代码运行于受限环境中</li><li>&nbsp;完全独立的应用包</li><li>互操作</li><li>智能的包</li></ol>          <p><strong>实时的未来</strong>     </p>     <p>说实话，实时框架是Meteor的最大卖点，实时Web应用程序会让人联想到多人游戏和实时在线文档编辑，但在使用Meteor时，我快速发现实时也可以编写出更加实用且非常好的应用程序，而这种实时很有可能会成为未来几年内Web应用程序的默认编写方式。</p>     <p>在桌面应用系统中，如果一个目录被两个窗口同时打开，那么当你在其中一个窗口删除一个文件后，你必须刷新另一个窗口，那个文件才会&#8220;消失&#8221;。因此，这就缺乏了实时性，而Meteor框架就可弥补这方面的不足。</p>     <p>此外，实时也影响到我们的编码风格。你无需刷新页面或使用特定的回调逻辑来使应用程序做出响应：每一个块数据都会自动监测、任何与UI元素有关的数据也会自动更新。</p>     <p>下面提供一个案例，一旦有人投票，就响应upvote按钮的&#8220;disable&#8221;类，模板代码（Meteor使用         <a href="http://thechangelog.com/handlebars-js/" target="_blank">Handlebars</a>）：</p>     <div><div id="highlighter_973470"  html"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div style="height: 24px !important;" number1="" index0=""  alt2"="">1</div><div style="height: 24px !important;" number2="" index1=""  alt1"="">2</div><div style="height: 24px !important;" number3="" index2=""  alt2"="">3</div><div style="height: 24px !important;" number4="" index3=""  alt1"="">4</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">&lt;</code><code keyword"="">div</code> <code color1"="">class</code><code plain"="">=</code><code string"="">"post"</code><code plain"="">&gt;</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">a</code> <code color1"="">href</code><code plain"="">=</code><code string"="">"#"</code> <code color1"="">class</code><code plain"="">=</code><code string"="">"upvote btn {{upvotedClass}}"</code><code plain"="">&gt;⬆&lt;</code><code keyword"="">a</code> <code plain"="">/&gt;</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">h3</code><code plain"="">&gt;&lt;</code><code keyword"="">a</code> <code color1"="">href</code><code plain"="">=</code><code string"="">"{{url}}"</code><code plain"="">&gt;{{title}}&lt;/</code><code keyword"="">a</code><code plain"="">&gt;&lt;/</code><code keyword"="">h3</code><code plain"="">&gt;</code></div><div number4="" index3=""  alt1"=""><code plain"="">&lt;/</code><code keyword"="">div</code><code plain"="">&gt;</code></div></div></td></tr></tbody></table></div></div>          <p>下面是与之匹配的控制器代码：</p>     <div><div id="highlighter_392042"  js"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div style="height: 24px !important;" number1="" index0=""  alt2"="">1</div><div style="height: 24px !important;" number2="" index1=""  alt1"="">2</div><div style="height: 48px !important;" number3="" index2=""  alt2"="">3</div><div style="height: 48px !important;" number4="" index3=""  alt1"="">4</div><div style="height: 24px !important;" number5="" index4=""  alt2"="">5</div><div style="height: 24px !important;" number6="" index5=""  alt1"="">6</div><div style="height: 24px !important;" number7="" index6=""  alt2"="">7</div><div style="height: 24px !important;" number8="" index7=""  alt1"="">8</div><div style="height: 24px !important;" number9="" index8=""  alt2"="">9</div><div style="height: 24px !important;" number10="" index9=""  alt1"="">10</div><div style="height: 24px !important;" number11="" index10=""  alt2"="">11</div><div style="height: 24px !important;" number12="" index11=""  alt1"="">12</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">Template.post.helpers({</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">upvotedClass: </code><code keyword"="">function</code><code plain"="">() {</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code comments"="">// test if user is logged in, and if their userId </code></div><div number4="" index3=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code comments"="">// is included in the 'upvoters' array</code></div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">var</code> <code plain"="">userId = Meteor.userId();</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">if</code> <code plain"="">(userId &amp;&amp; !_.include(</code><code keyword"="">this</code><code plain"="">.upvoters, userId)) {</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code string"="">'upvoteable'</code><code plain"="">;</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">} </code><code keyword"="">else</code> <code plain"="">{</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code string"="">'disabled'</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">}</code></div><div number12="" index11=""  alt1"=""><code plain"="">});</code></div></div></td></tr></tbody></table></div></div>          <p>这段代码妙在何处呢？如果用户的userid从upvoters数组中删除（例如，实现一个&#8220;cancel upvote&#8221;操作），这会自动在UI上反应出来，无需编写额外的代码。</p>     <p><strong>一切就绪了吗？</strong>     </p>     <p>现在，你可能会随着这一行行代码思考些东西：&#8220;好，它看起来很棒，但是它真的就可以作为现实应用（&nbsp;real-world apps）吗？&#8221;</p>     <p>答案肯定是依情况而定。Meteor当然可以作为现实应用使用。Telescope和Sidebar（基于Telescope）就是非常完美的例子。</p>     <p>但并不是说Meteor就可以完全作为现实应用使用。Meteor没有服务端渲染功能，有些网站对加载速度要求特别高，比如电子商务网站，而有些则需要在旧的/老的设备上运行，比如过时的手机。</p>     <p><strong>Meteor Book</strong>     </p>     <p>目前，我和         <a href="http://tom.thesnail.org/" target="_blank">Tom Coleman</a>（Meteor开源生态系统的主要贡献者之一，创建Meteor包管理器         <a href="https://github.com/oortcloud/meteorite" target="_blank">Meteorite</a>）正在专注于         <a href="http://themeteorbook.com/" target="_blank">The Meteor Book</a>，教你如何使用Meteor编写基本的应用程序。</p>     <p>更多精彩内容，大家可以来到Hacker News上和我一起         <a href="https://news.ycombinator.com/item?id=5362370" target="_blank">探讨</a>。（编译/张红月 责编/付江）</p> <hr />     <p><strong>学习资料：</strong>     </p>     <p>官方提供的3个示例：</p>          <ul><li>             <a href="http://meteor.com/examples/leaderboard">http://meteor.com/examples/leaderboard</a>         </li><li>             <a href="http://meteor.com/examples/todos">http://meteor.com/examples/todos</a>         </li><li>             <a href="http://meteor.com/examples/wordplay">http://meteor.com/examples/wordplay</a>         </li></ul>          <p>GitHub项目页：</p>          <ul><li>             <a href="http://github.com/meteor/meteor">http://github.com/meteor/meteor</a>         </li></ul>          <p>Meteor@StackOverflow</p>          <ul><li>             <a href="http://stackoverflow.com/questions/tagged/meteor?sort=newest&amp;pagesize=15">http://stackoverflow.com/questions/tagged/meteor?sort=newest&amp;pagesize=15</a>         </li></ul>          <p>文档：</p>          <ul><li>             <a href="http://docs.meteor.com/">http://docs.meteor.com/</a>         </li></ul>          <p>FAQ：</p>          <ul><li>             <a href="http://meteor.com/faq">http://meteor.com/faq</a>         </li></ul></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-03-22 09:41 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SEH异常处理学习总结 </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/03/21/198679.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 21 Mar 2013 07:43:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/03/21/198679.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198679.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/03/21/198679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198679.html</trackback:ping><description><![CDATA[<div>前一段时间，在看异常处理一章内容的时候，发现这一部分还真的挺有尿水：）所以上网搜了一下有关内容，呦嗬，还挺丰富的。当然有些自己还是看不懂，现在就将这些宝贝拿出来跟大家共享一下。<br />首先我们看一下使用异常处理的几种情况：<br />A． 用来处理非致命的错误<br />B． 对API函数的参数合法性的检验（假设参数都是合法的，只有遇到异常的时候进行合法性检验）<br />C． 处理致命错误（退出时最好的选择，但是有的时候可以用异常处理函数在程序退出前释放资源，删除临时文件等，甚至可以详细记录产生异常的指令位置和环境）<br />D． 处理&#8220;计划内&#8221;的异常（我们可能更关心这种情况，因为可以做很多的手脚，哈哈）<br />接着我们看看Windows下异常处理的两种方式：1使用筛选器2&nbsp;SEH异常处理<br />一、 使用筛选器<br />因为这里我要重点关注的是SEH的处理方式，所以还是简单的提一下筛选器处理方式。筛选器异常处理是通过异常回调函数来指定程序处理异常。这种方式的回调函数必须是唯一的，设置新的回调函数后以前的将失效。适用于进程范围。看一下这个函数的定义<br />Invoke SetUnhandledExecpionFilter,offset_Handler<br />Mov lpPrevHandler,eax<br />(先到这里吧有些难受，明天接着来)<br />######题外话：想起&#8220;司令&#8221;的一句话，觉得挺有道理：明天不一定美好，但是更美好的明天一定会到来！祝福所有的朋友。######<br /><br />上午有会，什么也没有做，下午？还有会，我tm晕了，中午不睡觉了，不把事情做不完心里不踏实。<br />回调函数的格式：<br />_Handlerproc pExecptionInfo<br />看看pExecptionInfo这个指针参数指向的一个数据结构<br />EXCEPTION_POINTERS&nbsp;STRUCT&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pExceptionRecord&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ContextRecord&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_POINTERS&nbsp;ENDS<br />下面介绍&nbsp;EXCEPTION_RECORD和CONTEXT结构的定义:&nbsp;<br />&nbsp;&nbsp;<br />;//=====================&nbsp;以下是两个成员的详细结构=========================<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION_RECORD&nbsp;STRUCT&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionCode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//异常码&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionFlags&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//异常标志&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pExceptionRecord&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//指向另外一个EXCEPTION_RECORD的指针&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//异常发生的地址&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberParameters&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//下面ExceptionInformation所含有的dword数目&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExceptionInformation&nbsp;&nbsp;DWORD&nbsp;EXCEPTION_MAXIMUM_PARAMETERS&nbsp;dup(?)&nbsp;<br />&nbsp;&nbsp;&nbsp;EXCEPTION_RECORDENDS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//EXCEPTION_MAXIMUM_PARAMETERS&nbsp;==15&nbsp;<br /><br />;//=============================具体解释================================<br /><br />ExceptionCode&nbsp;异常类型,SDK里面有很多类型,你可以在windows.inc里查找STATUS_来找到更多的异常类型,下面只给出hex值,具体标识定义请查阅windows.inc,你最可能遇到的几种类型如下:&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C0000005h----读写内存冲突&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C0000094h----非法除0&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C00000FDh----堆栈溢出或者说越界&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80000001h----由Virtual&nbsp;Alloc建立起来的属性页冲突&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C0000025h----不可持续异常,程序无法恢复执行,异常处理例程不应处理这个异&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;常&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C0000026h----在异常处理过程中系统使用的代码,如果系统从某个例程莫名奇妙的返回,则出现此代码,&nbsp;如果RtlUnwind时没有Exception&nbsp;Record参数也同样会填入这个代码&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80000003h----调试时因代码中int3中断&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80000004h----处于被单步调试状态&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注:也可以自己定义异常代码,遵循如下规则:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;____________________________________________________________________<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;位:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;31~30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;29~28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;27~16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15~0&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;____________________________________________________________________<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;含义:&nbsp;&nbsp;&nbsp;&nbsp;严重程度&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;29位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;功能代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;异常代码&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0==成功&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0==Mcrosoft&nbsp;&nbsp;&nbsp;&nbsp;MICROSOFT定义&nbsp;&nbsp;用户定义&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1==通知&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1==客户&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2==警告&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;28位&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3==错误&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;被保留必须为0&nbsp;<br />ExceptionFlags&nbsp;异常标志&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0----可修复异常&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1----不可修复异常&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2----正在展开,不要试图修复什么,需要的话,释放必要的资源&nbsp;<br />pExceptionRecord&nbsp;如果程序本身导致异常,指向那个异常结构&nbsp;<br />ExceptionAddress&nbsp;发生异常的eip地址&nbsp;<br />ExceptionInformation&nbsp;附加消息,在调用RaiseException可指定或者在异常号为C0000005h即内存异常时含义如下&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第一个dword&nbsp;0==读冲突&nbsp;1==写冲突&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第二个dword&nbsp;读写冲突地址&nbsp;<br />;//================================解释结束============================<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;off.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTEXT&nbsp;STRUCT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;_&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ContextFlags&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+0&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+4&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+8&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&gt;调试寄存器&nbsp;&nbsp;+C&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+10&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+14&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iDr7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;_|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+18&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FloatSave&nbsp;&nbsp;&nbsp;&nbsp;FLOATING_SAVE_AREA&nbsp;&lt;&gt;&nbsp;&nbsp;;浮点寄存器区&nbsp;+1C~~~88h&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regGs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;--|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+8C&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regFs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|/段寄存器&nbsp;&nbsp;&nbsp;&nbsp;+90&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;|/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+94&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regDs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;--|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+98&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEdi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;____________&nbsp;&nbsp;&nbsp;&nbsp;+9C&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEsi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;通用&nbsp;&nbsp;+A0&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEbx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;寄&nbsp;&nbsp;&nbsp;&nbsp;+A4&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEdx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;存&nbsp;&nbsp;&nbsp;&nbsp;+A8&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEcx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;器&nbsp;&nbsp;&nbsp;&nbsp;+AC&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;_______|___组_&nbsp;&nbsp;+B0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEbp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;++++++++++++++++&nbsp;+B4&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;|控制&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+B8&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regCs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;|寄存&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+BC&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regFlag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;|器组&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+C0&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regEsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+C4&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regSs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;++++++++++++++++&nbsp;+C8&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExtendedRegisters&nbsp;db&nbsp;MAXIMUM_SUPPORTED_EXTENSION&nbsp;dup(?)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTEXT&nbsp;ENDS&nbsp;<br />;//============================以上是两个成员的详细结构============&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />程序使用筛选器异常处理时可以通过查看上面结构中的regEip来找到产生异常的地址！调试的时候可以改变EIP的值以达到越过异常程序，转到&#8220;安全&#8221;的地方。<br />最后看一下筛选器异常处理回调函数的返回值<br />EXECPTION_EXECUTE_HANDLER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1；进程被终止，终止前不会出现提示错误的对话框<br />EXECPTION_CONTINUE_SEARCH 0；同样终止程序，显示错误对话框<br />EXECPTION_CONTINUE_EXECUTION -1；系统将CONTECT设置回去，继续执行程序<br /><br />使用筛选器程序是最简单的处理异常方法，不足：1&nbsp;不便于封装。2&nbsp;处理是全局性的也就是无法对每个线程或子程序设置一个私有的异常处理程序进行异常处理。<br />进入正题：SEH异常处理<br />首先解释一下什么是SEH异常处理：SEH("Structured&nbsp;Exception&nbsp;Handling"<img src="http://www.blogcn.com/images/wink.gif" alt="" border="0" hspace="2" vspace="2" />,即结构化异常处理.是操作系统提供给程序设计者的强有力的处理程序错误或异常的武器。<br />下面结合冷雨飘心的一个SEH异常处理程序来说明具体的用法：<br />;//====================================================================<br />;//&nbsp;ex.&nbsp;2,by&nbsp;Hume,2001&nbsp;&nbsp;线程相关的异常处理&nbsp;<br />;//====================================================================<br />.386&nbsp;<br />.model&nbsp;flat,&nbsp;stdcall&nbsp;<br />option&nbsp;casemap&nbsp;:none&nbsp;&nbsp;;&nbsp;case&nbsp;sensitive&nbsp;<br />include&nbsp;hd.h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//相关的头文件，你自己维护一个吧&nbsp;<br />;//============================&nbsp;<br />.data&nbsp;<br />szCap&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;"By&nbsp;Hume[AfO],2001...",0&nbsp;<br />szMsgOK&nbsp;db&nbsp;"It's&nbsp;now&nbsp;in&nbsp;the&nbsp;Per_Thread&nbsp;handler!",0&nbsp;<br />szMsgERR1&nbsp;db&nbsp;"It&nbsp;would&nbsp;never&nbsp;Get&nbsp;here!",0&nbsp;<br />buff&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;200&nbsp;dup(0)&nbsp;<br /><br />.code&nbsp;<br />_start:&nbsp;<br />;//========prog&nbsp;begin====================&nbsp;<br />&nbsp;&nbsp;ASSUME&nbsp;FS:NOTHING&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;perThread_Handler&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;fs:[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;fs:[0],esp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//建立SEH的基本ERR结构,如果不明白,就仔细研究一下吧&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xor&nbsp;&nbsp;&nbsp;&nbsp;ecx,ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cdq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;；//双字扩展到四个字节，因为是除法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;div&nbsp;&nbsp;&nbsp;&nbsp;ecx&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//以下永远不会被执行&nbsp;<br />&nbsp;invoke&nbsp;&nbsp;MessageBox,NULL,addr&nbsp;szMsgERR1,addr&nbsp;szCap,MB_OK+MB_ICONINFORMATION&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pop&nbsp;&nbsp;&nbsp;&nbsp;fs:[0]&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;esp,4&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;ExitProcess,NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />;//============================&nbsp;<br />perThread_Handler:&nbsp;<br />&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;MessageBox,NULL,addr&nbsp;szMsgOK,addr&nbsp;szCap,MB_OK+MB_ICONINFORMATION&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//ExceptionContinueSearch,不处理,由其他例程或系统处理&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//ExceptionContinueExecution,表示已经修复CONTEXT,可从异常发生处继续执行&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;//这里如果返回0,你会陷入死循环,不断跳出对话框....&nbsp;<br /><br />;//=============================Prog&nbsp;Ends==============&nbsp;<br />end&nbsp;_start<br />程序本身很简单，注释也很详细。我们来看看是如何注册回调函数的<br />push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;perThread_Handler&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;fs:[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;fs:[0],esp&nbsp;<br />仅仅三个语句就解决了~那么为什么要用fs这个段寄存器呢？这里又涉及一个重要的内容：TIB（Thread&nbsp;Information&nbsp;Block线程信息块）。我们来看看这个重要的数据结构（引用了《罗聪浅谈利用SEB实现反跟踪》的部分内容）<br />TEB(Thread&nbsp;Environment&nbsp;Block)&nbsp;在&nbsp;Windows&nbsp;9x&nbsp;系 列中被称为&nbsp;TIB(Thread&nbsp;Information&nbsp;Block)，它记录了线程的重要信息，而且每一个线程都会对应一个&nbsp;TEB&nbsp;结 构。&nbsp;Matt&nbsp;Pietrek&nbsp;大牛已经给我们列出了它的结构，我就不多说啦，见下：（摘 自&nbsp;Matt&nbsp;Pietrek&nbsp;的&nbsp;Under&nbsp;The&nbsp;Hood&nbsp;-&nbsp;MSJ&nbsp;1996）&nbsp;<br /><br />//===========================================================&nbsp;<br />//&nbsp;file:&nbsp;TIB.H&nbsp;<br />//&nbsp;Author:&nbsp;Matt&nbsp;Pietrek&nbsp;<br />//&nbsp;From:&nbsp;Microsoft&nbsp;Systems&nbsp;Journal&nbsp;"Under&nbsp;the&nbsp;Hood",&nbsp;May&nbsp;1996&nbsp;<br />//===========================================================&nbsp;<br />#pragma&nbsp;pack(1)&nbsp;<br /><br />typedef&nbsp;struct&nbsp;_EXCEPTION_REGISTRATION_RECORD&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;struct&nbsp;_EXCEPTION_REGISTRATION_RECORD&nbsp;*&nbsp;pNext;&nbsp;<br />&nbsp;&nbsp;FARPROC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pfnHandler;&nbsp;<br />}&nbsp;EXCEPTION_REGISTRATION_RECORD,&nbsp;*PEXCEPTION_REGISTRATION_RECORD;&nbsp;<br /><br />typedef&nbsp;struct&nbsp;_TIB&nbsp;<br />{&nbsp;<br />PEXCEPTION_REGISTRATION_RECORD&nbsp;pvExcept;&nbsp;//&nbsp;00h&nbsp;Head&nbsp;of&nbsp;exception&nbsp;record&nbsp;list&nbsp;<br />PVOID&nbsp;&nbsp;pvStackUserTop;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;04h&nbsp;Top&nbsp;of&nbsp;user&nbsp;stack&nbsp;<br />PVOID&nbsp;&nbsp;pvStackUserBase;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;08h&nbsp;Base&nbsp;of&nbsp;user&nbsp;stack&nbsp;<br /><br />union&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;0Ch&nbsp;(NT/Win95&nbsp;differences)&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;struct&nbsp;&nbsp;//&nbsp;Win95&nbsp;fields&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WORD&nbsp;&nbsp;&nbsp;&nbsp;pvTDB;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;0Ch&nbsp;TDB&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WORD&nbsp;&nbsp;&nbsp;&nbsp;pvThunkSS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;0Eh&nbsp;SS&nbsp;selector&nbsp;used&nbsp;for&nbsp;thunking&nbsp;to&nbsp;16&nbsp;bits&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;unknown1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;10h&nbsp;<br />&nbsp;&nbsp;}&nbsp;WIN95;&nbsp;<br /><br />&nbsp;&nbsp;struct&nbsp;&nbsp;//&nbsp;WinNT&nbsp;fields&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID&nbsp;SubSystemTib;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;0Ch&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;FiberData;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;10h&nbsp;<br />&nbsp;&nbsp;}&nbsp;WINNT;&nbsp;<br />}&nbsp;TIB_UNION1;&nbsp;<br /><br />PVOID&nbsp;&nbsp;pvArbitrary;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;14h&nbsp;Available&nbsp;for&nbsp;application&nbsp;use&nbsp;<br />struct&nbsp;_tib&nbsp;*ptibSelf;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;18h&nbsp;Linear&nbsp;address&nbsp;of&nbsp;TIB&nbsp;structure&nbsp;<br /><br />union&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;1Ch&nbsp;(NT/Win95&nbsp;differences)&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;struct&nbsp;&nbsp;//&nbsp;Win95&nbsp;fields&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WORD&nbsp;&nbsp;&nbsp;&nbsp;TIBFlags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;1Ch&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WORD&nbsp;&nbsp;&nbsp;&nbsp;Win16MutexCount;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;1Eh&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;DebugContext;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;20h&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;pCurrentPriority;&nbsp;&nbsp;//&nbsp;24h&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;pvQueue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;28h&nbsp;Message&nbsp;Queue&nbsp;selector&nbsp;<br />&nbsp;&nbsp;}&nbsp;WIN95;&nbsp;<br /><br />&nbsp;&nbsp;struct&nbsp;&nbsp;//&nbsp;WinNT&nbsp;fields&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;unknown1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;1Ch&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;processID;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;20h&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;threadID;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;24h&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;unknown2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;28h&nbsp;<br />&nbsp;&nbsp;}&nbsp;WINNT;&nbsp;<br />}&nbsp;TIB_UNION2;&nbsp;<br /><br />PVOID*&nbsp;&nbsp;pvTLSArray;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;2Ch&nbsp;Thread&nbsp;Local&nbsp;Storage&nbsp;array&nbsp;<br /><br />union&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;30h&nbsp;(NT/Win95&nbsp;differences)&nbsp;<br />{&nbsp;<br />&nbsp;&nbsp;struct&nbsp;&nbsp;//&nbsp;Win95&nbsp;fields&nbsp;<br />&nbsp;&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID*&nbsp;&nbsp;pProcess;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;30h&nbsp;Pointer&nbsp;to&nbsp;owning&nbsp;process&nbsp;database&nbsp;<br />&nbsp;&nbsp;}&nbsp;WIN95;&nbsp;<br />}&nbsp;TIB_UNION3;&nbsp;<br /><br />}&nbsp;TIB,&nbsp;*PTIB;&nbsp;<br />#pragma&nbsp;pack()<br />让我们抬头看看上面的&nbsp;Matt&nbsp;Pietrek&nbsp;的代码，其中有这么一行：&nbsp;<br /><br />PEXCEPTION_REGISTRATION_RECORD&nbsp;pvExcept;&nbsp;//&nbsp;00h&nbsp;Head&nbsp;of&nbsp;exception&nbsp;record&nbsp;list&nbsp;<br /><br />注 意到&nbsp;PEXCEPTION_REGISTRATION_RECORD&nbsp;这个定义，它表示&nbsp;pvExcept&nbsp;这个变量正 是&nbsp;exception&nbsp;record&nbsp;list&nbsp;的入口，这个入口位于整个结构的&nbsp;0&nbsp;偏移处。同时， 在&nbsp;M&nbsp;的&nbsp;Intel&nbsp;i386&nbsp;Windows&nbsp;NT/2K/XP&nbsp;内核中，每当创建一个线程，OS&nbsp;均会为每个线程分配&nbsp;TEB&nbsp;，而 且&nbsp;TEB&nbsp;永远放在&nbsp;fs&nbsp;段选择器指定的数据段的&nbsp;0&nbsp;偏移处。&nbsp;<br />这样一来，你就明白了&nbsp;SEH&nbsp;注册的偏移为什么是在&nbsp;fs:[0]&nbsp;了吧？&nbsp;<br />事实上&nbsp;Windows&nbsp;系统都是通过这种方法来为应用程序提供信息的，比如有这样的例子：&nbsp;<br />struct&nbsp;_tib&nbsp;*ptibSelf;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;18h&nbsp;Linear&nbsp;address&nbsp;of&nbsp;TIB&nbsp;structure&nbsp;<br />DWORD&nbsp;threadID;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;24h&nbsp;<br /><br />Windows&nbsp;提供了一个&nbsp;API&nbsp;：GetCurrentThreadID()，它的内部工作原理其实是这样的：（利用了上面的这两个地址）&nbsp;<br /><br />mov&nbsp;eax,&nbsp;fs:[18h]&nbsp;&nbsp;&nbsp;&nbsp;;因为&nbsp;18h&nbsp;偏移处是&nbsp;TIB&nbsp;结构的线性偏移地址&nbsp;<br />mov&nbsp;eax,&nbsp;[eax&nbsp;+&nbsp;24h]&nbsp;;因为&nbsp;24h&nbsp;偏移处是&nbsp;threadID&nbsp;的地址&nbsp;<br />ret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;把&nbsp;eax&nbsp;中储存的&nbsp;threadID&nbsp;地址返回<br />注：为什么要声明assume&nbsp;fs:nothing?因为masm编译器默认将fs段寄存器定义为error，所以程序在使用fs前必须将它启动！<br />接下来看看SEH的回调函数<br />_Handler proc&nbsp;_lpExecptionRecord,&nbsp;_lpSEH,lp_context,lp_DispatcherContext<br />&nbsp;<br />_lpExecptionRecord指向一个EXECPTION_RECORD结构。<br />lp_context&nbsp;指向一个CONTEXT结构。<br />_lpSEH&nbsp;&nbsp;指向注册回调函数时使用的EXXCEPTION_REGISTRATION结构的地址。<br />返回值有四种取值：<br />ExecptionContinueExecution&nbsp;(&nbsp;0&nbsp;<img src="http://www.blogcn.com/images/wink.gif" alt="" border="0" hspace="2" vspace="2" />：系统将线程环境设置为_lpContext指向的CONTEXT结构并继续执行。<br />ExceptionContinueSearch（1）：回调函数拒绝处理这个异常，系统通过EXECPTION_REGISTRATION结构的prev字段得到前一个回调函数的地址并调用它。<br />ExecptionNestedExecption&nbsp;（2）：发生异常嵌套。<br />ExecptionCollidedUnwind&nbsp;&nbsp;（3）：异常展开操作。这一个部分不做多讲，有兴趣的可以看看罗云彬的书，其实是很重要的一部分。<br />如果一个程序既有筛选器异常处理又有SEH异常处理，而且系统还有默认的异常处理机制，那么他们被调用的先后次序是怎么样的呢？<br />发生异常时系统的处理顺序(by&nbsp;Jeremy&nbsp;Gordon):&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;1.系统首先判断异常是否应发送给目标程序的异常处理例程,如果决定应该发送,并且目标程序正在被调试,则系统挂起程序并向调试器发送EXCEPTION_DEBUG_EVENT消息.呵呵,这不是正好可以用来探测调试器的存在吗?&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;2.如果你的程序没有被调试或者调试器未能处理异常,系统就会继续查找你是否安装了线程相关的异常处理例程,如果你安装了线程相关的异常处理例程,系统就把异常发送给你的程序seh处理例程,交由其处理.<br />&nbsp;&nbsp;&nbsp;&nbsp;3.每个线程相关的异常处理例程可以处理或者不处理这个异常,如果他不处理并且安装了多个线程相关的异常处理例程,可交由链起来的其他例程处理.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;4.如果这些例程均选择不处理异常,如果程序处于被调试状态,操作系统仍会再次挂起程序通知debugger.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;5.如果程序未处于被调试状态或者debugger没有能够处理,并且你调用SetUnhandledExceptionFilter安装了最后异&nbsp;常处理例程的话,系统转向对它的调用.&nbsp;<br />6.如果你没有安装最后异常处理例程或者他没有处理这个异常,系统会调用默认的系统处理程序,通常显示一个对话框,&nbsp;你可以选择关闭或者最后将其附加到调试器上的调试按钮.如果没有调试器能被附加于其上或者调试器也处理不了,系统就调用ExitProcess终结程序.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;7.不过在终结之前,系统仍然对发生异常的线程异常处理句柄来一次展开,这是线程异常处理例程最后清理的机会.<br /><br />说了这么多你也许会问SEH异常处理到底有什么用处呢？呵呵，且听小生慢慢道来~~~<br />第一道菜：病毒程序巧用SEH<br />这里简单的说一下如何利用SEH异常处理程序来躲避下毒软件的反病毒引擎。一个反病毒引擎在一个程序运行的时候会模拟程序的代码，当发现程序代码的疑点比较多的时候会报告成病毒。看看下面这段程序：<br />start:call&nbsp;Set_SEH;这句其实就是&nbsp;push&nbsp;offset&nbsp;CONTINUE<br />;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JMP&nbsp;Set_SEH<br />CONTINUE:mov&nbsp;esp,&nbsp;[esp+8];&nbsp;[ESP+8]存储的是旧的堆栈地址。<br />push&nbsp;offset&nbsp;Start_Virus&nbsp;;----_&nbsp;把Start_Virus&nbsp;的地址压栈，当作返回地址<br />ret;----跳到Start_Virus去，是不是很magic?&nbsp;<br /><br />Set_SEH:sub&nbsp;edx,&nbsp;edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;Edx&nbsp;=0&nbsp;<br />Assume&nbsp;fs:nothing&nbsp;<br />push&nbsp;dword&nbsp;ptr&nbsp;fs:[edx];把指去&nbsp;_EXCEPTIONAL_REGISTRATION_RECORD&nbsp;结构的指针入栈<br />mov&nbsp;fs:[edx],&nbsp;esp;安装一个seh<br />mov&nbsp;[edx],edx;引起一个内存读写冲突，发生异常因为edx=0&nbsp;<br />;如果反病毒引擎不处理异常，不进入seh&nbsp;处理程序(即&nbsp;CONTINUE:&nbsp;<img src="http://www.blogcn.com/images/wink.gif" alt="" border="0" hspace="2" vspace="2" />，继续模&nbsp;<br />;拟下个指令，也就是jmp&nbsp;start，那么就进入一个死循环，可能会引起死机。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />jmp&nbsp;start&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />Start_Virus:&nbsp;&nbsp;&nbsp;&nbsp;.....<br />是不是很简单呢？就是让反病毒引擎不处理这个人为的异常时进入死循环~！！<br />第二道菜：TEB反跟踪初探<br />如果你的记性够好的话一定记得上面介绍过的TEB（TIB）线程信息块结构中有这么一句：<br />PVOID*&nbsp;&nbsp;pProcess;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;30h&nbsp;Pointer&nbsp;to&nbsp;owning&nbsp;process&nbsp;database&nbsp;<br />这 个偏移地址处的内容非常有用，它指向本线程的拥有者的&nbsp;PDB(Process&nbsp;Database)&nbsp;的线性地址。当你用动态调试器，例 如&nbsp;OllyDbg&nbsp;的时候，调试器是把调试的对象作为一个子线程进行跟踪的，在这种情况下，被调试的对象的&#8220;拥有者&#8221;就是调试器本身，也就是说，它 的&nbsp;TEB&nbsp;的&nbsp;30h&nbsp;处的偏移指向的内容肯定不为&nbsp;0&nbsp;，这样，我们就可以利用这一点，判断&nbsp;30h&nbsp;偏移指向的内容，来判断是否有调试器跟踪。&nbsp;<br />最后给出一个&nbsp;Anti-Debug&nbsp;的例子程序，用&nbsp;MASM&nbsp;编译完成后，请用&nbsp;OllyDbg&nbsp;来加载调试一下，看看与正常的运行结果有什么不同。&nbsp;<br />;*********************************************************&nbsp;<br />;程序名称：演示利用&nbsp;TEB&nbsp;结构进行&nbsp;Anti-Debug&nbsp;<br />;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请用&nbsp;OllyDbg&nbsp;进行调试&nbsp;<br />;适用OS：Windows&nbsp;NT/2K/XP&nbsp;<br />;作者：罗聪&nbsp;<br />;日期：2003-2-9&nbsp;<br />;出处：<img alt="::URL::" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" hspace="2" /><a href="http://www.luocong.com%EF%BC%88%E8%80%81%E7%BD%97%E7%9A%84%E7%BC%A4%E7%BA%B7%E5%A4%A9%E5%9C%B0%EF%BC%89/" target="_blank">http://www.LuoCong.com（老罗的缤纷天地）</a> &nbsp;<br />;注意事项：如欲转载，请保持本程序的完整，并注明：&nbsp;<br />;转载自&#8220;老罗的缤纷天地&#8221;（<img alt="::URL::" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" hspace="2" /><a href="http://www.luocong.com%EF%BC%89/" target="_blank">http://www.LuoCong.com）</a> &nbsp;<br />;*********************************************************&nbsp;<br /><br />.386&nbsp;<br />.model&nbsp;flat,&nbsp;stdcall&nbsp;<br />option&nbsp;casemap:none&nbsp;<br /><br />include&nbsp;/masm32/include/windows.inc&nbsp;<br />include&nbsp;/masm32/include/kernel32.inc&nbsp;<br />include&nbsp;/masm32/include/user32.inc&nbsp;<br />includelib&nbsp;/masm32/lib/kernel32.lib&nbsp;<br />includelib&nbsp;/masm32/lib/user32.lib&nbsp;<br /><br />.data&nbsp;<br />szCaption&nbsp;&nbsp;db&nbsp;&nbsp;"Anti-Debug&nbsp;Demo&nbsp;by&nbsp;LC,&nbsp;2003-2-9",&nbsp;0&nbsp;<br />szDebugged&nbsp;&nbsp;db&nbsp;&nbsp;"Hah,&nbsp;let&nbsp;me&nbsp;guess...&nbsp;U&nbsp;r&nbsp;dEBUGGINg&nbsp;me!&nbsp;<img src="http://www.blogcn.com/images/smile.gif" alt="" border="0" hspace="2" vspace="2" />",&nbsp;0&nbsp;<br />szFine&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;"Good&nbsp;boy,&nbsp;no&nbsp;dEBUGGEr&nbsp;detected!",&nbsp;0&nbsp;<br /><br />.code&nbsp;<br />main:&nbsp;<br />&nbsp;&nbsp;assume&nbsp;&nbsp;fs:nothing<br />&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,&nbsp;fs:[30h]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;指向&nbsp;PDB(Process&nbsp;Database)<br />&nbsp;&nbsp;movzx&nbsp;&nbsp;eax,&nbsp;byte&nbsp;ptr&nbsp;[eax&nbsp;+&nbsp;2h]；无符号数带零扩展<br />&nbsp;&nbsp;or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;al,&nbsp;al<br />&nbsp;&nbsp;jz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_Fine<br />_Debugged:<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;MB_OK&nbsp;or&nbsp;MB_ICONHAND<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;szCaption<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;szDebugged<br />&nbsp;&nbsp;jmp&nbsp;&nbsp;&nbsp;&nbsp;_Output<br />_Fine:<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;MB_OK&nbsp;or&nbsp;MB_ICONINformATION<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;szCaption<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;szFine<br />_Output:&nbsp;<br />&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;NULL<br />&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;MessageBoxA<br />&nbsp;&nbsp;invoke&nbsp;&nbsp;ExitProcess,&nbsp;0<br />&nbsp;end&nbsp;main<br />第三道菜：利用SEH执行shellcode<br />假设异常处理例程入口00401053,程序刚开始执行时esp是0012ffc4,以前的fs:[0]是0012ffe0<br />建立了TIB结构的第一个成员后堆栈的情况如下:<br /><br />&nbsp;&nbsp;内存低地址<br />&nbsp;&nbsp;<br />|&nbsp;E0&nbsp;|12ffbc(esp)<br />|&nbsp;FF&nbsp;|<br />|&nbsp;12&nbsp;|&nbsp;&nbsp;--ERR结构的第一个成员<br />|_00_|<br />|&nbsp;53&nbsp;|12ffc0<br />|&nbsp;10&nbsp;|<br />|&nbsp;40&nbsp;|&nbsp;&nbsp;--ERR结构的第二个成员<br />|&nbsp;00&nbsp;|<br /><br />&nbsp;&nbsp;内存高地址<br /><br />&nbsp;&nbsp;好了然后程序CALL一个函数,函数里面有一个局部变量并且在往其分配的空间中写入的数据时产生溢出.这时堆栈如下<br /><br />____<br />|&nbsp;&nbsp;&nbsp;&nbsp;|12f000&nbsp;局部变量分配的空间,并且向12ffc0方向溢出了.<br />|&nbsp;&nbsp;&nbsp;&nbsp;|<br />....<br />....<br />|_EBP|12ffb4&nbsp;函数中保存老的EBP<br />|&nbsp;xx&nbsp;|<br />|&nbsp;xx&nbsp;|<br />|&nbsp;xx&nbsp;|<br />|_EIP|12ffb8&nbsp;call函数时EIP进栈<br />|&nbsp;xx&nbsp;|<br />|&nbsp;xx&nbsp;|<br />|_xx_|<br />|&nbsp;E0&nbsp;|12ffbc(esp)&nbsp;&nbsp;&nbsp;{当SEH起作用的时候EBX刚好指向这个地址(也可说总是指向当前ERR结构)}<br />|&nbsp;FF&nbsp;|<br />|&nbsp;12&nbsp;|&nbsp;&nbsp;--ERR结构的第一个成员<br />|_00_|<br />|&nbsp;53&nbsp;|12ffc0<br />|&nbsp;10&nbsp;|<br />|&nbsp;40&nbsp;|&nbsp;&nbsp;--ERR结构的第二个成员<br />|_00_|<br />|&nbsp;&nbsp;&nbsp;&nbsp;|12ffc4<br />&nbsp;&nbsp;&nbsp;继 续看,假设溢出代码一直到了12ffc4,然后call的函数该返回了,因为保存的EIP被溢出代码代替所以程序出错(不会不出错吧?),这样ESH开始 起作用了(注:在这期间系统要执行一些操作,所以EBX才会指向当前ERR).这样一来程序就会跳到12ffc0里的地址去执行!而12ffc0里的东东 早已不是原来的00401053了.这样我们不就改变了程序的流向了么.12ffc0中该写入什么内容呢?应是内存中JMP&nbsp;EBX的代码的地址.这样跳 了3下后最终就会跳到12ffbc去执行.这个四字节可是宝贵的啊<img src="http://www.blogcn.com/images/smile.gif" alt="" border="0" hspace="2" vspace="2" />现在假设JMP&nbsp;EBX这个指令在内存中的地址是0x77e33f4d<br />那下具体看一下现在堆栈的情况:<br /><br />|&nbsp;EB&nbsp;|12ffbc(esp)&nbsp;&nbsp;&nbsp;{当ESH起作用的时候EBX刚好指向这个地址(也可说总是指向当前ERR结构)}<br />|&nbsp;06&nbsp;|<br />|&nbsp;90&nbsp;|&nbsp;&nbsp;--ERR结构的第一个成员,执行JMP&nbsp;EBX后就到这儿来执行了(EB&nbsp;06是短跳转JMP&nbsp;12FFC4的机器码)<br />|_90_|&nbsp;&nbsp;后面的90是nop空指令的机器码.<br />|&nbsp;4D&nbsp;|12ffc0<br />|&nbsp;3F&nbsp;|<br />|&nbsp;E3&nbsp;|&nbsp;&nbsp;--ERR结构的第二个成员,出错处理函数的入口地址(现在成了JMP&nbsp;EBX的地址)<br />|_77_|<br />|&nbsp;&nbsp;&nbsp;&nbsp;|12ffc4<br />....<br /><br />&nbsp;&nbsp;好现在来看看12ffc4里面有些什么代码.(简单的说这段代码的作用是计算真正的shellcode的起始地址,然后跳过去执行.<br /><br />低地址<br /><br />|&nbsp;&nbsp;&nbsp;&nbsp;|12f000(shellcode开始地址)<br />....<br />....<br />|&nbsp;81&nbsp;|12ffc4<br />|&nbsp;C3&nbsp;|&nbsp;&nbsp;add&nbsp;ebx,FFFFF03Ch(ebx=12ffc4,指令长度6,作用计算计算shellcode地址)<br />|&nbsp;3C&nbsp;|<br />|&nbsp;F0&nbsp;|<br />|&nbsp;FF&nbsp;|<br />|&nbsp;FF&nbsp;|<br />|&nbsp;FF&nbsp;|12ffca&nbsp;jmp&nbsp;ebx<br />|&nbsp;D3&nbsp;|&nbsp;&nbsp;<br /><br />高地址<br /><br />&nbsp;<br />测试程序<br /><br />-------------------------SEH.ASM------------------<br />.386<br />.model&nbsp;flat,stdcall<br />option&nbsp;casemap:none<br /><br />include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;../include/user32.inc<br />includelib&nbsp;&nbsp;&nbsp;&nbsp;../lib/user32.lib<br />include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;../include/kernel32.inc<br />includelib&nbsp;&nbsp;&nbsp;&nbsp;../lib/kernel32.lib<br /><br /><br /><br />.data<br />hello&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;'利用一个读INI文件的API来演示WIN2000本地溢出',0<br />lpFileName&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;'./seh.ini',0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />lpAppName&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;'iam',0<br />lpKeyName&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;'czy',0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />lpDefault&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;'ddd',0<br />szCap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;"SEH&nbsp;TEST",0<br />szMsgOK&nbsp;db&nbsp;"OK,the&nbsp;exceptoin&nbsp;was&nbsp;handled&nbsp;by&nbsp;final&nbsp;handler!",0<br />szMsgERR1&nbsp;db&nbsp;"It&nbsp;would&nbsp;never&nbsp;Get&nbsp;here!",0<br /><br />.code<br /><br />testov&nbsp;&nbsp;&nbsp;&nbsp;proc<br />&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;&nbsp;&nbsp;lpReturnedString[2224]&nbsp;:&nbsp;byte&nbsp;&nbsp;&nbsp;&nbsp;;返回的字串搞成本地变量这样就和C语言一样了,它是在栈中&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;GetPrivateProfileString,offset&nbsp;&nbsp;&nbsp;&nbsp;lpAppName,offset，lpKeyName,offset&nbsp;lpDefault,ADDR&nbsp;lpReturnedString,2249,offset&nbsp;lpFileName&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;MessageBox,0,addr&nbsp;lpReturnedString,addr&nbsp;lpReturnedString,1<br />&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;<br />testov&nbsp;&nbsp;&nbsp;&nbsp;endp<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />start:<br />&nbsp;&nbsp;&nbsp;&nbsp;ASSUME&nbsp;fs:NOTHING<br />&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;MessageBox,0,addr&nbsp;szMsgERR1,addr&nbsp;szCap,30h+1000h&nbsp;;下断点&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;Final_Handler&nbsp;&nbsp;&nbsp;&nbsp;;压入正常的出错处理程序入口地址<br />&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;FS:[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;把前一个TIB的地址压入<br />&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;fs:[0],esp<br />&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;testov&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;pop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs:[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;还原FS:[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />Final_Handler:&nbsp;&nbsp;&nbsp;;由于溢出了下面的代码不会被执行.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox,0,addr&nbsp;szMsgOK,addr&nbsp;szCap,30h<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invoke&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExitProcess,0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax,1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret<br />end&nbsp;start<br /><br />-----------------end-------------<br /><br />1<img src="http://www.blogcn.com/images/smile.gif" alt="" border="0" hspace="2" vspace="2" />如何更好的在内存中找JMP&nbsp;EBX的代码:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在softice中执行S&nbsp;10:0&nbsp;L&nbsp;FFFFFFFF&nbsp;FF&nbsp;D3就可以了,但实际上这样找到的<br />地址可能不能执行代码.所以用下面的方法:<br />&nbsp;&nbsp;&nbsp;map32&nbsp;kernel32(在当前进程中查找映射的kernel32&nbsp;DLL的信息)&nbsp;&nbsp;&nbsp;<br />一般有如下显示:<br />&nbsp;&nbsp;Owner&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Obj&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;Obj#&nbsp;&nbsp;&nbsp;&nbsp;Address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TYPE<br />kernel32&nbsp;&nbsp;&nbsp;&nbsp;.text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0001&nbsp;&nbsp;&nbsp;&nbsp;001b:77b61000&nbsp;&nbsp;&nbsp;&nbsp;0005d1ae&nbsp;code&nbsp;RO<br />......<br />&nbsp;&nbsp;然后<br />S&nbsp;77b61000&nbsp;L&nbsp;5d1ae&nbsp;FF&nbsp;D3<br />如果显示如下说明找到了:<br />&nbsp;&nbsp;Pattern&nbsp;Found&nbsp;at&nbsp;0023:77e61674&nbsp;....<br /><br />2)关于缓冲区的大小的问题:<br />&nbsp;&nbsp;利用SEH的办法就起码要设成1000个字节多,你的shellcode才不会被不知哪来的数据覆盖!<br />这道菜czy做的不好吃：（我感觉理解起来有些困难~！因为关于缓冲区溢出自己接触的太少，不过好东西要保留的，以后回过头看！<br />第四道菜：用&nbsp;SEH&nbsp;技术实现&nbsp;API&nbsp;Hook<br />这一部分不想展开了，给大家一个链接吧。<br /><br /><img alt="::URL::" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" hspace="2" /><a href="http://www.luocong.com/articles/show_article.asp?Article_ID=25" target="_blank">http://www.luocong.com/articles/show_article.asp?Article_ID=25</a> <br /><br />最后作为结束语说说的缺点吧：）一个人只有正视自己的缺点才能不断地进步！呵呵<br />在 SEH异常处理链中最后一个被装载的SEH异常处理程序总是被第一个调用，想想如果自己花了一个星期才写出来一个异常处理程序，能够完美处理所有异常,并 希望异常全部由你来处理,但很不幸,比如你调用了一个外部模块,而这个模块自己安装了一个ugly的seh处理例程,他的动作是只要有异常发生就简单地终 止程序，哈哈，那就死悄悄了。又比如你想在你的加壳程序里面加密目标程序代码段,然后发生无效指令异常的时候用你自己安装的处理句柄来解密代码段继续执 行,听起来这的确是一个好主意,但遗憾的是大多数C/C++代码都用_try{}_except{}块来保证其正确运行,而这些异常处理例程是在你壳注册 的例程之后安装的,因而也就在链的前面,无效指令一执行,首先是C/C++编译器本身提供的处理例程或者程序其他的异常处理例程来处理,可能简单结束程序 或者....<br />好累！~~~~~~<br />写了两天，错了，应该是剪接+消化了两天，有很多的程序和文字是从hume,老罗，还有czy那里&#8220;剽窃&#8221;的：）希望高手们不要生气~~天下书籍一大抄。你们的必将是我的，当然我的也会共享给你们的。呵呵，现在还不行，级别不够啊。</div>转自:<div>http://blog.csdn.net/toberooter/article/details/308365</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-03-21 15:43 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/03/21/198679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>九种引人瞩目的开源大数据技术</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/03/19/198572.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 19 Mar 2013 01:59:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/03/19/198572.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198572.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/03/19/198572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198572.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198572.html</trackback:ping><description><![CDATA[<div><p><span style="font-family: 微软雅黑">越来越多的公司开始聚焦于大数据技术领域，而开源恰恰是大数据技术的灵魂。以下将为您介绍九大引人注目的开源大数据技术，请拭目以待：</span></p> <p><span style="font-family: 微软雅黑"><strong>1.Apache Hadoop</strong></span></p> <p><img style="cursor: pointer" alt="" src="http://cms.csdnimg.cn/articlev1/uploads/allimg/120615/120_120615112136_1.gif" height="136" width="535" border="0" />&nbsp;</p> <p><span style="font-family: 微软雅黑"><a href="http://hadoop.apache.org/">Apache hadoop</a>是 一个开源的分布式计算框架，最初由Doug为支持其开源Web搜索引擎Nutch所创立。通过集成MapReduce技术，Hadoop将大数据分布到多 个数据节点上进行处理。Hadoop遵循Apache  2.0许可证，可以轻松处理结构化、半结构化和非结构化数据，一举成为现在非常流行的大数据解决方案，</span></p> <p><strong><span style="font-family: 微软雅黑">2.R语言</span></strong>&nbsp;</p> <p><span style="font-family: 微软雅黑"><a href="http://www.r-project.org/">R语言</a>是一种开源编程语言，专门为数据统计和数据可视化而设计。R语言最初由Ross Ihaka和Robert Gentleman在奥克兰大学设计出来，之后迅速成为大数据领域的重要工具。R语言遵循GPL许可证。</span></p> <p><strong><span style="font-family: 微软雅黑">3.Cascading</span></strong></p> <p><img style="width: 537px; height: 140px; cursor: pointer" alt="" src="http://cms.csdnimg.cn/articlev1/uploads/allimg/120615/120_120615112912_1.png" height="277" width="688" border="0" /></p> <p><span style="font-family: 微软雅黑"><a href="http://www.cascading.org/">Cascading</a>是 一个针对Java开发人员的应用框架，可以快速、轻松地基于Apache  Hadoop开发数据分析和数据管理应用。Cascading是Hadoop的抽象层，可以屏蔽MapReduce的复杂性，支持任何基于JVM的编程语 言在Hadoop集群上执行数据处理任务。Cascading最初由Chris  Wensel开发，用于作为MapReduce的替代API。Cascading遵循GNU许可证，一般用于广告定位、日志分析、Web数据挖掘和ETL 应用。</span></p> <p><strong><span style="font-family: 微软雅黑">4.Scribe</span></strong></p> <p><span style="font-family: 微软雅黑"><a href="https://github.com/facebook/scribe">Scribe</a>于2008年发布，是一个由Facebook开发的日志聚合服务器软件，用于实时从大量服务器汇集日志数据。Scribe遵循Apache 2许可证，扩展性极佳，每天可应对数百亿日志记录的挑战。</span></p> <p><strong><span style="font-family: 微软雅黑">5.ElasticSearch</span></strong></p> <p><img style="width: 527px; height: 134px; cursor: pointer" alt="" src="http://cms.csdnimg.cn/articlev1/uploads/allimg/120615/120_120615113226_1.PNG" height="178" width="599" border="0" /></p> <p><span style="font-family: 微软雅黑"><a href="http://www.elasticsearch.org/">ElasticSearch</a>是一款由Shay Banon开发，遵循Apache许可证的开源搜索服务器。ElasticSearch基于分布式计算，对于实时搜索可以提供很好的可扩展性解决方案。许多公司已经对ElasticSearch表示认可，比如StumbleUpon和Mozilla。</span></p> <p><strong><span style="font-family: 微软雅黑">6.Apache HBase</span></strong></p> <p><span style="font-family: 微软雅黑"><a href="http://hbase.apache.org/">Apache HBase</a>是一个使用Java语言编写的、以谷歌BigTable技术为基础的开源非关系型列式分布数据库，可运行在HDFS文件系统之上。HBase提供了很好的存储容错能力和快速访问大量稀疏文件的能力。HBase遵循Apache 2许可证。</span></p> <p><strong><span style="font-family: 微软雅黑">7.Apache Cassandra</span></strong></p> <p><img style="cursor: pointer" alt="" src="http://cms.csdnimg.cn/articlev1/uploads/allimg/120615/120_120615113508_1.png" height="100" width="500" border="0" /></p> <p><span style="font-family: 微软雅黑"><a href="http://cassandra.apache.org/">Cassandra</a>是由Facebook开发的另一个开源NoSQL数据库，遵循Apache 2许可证。由于对HBa</span><span style="font-family: 微软雅黑">se的喜爱，Facebook开始逐渐放弃使用Cassandra，但许多公司，如Netflix依然使用Cassandra数据库为其后端流媒体服务提供动力。</span></p> <p><strong><span style="font-family: 微软雅黑">8.MongoDB</span></strong></p> <p><img style="cursor: pointer" alt="" src="http://cms.csdnimg.cn/articlev1/uploads/allimg/120615/120_120615112252_1.png" height="166" width="500" border="0" /></p> <p><span style="font-family: 微软雅黑"><a href="http://www.mongodb.org/">MongoDB</a>是 一个基于分布式文件存储的数据库，由C++语言编写。旨在为Web应用提供可扩展的高性能数据存储解决方案。MongoDB是非常流行的JSON文档式 NoSQL数据库，许多公司都非常认同MongoDB。MTV  Networks、craigslist和迪斯尼互动传媒集团，纽约时报以及Etsy都是MongoDB的客户。MongoDB遵循GNU  Affero通用许可证，语言驱动遵循Apache许可证，10gen公司提供商业化的MongoDB许可证。</span></p> <p><strong><span style="font-family: 微软雅黑">9.Apache CouchDB</span></strong></p> <p><span style="font-family: 微软雅黑"><a href="http://couchdb.apache.org/">CouchDB</a>也 是一个流行的开源NoSQL数据库，它以文档方式（JSON）存储数据。CouchDB使用JavaScript语言作为查询语言，集成 MapReduce技术。IBM Lotus Notes的开发人员Damien  Katz在2005年构建了CouchDB，用于大规模对象的数据存储系统。CouchDB遵循Apache  2许可证，英国广播公司（BBC）使用CouchDB存储动态内容，瑞士瑞信银行（Credit Suisse）的商品部也采用了它。</span></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-03-19 09:59 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/03/19/198572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 维护</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/28/198133.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 28 Feb 2013 03:15:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/28/198133.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198133.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/28/198133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198133.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198133.html</trackback:ping><description><![CDATA[<div><p>SSH配置：</p> <p>1、修改vi&nbsp;/etc/ssh/sshd_config，根据模板将要修改的参数注释去掉并修改参数值：</p> <p>Port 22 指定SSH连接的端口号，安全方面不建议使用默认22端口</p> <p>Protocol 2,1 允许SSH1和SSH2连接，建议设置成 Protocal 2</p> <p>其他参数根据自己的需要进行调整。配置方法详见：&nbsp;man ssh_config</p> <p>2、修改hosts.deny 在最后面添加一行：</p> <p>sshd:All</p> <p>3、修改hosts.allow 在最后面添加一行：</p> <p>sshd:All</p> <p>如果为了安装可以限制访问的IP，设置如下：</p> <p>sshd:192.168.0.101</p> <p>sshd:192.168.0.102</p> <p>上述配置表示只允许101和102的服务器进行SSH连接</p> <p>4、启动SSH</p> <p>/etc/init.d/sshd start</p></div><br /><div># chkconfig --list |grep sshd<br /><div>sshd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0:off&nbsp;&nbsp; 1:off&nbsp;&nbsp; 2:on&nbsp;&nbsp;&nbsp; 3:on&nbsp;&nbsp;&nbsp; 4:on&nbsp;&nbsp;&nbsp; 5:on&nbsp;&nbsp;&nbsp; 6:off</div></div><div>#chkconfig --level 2345 sshd on<br /><br />iptables<br /><div># Generated by iptables-save v1.4.7 on Tue Feb&nbsp; 7 19:06:20 2012<br />*filter<br />:INPUT ACCEPT [100:10222]<br />:FORWARD ACCEPT [0:0]<br />:OUTPUT ACCEPT [75:7016]<br />-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT<br />-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT<br />COMMIT<br /># Completed on Tue Feb&nbsp; 7 19:06:20 2012</div><br /><br /><div><div>（1）屏蔽所有端口&nbsp;</div> <div>（2）把SSH的缺省端口设置为56565&nbsp;</div> <div>（3）把56565、80、3306端口打开&nbsp;</div> <div>（4）把3306端口设置为只允许本机访问</div> <div>&nbsp;</div> <div>如果没有安装iptables的话，运行命令yum install iptables完成iptables安装</div> <div>&nbsp;</div> <div>初始化安装以后，显示为以下信息：</div> <div>&nbsp;</div> <div>[root@tp ~]# iptables -L -n</div> <div>&nbsp;</div> <div>Chain INPUT (policy ACCEPT)</div> <div>&nbsp;</div> <div>target prot opt source destination</div> <div>&nbsp;</div> <div>Chain FORWARD (policy ACCEPT)</div> <div>&nbsp;</div> <div>target prot opt source destination</div> <div>&nbsp;</div> <div>Chain OUTPUT (policy ACCEPT)</div> <div>&nbsp;</div> <div>target prot opt source destination</div> <div>（1）屏蔽所有端口</div> <div>&nbsp;</div> <div>[root@tp ~]# iptables -F</div> <div>[root@tp ~]# iptables -X</div> <div>[root@tp ~]# iptables -P INPUT DROP</div> <div>[root@tp ~]# iptables -P OUTPUT DROP</div> <div>[root@tp ~]# iptables -P FORWARD DROP</div> <div>当超出了IPTABLES里filter表里的两个链规则  (INPUT,FORWARD)时,不在这两个规则里的数据包怎么处理呢,那就是DROP(放弃)，有同学喜欢配置OUTPUT为accpet，因为如果 被入侵，对方可以使用服务器做为中转，发起攻击，也会产生大量的数据包，所以这里配置为DROP</div> <div>&nbsp;</div> <div>（2）把SSH的缺省端口设置为56565</div> <div>&nbsp;</div> <div>在修改ssh端口时，应先把要修改的端口号56565加入白名单</div> <div>&nbsp;</div> <div>[root@tp ~]# iptables -A INPUT -p tcp --dport 56565 -j ACCEPT</div> <div>[root@tp ~]# iptables -A OUTPUT -p tcp --sport 56565 -j ACCEPT</div> <div>[root@tp ~]# /etc/rc.d/init.d/iptables save</div> <div>[root@tp ~]# service iptables restart</div> <div>再修改端口号</div> <div>&nbsp;</div> <div>[root@linux ~]# vi /etc/ssh/sshd_config</div> <div>将"#Port 22"修改为"Port 56565"</div> <div>&nbsp;</div> <div>重启ssh服务</div> <div>&nbsp;</div> <div>[root@linux ~]# /etc/init.d/sshd restart</div> <div>Stopping sshd: [ OK ]</div> <div>Starting sshd: [ OK ]</div> <div>如果想看看sshd端口号是否修改成功的话，可以使用 netstat -an 命令查看一下或退出ssh使用新端口号登陆尝试。</div> <div>&nbsp;</div> <div>（3）把80端口打开</div> <div>&nbsp;</div> <div>[root@tp ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT</div> <div>[root@tp ~]# iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT</div> <div>[root@tp ~]# /etc/rc.d/init.d/iptables save</div> <div>[root@tp ~]# service iptables restart</div> <div>（4）把3306端口设置为只允许本机访问</div> <div>&nbsp;</div> <div>[root@tp ~]#/sbin/iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT</div> <div>[root@tp ~]#/sbin/iptables -A OUTPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT<br /><br /><div>http://gzjhj88.blog.51cto.com/1049760/629563<br /><div>http://www.redicecn.com/html/qita/20110331/243.html</div><div>http://wenku.baidu.com/view/94fadf1252d380eb62946d95.html<br /><br /><div>http://www.bugbeta.cn/?p=495</div><div>http://gzjhj88.blog.51cto.com/1049760/629563</div><div>http://gzjhj88.blog.51cto.com/1049760/315021</div></div></div></div></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-28 11:15 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/28/198133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>phonegap js 和 本地代码 调用原理(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 07:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198001.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198001.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198001.html</trackback:ping><description><![CDATA[<div><p><strong>iOS</strong><strong>：</strong>通过让本地代码拦截JavaScript中调用的 window.location=&#8221;gap://Class.method/args&#8221;命令，来实现从JavaScript到本地代码之间的通信。在本地 代码拦截该命令后，解析获取的参数，然后调用对应的类、方法并传递参数。对应的，使用 UIWebView.stringByEvaluatingJavaScriptFromString来实现本地代码调用JavaScript。</p><p><strong>Android</strong><strong>：</strong>通 过拦截JavaScript的prompt命令实现从JavaScript到本地代码的通信。JavaScript  prompt命令默认会弹出对话框，而PhoneGap的Android本地代码会拦截该对话框，并进一步取得JavaScript数据。相应 的，Android上的PhoneGap内部，使用Java实现了一个HTTP服务器，通过持久性的XHR连接，JavaScript可以不断轮询内部 XHR服务器存储的信息，从而实现了从Java到JavaScript方向的通信。</p><p><strong>BlackBerry 4.x</strong><strong>：</strong>JavaScript 与本地代码之间的唯一通信方式是通过document.cookie实现的。JavaScript设定Cookie，本地代码从Cookie中获取信息。 对应的，本地代码也可以设定Cookie，允许JavaScript从Cookie中获取本地代码信息。</p><p><strong>BlackBerry WebWorks</strong><strong>：</strong>新 的BlackBerry WebWorks  SDK更好地支持了Java与JavaScript之间的交互通信。通过ScriptEngine.addExtension，Java对象可以被暴露给 JavaScript，而对应的Java可以使用ScriptEngine.executeScript来调用JavaScript。</p><p><strong>Windows Phone 7</strong><strong>：</strong>在Windows Phone 7中，JavaScript通过window.external.Notify可以将信息发送给本地代码。而相应的，WebBrowser.InvokeScript允许本地代码调用JavaScript。</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 15:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浏览器探究——执行网页跳转 (转) </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 07:07:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197999.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197999.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197999.html</trackback:ping><description><![CDATA[<div><div id="article_content">  <p align="center">浏览器探究&#8212;&#8212;执行网页跳转</p> <p>Main线程中执行。</p> <p>UrlInputView</p> <p>控件UrlInputView执行OnEditorAction-&gt;finishInput</p> <p>/**</p> <p>&nbsp;*url/search input view</p> <p>&nbsp;*handling suggestions</p> <p>&nbsp;*/</p> <p>public class UrlInputView extendsAutoCompleteTextView</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;implements OnEditorActionListener,</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CompletionListener, OnItemClickListener, TextWatcher</p> <p>由此可见，UrlInputView即输入网址的那个控件，该控件包括输入URL和执行搜索输入。</p> <p>Controller</p> <p>在经过UrlInputView的处理后，会调用Controller.handleNewIntent。</p> <p>Controller是浏览器中最重要的类，作为整个浏览器的主控类。Controller中有IntentHandler，这里会调用IntentHandler.onNewIntent</p> <p>IntentHandler</p> <p>//Handle all browser related intents</p> <p>这里对一些特殊的URL做处理这里还包含了一些debug信息，比如&#8221;about:debug.dom.file"这种形式的网址。如果是普通的 url，不需要做特殊处理，则执行到最后执行Controller.loadUrlDataIn，即经过了IntentHandler后又回到了 Controller。</p> <p>Controller</p> <p>/**</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* Load UrlData into a Tab and update the title bar to reflect the new</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* load.&nbsp; Call this instead ofUrlData.loadIn directly.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* @param t The Tab used to load.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* @param data The UrlData being loaded.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;*/</p> <p>经过简单的处理，会把要加载的url作为参数调用被显示的tab，即执行Tab.loadUrl。这样看来Controller还只是个桥梁的作 用，把从UrlInputView得到的url，交给IntentHandler做处理，然后再把url交给Tab做实际的加载。</p> <p>Tab</p> <p>//Class for maintaining Tabs with a mainWebView and a subwindow.</p> <p>Tab作为一个窗口的抽象概念而存在，对一个窗口的操作都需要通过Tab来进入。另外有个TabControl用来管理所有的Tab.</p> <p>执行语句mMainView.loadUrl。这个mMainView是个WebView。从这终于进入了framework的webkit层了。</p> <p>WebView</p> <p>WebView作为Tab的核心控件，负责网页的真正的加载，显示等操作，是framework/webkit中最主要的类。通过Tab来找到WebView.</p> <p>在WebView.loadUrl-&gt;WebView.loadUrlImpl中会向WebViewCore发消息，</p> <p>WebViewCore</p> <p>该类在一个独立的线程中运行，该类主要通过Message，Handler的机制在WebView与WebViewCore之间通讯的，这里 WebView是在Main线程中，而WebViewCore是在单独的&nbsp;WebViewCoreThread线程中。WebViewCore是 framework/webkit核心类，它在单独的线程中来接收消息，每个消息相当于一个请求的任务，而这个WebViewCore相当于一个服务，它 在消息循环中不停的接收任务（消息），然后处理任务，然后再接收下一个任务（消息）。任务的执行很多是通过jni调用c层webkit来操作的。在c层 webkit有webkit/Source/WebKit/android/jni/WebViewCore.cpp与该java层的 WebViewCore对应。即这个WebViewCore是java层与c层的一个主要桥梁。</p> <p>在WebView.loadUrlImpl在执行了mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);则WebViewCore接收到LOAD_URL任务，执行对它的处理。</p> <p>WebViewCore中有BrowserFrame成员</p> <p>BrowserFrame</p> <p>BrowserFrame extends  Handler它也有很多JNI与C层的webkit的Webkit/Source/WebKit/android/jni /WebCoreFrameBridge.cpp对应。它用来处理页面的具体情况，即Frame，这个Frame是一个具体的页面的概念。</p> <p>WebViewCore.loadUrl会调用BrowserFrame.loadUrl。BrowserFrame会调用到WebCoreFrameBridge.cpp的LoadUrl。</p> <p>这里略去c层的处理部分。</p> <p>WebCoreFrameBridge.cpp的LoadUrl执行后会执行到WebCoreFrameBridge.cpp的loadStarted，这里又会回调BrowserFrame.loadStarted函数。</p> <p>/**</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* native callback</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* Indicates the beginning of a new load.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* This method will be called once for the main frame.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;*/</p> <p>即通过BrowserFrame的loadUrl在c层做处理后，又回调到BrowserFrame的loadStarted。</p> <p>这里在理一下，主线程中有Tab，Tab里有WebView。即WebView也是运行在主线程的。而WebView里有WebViewCore，WebViewCore又是运行在一个单独的线程里的。</p> <p>那么多个WebView是否就对应多个WebViewCore和多个WebViewCore线程呢？</p> <p>看下WebView，WebView的构造函数中会mWebViewCore= new WebViewCore(context, this,  mCallbackProxy,  javaScriptInterfaces);创建了WebViewCore对象，即每个WebView都有个WebViewCore对象。但是 WebViewCore中的WebCoreThread是一个静态的，即一个单例的。而这个WebCoreThread中运行的 privatestatic Handler sWebCoreHandler;也是个静态的。</p> <p>由此可见WebViewCore类本身就是个外壳，真正处理任务的是WebCoreThread及其里面的sWebCoreHandler，这个真 正处理任务的是静态的，只有一份，WebViewCore这个外壳只是沟通webView与WebCoreThread的桥梁，相当于一个代理类。是 WebCoreThread提供给外面的处理接口。</p> <p>那么BrowserFrame呢？在WebViewCore的构造最后会发送一个INITIALIZE的消息给 WebCoreThread，WebCoreThread接收到后会执行WebViewCore.initialize，这个函数会构造 mrowserFrame。即每次构造WebViewCore时同样会构造一个BrowserFrame。但是为什么不在主线程中创建呢？一方面它是继承 自Handler，这个Handler需要在WebViewCoreThread线程中运行，所以需要在该线程来创建。另一方面在它的构造中需要创建 JWebCoreJavaBridge这个是C层的类，貌似这个类也需要在WebViewCoreThread线程中创建和销毁才行。</p> <p>由上分析可知，WebView包含一个WebViewCore，WebViewCore包含一个BrowserFrame。多个 WebViewCore共同对应唯一的一个WebCoreThread。WebViewCore只是个外壳，WebCoreThread作为任务的处 理，WebCoreThread主要就是个大Handler不停的处理接收到的任务，WebCoreThread会调用很多jni来调用webkit接 口，BrowserFrame也有很多jni来调用webkit接口。由他们的组成情况又可知WebCoreThread直接调的jni是多个 WebView共同的，即不跟具体的WebView相关，而通过BrowserFrame调用的则跟一个具体的WebView相关了。</p> <p>CallBackProxy</p> <p>/**</p> <p>&nbsp;*This class is a proxy class for handling WebCore -&gt; UI thread messaging. All</p> <p>&nbsp;*the callback functions are called from the WebCore thread and messages are</p> <p>&nbsp;*posted to the UI thread for the actual client callback.</p> <p>&nbsp;*/</p> <p>/*</p> <p>&nbsp;*This class is created in the UI thread so its handler and any private classes</p> <p>&nbsp;*that extend Handler will operate in the UI thread.</p> <p>&nbsp;*/</p> <p>class CallbackProxy extends Handler {</p> <p>另外还有个类CallBackProxy。它存在于WebView，WebViewCore，BrowserFrame中。在WebView构造函 数中创建，并在WebViewCore和BrowserFrame构造函数中作为参数传入并赋值给它们内部的引用。可见CallBackProxy是 WebViewCore和BrowserFrame向WebView回调的桥梁。</p> <p>CallBackProxy是一个Handler，它在主线程中被创建，即WebViewCore和BrowserFrame会通过发消息的方式将 需求传递到主线程的CallBackProxy中，CallBackProxy的事件处理循环会执行相应的处理。可见主线程中WebView通过 WebViewCore发消息给WebViewCoreThread线程执行操作，WebViewCoreThread线程又会通过 CallBackProxy回调消息给主线程执行处理。</p> <p>再回到BrowserFrame.loadStarted处。</p> <p>BrowserFrame.loadStarted会调用 CallBackProxy.onPageStarted，CallBackProxy.onPageStarted中会给发PAGE_STARTED消 息，主线程中的CallBackProxy的handleMessage会执行处理。在处理时会执行 WebViewClient.onPageStarted。</p> <p>WebViewClient</p> <p>mWebViewClient本身只是提供一个接口基类，Tab中private finalWebViewClient mWebViewClient = new WebViewClient()</p> <p>// WebViewClient implementation for themain WebView</p> <p>//Set the WebViewClient that will receivevarious notifications and requests. This will replace the current handler.</p> <p>这个WebViewClient会传给Tab中的WebView的CallbackProxy。这个WebViewClient会让CallbackProxy返回信息或回调处理给Tab。</p> <p>回到WebViewClient.onPageStarted，这里做了一些判断处理后，调用WebViewController.onPageStarted。</p> <p>WebViewController</p> <p>//WebView aspect of the controller</p> <p>public interface WebViewController</p> <p>在Tab的构造时，WebViewController会作为参数传入，并设置给Tab。那么Tab中的WebViewController到底是什么？Tab是在TabController中创建的，而Tab构造时传入的是Controller。</p> <p>public class Controller implementsWebViewController, UiController</p> <p>由此可见Tab中的WebViewController其实就是对应Controller。只是通过WebViewController接口作为引用的。即Tab中只关心Controller的WebViewController接口部分。</p> <p>这样就可以看出BrowserFrame通过消息与主线程中的CallbackProxy处理循环关联，CallbackProxy又通过 WebViewClient与Tab关联，回调了Tab提供的接口，而Tab又通过WebViewController接口，调用了Controller 这个核心类的函数。即调用到WebViewController.onPageStarted，也即是 Controller.onPageStarted.</p> <p>Controller.onPageStarted中一个主要的处理是</p> <p>if (!mNetworkHandler.isNetworkUp())  {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;view.setNetworkAvailable(false);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}这里判断网络是否是激活状态，如果不是激活 状态则执行WebView.SetNetworkAvailable(Boolean networkUp)</p> <p>/**&nbsp;&nbsp;&nbsp;&nbsp; * Inform WebView ofthe network state. This is used to  set&nbsp;&nbsp;&nbsp;&nbsp;* the JavaScript property window.navigator.isOnline and&nbsp;&nbsp;&nbsp;&nbsp; *  generates the online/offline event asspecified in HTML5, sec. 5.7.7&nbsp;&nbsp;&nbsp;&nbsp;  *@param networkUp boolean indicating if network is  available&nbsp;&nbsp;&nbsp;&nbsp; */</p> <p>该函数其实就是像WebViewCore发送SET_NETWORK_STATE消息，好吧，又回到了WebViewCoreThread线程了， 处理的方式是直接BrowserFrame.sJavaBridge.setNetworkOnLine。这个函数是个jni函数，其调用的是c层 JavaBridge的函数。这个jni函数主要就是通知c层WebCore网路状态已经变化，并把最新的网络状态告诉WebCore。</p> <p>由此可见WebView.setNetworkAvailable还是个挺重要的函数，通过它才能告诉底层网络的状态。</p> <p>那么额外看下网络状态如何获取并传递的，在loadUrl发起加载url这块判断了一次，即当无网络时主动通知一次。其他的呢？</p> <p>在NetworkStateHandler中会注册一个BroadcastReceiver，该receiver会关注 ConnectivityManager.CONNECTIVITY_ACTION广播，该广播是在网络发生连接变化时被发出，该receiver在接收 到网络连接变化的广播后，会查询当前的连接情况，然后执行NetworkStarteHandler.onNetworkToggle，这个函数里面就会 调用WebView.setNetworkAvailable，也即跟上述描述的那样，给WebViewCoreThread线程发消息，通知c层 WebCore网络的最新状态。</p> <p>这样就清楚了，网络广播时会通知C层最新状态，在执行loadUrl时，如果网络不可用也会通知C层网络最新状态。</p> <p>这里先跨过Controller.onPageStarte的其他处理过程。此次任务处理完毕。</p> <p>此时WebViewCoreThread线程中BrowserFrame仍然处于c层的LoadUrl中，此时的调用栈为:</p> <p>BrowserFrame.nativeLoadUrl</p> <p>BrowserFrame.loadUrl</p> <p>WebViewCore.loadUrl</p> <p>这里又会回调BrowserFrame.shouldInterceptRequest，它会调用BrowserFrame.inputStreamForAndroidResource函数</p> <p align="left">&nbsp;/**<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get&nbsp;the&nbsp;InputStream&nbsp;for&nbsp;an&nbsp;Android&nbsp;resource<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;There&nbsp;are&nbsp;three&nbsp;different&nbsp;kinds&nbsp;of&nbsp;android&nbsp;resources:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;file:///android_res<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;file:///android_asset<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;content://<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;url&nbsp;The&nbsp;url&nbsp;to&nbsp;load.<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;An&nbsp;InputStream&nbsp;to&nbsp;the&nbsp;android&nbsp;resource<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ </p> <p>这个函数会对几种特殊的url做不同的处理，当输入一个标准的http的url时，该函数不起什么作用。</p> <p>BrowserFrame.shouldInterceptReques接下来会调用 CallbackProxy.shouldInterceptRequest，看到调用CallbackProxy的函数，基本上就是要发消息给主线程让 主线程去处理任务了，这里发送了LOAD_RESOURCE消息，主线程接收后执行WebViewClient.onLoadResource。回到 BrowserFrame.nativeLoadUrl处，此时这个jni的函数终于执行完毕，也不再回调其他函数了，该函数完 成，WebViewCoreThread线程执行完LoadUrl的处理。</p> <p>当没有连接网络时，有个单独的线程会执行JWebCoreJavaBridge.signalServiceFuncPtrQueue这个JNI的 回调函数，该回调函数会发FYBCPTR_MESSAGE消息给WebViewCoreThread线程，但处理函数是 JWebCoreJavaBridge.handle，由此可见WebViewCoreThread线程不仅仅有一个Handler在处理事件.</p> <p>JWebCoreJavaBridge</p> <p>JWebCoreJavaBridge extends Handler  可见JWebCoreJavaBridge也是个Handler也是在WebViewCoreThread线程中运行的，只是发送消息的线程不是主线程， 是另一个单独的线程，并且消息的发送来源是JNI的回调。</p> <p>JWebCoreJavaBridge对应的JNI是webkit/Source/WebKit/android/jni/JavaBridge.cpp的函数。</p> <p>JWebCoreJavaBridge处理FYBCPTR_MESSAGE消息时会调用一个JNI函数，在JNI函数里又会回调BrowserFrame.reportError。</p> <p>又是跟上面类似的流程，BrowserFrame.reportError调用CallbackProxy.onReceiveError，这个 CallbackProxy里会发消息REPORT_ERROR，然后主线程接收消息，执行 WebViewClient.onReceivedError。</p> <p>接着又是收到FUNCPTR_MESSAGE消息，调用nativeServiceFuncPtrQueue，但是这里回调了 BrowserFrame.loadStarted，然后的处理流程跟上述的LoadUrl中调用BrowserFrame.loadStarted过程 一样。</p> <p>接着WebViewCoreThread线程又是收到FUNCPTR_MESSAGE消息，调用 JWebCoreJavaBridge.nativeServiceFuncPtrQueue，WebViewCore.contentDraw被调用， 该函数发送WEBKIT_DRAW，处理该消息会执行绘制的操作。</p> <p>接着WebViewCoreThread线程中JWebCoreJavaBridge.handleMessage又被调用，还是 FUNCPTR_MESSAGE消息，仍然是调用nativeServiceFuncPtrQueue。但此时BrowserFrame收到 loadFinished的回调，发PAGE_FINISHED消息，主线程接收消息处理时会执行WebView.onPageFinished和 WebViewClient.onFinished.</p>  </div></div><div>http://blog.csdn.net/hxwwf/article/details/7281318</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 15:07 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse 4.2 aptana</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197992.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197992.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197992.html</trackback:ping><description><![CDATA[<div> 	<div id="cnblogs_post_body"><p>1、使用软件更新的方式：</p> <p>打开Eclipse -&gt; Help -&gt; Install New Software 然后在弹出对话框的 Work with 框中输入如下的地址，回车。</p> <p>http://update.aptana.com/update/studio/3.2/</p> <p>然后就会一步步选择需要安装的组件即可。</p> <p>2、在Eclipse 4.2 上安装 Aptana 3.2遇到的错误，提示找不到&nbsp;org.eclipse.update.ui 0.0.0</p> <p>通过google（这种时候记得别使用百度），看到有同样的问题：</p> <p>http://boards.developerforce.com/t5/General-Development/Trouble-with-Force-com-IDE-installation-in-Eclipse-4-2/m-p/480891#M73687</p> <p>&nbsp;</p> <p>其中的有人回答：</p> <div lia-quilt-row-main"=""> <div lia-quilt-column-20="" lia-quilt-column-right=""  lia-quilt-column-main-right"=""> <div lia-quilt-column-alley-right"=""> <div id="messagebodydisplay_4"  lia-component-body"=""> <div>Hi, After i am downloadinng  org.eclipse.update.ui_3.2.300.v20100512.jar and  org.eclipse.update.ui.source_3.2.300.v20100512.jar files from the below  site and placed it under eclipse/plugins directory and it worked for me.<a href="http://grepcode.com/snapshot/repository.grepcode.com/java/eclipse.org/3.6/org.eclipse.update/ui/3.2...." rel="nofollow" target="_blank">http://grepcode.com/snapshot/repository.grepcode.com/java/eclipse.org/3.6/org.eclipse.update/ui/3.2....</a>&nbsp;thanks, Ravi</div> </div> </div> </div> </div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"="">按照提示的这个网址，去下载 ui组件，放置到eclipse目录的 plugins 之中，重启eclipse，再次安装即可成功。</div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"="">注：Eclipse 4.2的update  ui，在这里：http://grepcode.com/search /?r=repository.grepcode.com$java$eclipse.org$4.2&amp;start=20&amp;query=org.eclipse.update+ui+3.2....&amp;entity=project</div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"=""><strong>另外如果要安装Aptana直接输入：http://download.aptana.com/studio3/plugin/install 进行更新即可。</strong></div></div></div><br /><div><div lia-component-message-header"=""> 					<div lia-quilt-row-standard"=""> 	 						<div lia-quilt-column-20=""  lia-quilt-column-left"=""> 	<div lia-quilt-column-alley-left"=""> 		 							 		<div> 			<img title="Solution!" id="display_5" src="http://sforce.i.lithium.com/skins/images/AB7BE5A46312549054BBC94CA9D2261C/base/images/message_type_solution.png" alt="" /> 			 			 			 			 			<h1>Re: Trouble with Force.com IDE installati<wbr>on in Eclipse 4.2</h1> 			<span> 				 				 			</span> 		</div> 	 						 	</div> </div> 						<div lia-quilt-column-04=""  lia-quilt-column-right"=""> 	<div lia-quilt-column-alley-right"=""> 		 							 		<div> 			<div lia-menu-action=""  message-menu"="" id="actionMenuDropDown_3">	 	<div> 		<div><a default-menu-option="" lia-js-click-menu=""  lia-link-navigation"="" id="dropDownLink_3" href="http://boards.developerforce.com/t5/General-Development/Trouble-with-Force-com-IDE-installation-in-Eclipse-4-2/td-p/477651#">Options</a> 			<div> 				<div> 					 	  				</div> 			</div> 		</div> 	</div> </div> 		</div> 	 						 	</div> </div> 					 </div> 				</div> 			  	 				<p lia-message-post-date=""  lia-component-post-date-last-edited"=""> 					 		 <span lia-message-posted-on=""  lia-component-common-widget-date"="">  	 		 		 		&#8206;08-09-2012 	 		 		10:06 AM 	 	  	 	 	 	 	 	 	 	 	 	 	 	 </span> 	 				</p> 			  	 				<div id="messagebodydisplay_2"> 	 		<div> 			 				<p>Update:</p><p>&nbsp;</p><p>In the post I linked above:&nbsp;<a href="http://boards.developerforce.com/t5/General-Development/Install-Eclipse-Juno-4-2-with-Force-com-IDE/m-p/480771#M73674" target="_blank">http://boards.developerforce.com/t5/General-Develo<wbr>pment/Install-Eclipse-Juno-4-2-with-Force-com-IDE/<wbr>...</a>, there's been a solution that worked for me.</p><p>&nbsp;</p><p>To Quote Zokito:</p><p>&nbsp;</p><div lia-component-message-header"=""><div lia-quilt-row-standard"=""><div lia-quilt-column-20=""  lia-quilt-column-left"=""><div lia-quilt-column-alley-left"=""><div><em>08-09-2012&nbsp;09:04 AM</em></div></div></div></div></div><div lia-component-body"=""><div><p><em>Hi,</em></p><p><em>&nbsp;</em></p><p><em>cause of the problem lies here:</em></p><p><em>&nbsp;</em></p><p><em><a href="http://www.eclipse.org/eclipse/development/porting/4.2/incompatibilities.html" target="_blank" rel="nofollow">http://www.eclipse.org/eclipse/development/porting<wbr>/4.2/incompatibilities.html</a></em></p><p><em>(search for&nbsp;org.eclipse.update.ui)</em></p><p><em>&nbsp;</em></p><p><em>It  should be possible to fetch the deependency automatically through the  marketplace but for me it's not working.... so what would you need to do  is install the&nbsp;<strong>org.eclipse.update.ui&nbsp;</strong>manually from e.g.</em></p><p><em><a href="http://www.java2s.com/Code/Jar/o/Downloadorgeclipseupdateui32300v20100512jar.htm" target="_blank" rel="nofollow">http://www.java2s.com/Code/Jar/o/Downloadorgeclips<wbr>eupdateui32300v20100512jar.htm</a></em></p><p><em>&nbsp;</em></p><p><em>&nbsp;</em></p><p><em>extract it and than copy the jar file to your eclipse/plugins/ directory.&nbsp;</em></p><p><em>Start Eclipse again and then try to install the Force IDE plugin.</em></p><p><em>&nbsp;</em></p><p><em>&nbsp;</em></p><p><em>this solved the issue for me</em></p><p>&nbsp;</p><p>Hope this is helpful!</p><p>&nbsp;</p><p>Kelly</p></div></div> 			 			 				 			 		</div> 		 		 		 		 		 		 		 	 </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 10:25 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android root权限获取大揭秘(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 20 Feb 2013 08:07:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197955.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197955.html</trackback:ping><description><![CDATA[<div><div> 				   <div id="content"> <p><a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://os-android.liqucn.com/" target="_blank">android</a> <a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/rj/18902.shtml" target="_blank">root</a>权限获取的教程有很多，为了让大家更进一步的了解root的奥秘所在，灵客风特为您奉献本文，希望对您有所帮助。</p> <p>Android的<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/" target="_blank">应用</a>程序入口肯定是<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://os-java.liqucn.com/" target="_blank">java</a>程序。应用程序的启动者是由<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/rj/c/298/" target="_blank">系统</a>临时根据Androidmanifest.xml中定义的权限而创建的临时用户。而不像linux那样是使用登陆者的身份启动，从而使得进程具有登陆者的所有权限。这也是Android的安全机制之一。</p> <p>新的权限机制也带来新的问题，Android给应用程序的权限是按功能来分，java虽然可以访问文件系统。但由于应用程序本身是临时用户启动，这个临时用户权限十分有限。因此诞生了&lt;<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/article/39745.shtml" target="_blank">越狱</a>/root机器&gt;这样的产物。</p> <p>其实root机器不是真正能让你的应用程序具有root权限。它原理就跟linux下的像sudo这样的命令。在系统的bin目录下放个su程序并属主是root并有suid权限。则通过su执行的命令都具有Android root权限。</p> <p>Su的源代码网上也有，有兴趣的同学去google下。</p> <p>当然使用临时用户权限想把su拷贝的/system/bin目录并改属性并不是一件容易的事情。这里用到2个工具跟2个命令。工具就是busybox。不熟悉的同学可以去网上google下。这个太有名了我就不多说了。</p> <p>把busybox拷贝到你有权限访问的目录然后给他赋予4755权限，你就可以用它做很多事了。</p> <p>当然busybox只能不能提升权限，真正提升权限的是ratc这个程序，这个程序中一键root包里面可以找到，作用是rooting在adb的shell。</p> <p>网上介绍Ratc的文章不多，它是rage against the cage  的缩写。是真正的提升权限的破解程序。虽然我没看过源代码，但估计是利用adb源代码部分内容来实现的，原理估计跟模拟器使用adb  shell登陆可以获得root shell差不多。（因为它运行需要adb连接才会成功）。</p> <p>使用busybox前先运行ratc，这样运行busybox的UID将是0，也就是root。</p> <p>首先把system目录改成可读性的：busybox mount -o remount,rw /system，</p> <p>当然你还不能改下面的文件，因为system下文件的所有者都不是你。</p> <p>但你可以偷梁换柱把system下的目录给换掉。</p> <p>使用命令Busybox mount -t tmpfs none /system/xbin，呵呵这下xbin目录你随便写了。</p> <p>将su跟busybox弄过去cp /data/data/xxx/su /system/xbin。然后赋权限chmod 4755 /system/xbin/su。</p> <p>然后使目录生效busybox --install -s /system/xbin，</p> <p>别忘善后busybox mount -o remount,ro /system去掉system可写。</p> <p>这样只是临时的，只能用su跟busybox能执行一些原来系统没有权限执行的命令而已。当系统重启后/system/xbin又变为原来的文件。 真正要改系统的话需要自己写内核代码（相当于windows的驱动程序）。内核文件拥有所有权限。使用busybox命令insmod  /data/data/xxx/xxx.ko装载内核文件，你想干嘛就可以干嘛了。</p> <p>当然我们不是搞破解的没必要去改别人的机器，我们只是想让自己应用程序具有root权限而已。所以临时的su就可以了。我们用c++写一个可执行文 件。使用socket可以跟java的程序通讯。然后将需要使用root权限才能执行的代码放在c++程序里，然后java程序中创建新的su进程，将 c++程序带全路径作为参数1。启动后就可以通过socket调用c++函数去执行你想干的事了。</p> <p>最后程序执行完了别忘了善后busybox umount /system/xbin。</p> <p>最后说说要注意的事情，如果机器已经拥有Android root权限的话就不需要做这些事情了，但root过的机器都有装有个权限管理的程序。会弹出对话框。但这个程序管理能力有限，如果不想让他弹出的话。也许可以通过改su文件名来解决。有兴趣的同学不妨试试。</p></div>							</div></div><br /><div><div id="article_content">  <span style="font-size:18px">现在Android系统的root破解基本上成为大家的必备技能！网上也有很多中一键破解的 软件，使root破解越来越容易。但是你思考过root破解的原理吗？root破解的本质是什么呢？难道是利用了Linux  kernal的漏洞吗？本文将简单对root的破解原理进行分析。</span> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 网上有一篇文章已经对root破解的基本原理进行了简单介绍，大家可以先参考一下《</span><a href="http://hi.baidu.com/%CF%B1%B8%BE%C2%B1%C3%E6/blog/item/14c5dc296003ce225243c170.html" target="_blank"><span style="font-size:18px">android root权限破解分析</span></a><span style="font-size:18px">》，本文只能说对root原理进行了方向性的描述，但是在一些具体的方面没有描述清楚。本文将会对其进行一些必要的扩展和补充。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 如果你进行过程序开发，在root过的手机上面获得root权限的代码如下：</span> </p> <div id="codeSnippetWrapper" style="border-bottom:silver 1px solid; text-align:left; border-left:silver 1px solid; padding-bottom:4px; line-height:12pt; background-color:#f4f4f4; margin:20px 0px 10px; padding-left:4px; width:97.5%; padding-right:4px; font-family:'Courier New',courier,monospace; direction:ltr; max-height:200px; font-size:8pt; overflow:auto; border-top:silver 1px solid; border-right:silver 1px solid; padding-top:4px"> <div id="codeSnippet" style="border-bottom-style:none; text-align:left; padding-bottom:0px; line-height:12pt; background-color:#f4f4f4; border-left-style:none; padding-left:0px; width:100%; padding-right:0px; font-family:'Courier New',courier,monospace; direction:ltr; border-top-style:none; color:black; border-right-style:none; font-size:8pt; overflow:visible; padding-top:0px"> <div bg_java"=""><div><div><strong>[java]</strong> <a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="view plain">view plain</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="copy">copy</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="print">print</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="?">?</a></div></div><ol start="1"><li><span>Runtime.getRuntime().exec("su");&nbsp;DataOutputStream&nbsp;os&nbsp;=&nbsp;new&nbsp;DataOutputStream(process.getOutputStream());&nbsp;&nbsp;</span></li><li>......&nbsp;&nbsp;</li><li>os.writeBytes(<span>"exit\n");&nbsp;&nbsp;</span></li><li>os.flush();&nbsp;&nbsp;</li></ol></div></div> </div> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 从上面代码我们可以看到首先要运行su程序，其实root的秘密都在su程序中，《</span><a href="http://hi.baidu.com/%CF%B1%B8%BE%C2%B1%C3%E6/blog/item/14c5dc296003ce225243c170.html" target="_blank"><span style="font-size:18px">android root权限破解分析</span></a><span style="font-size:18px">》中讲到Android系统默认的su程序只能root和shell可以用运行su，这个是安全的。如果把这个限制拿掉，就是root破解了！</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 下面我们仔细分析一下程序是怎样获得root权限的，如果对Linux的su命令熟悉的朋友可能知道su程序都设置SUID位，我们查看一下我的手机（已经root破解）上的su权限设置，</span></p> <p><img src="http://api.photoshop.com/v1.0/accounts/a6dba90e84ba45f8aa3ec8f7953a00d0/assets/8e179ed1b58e45e68b843c3cfe37788d" alt="" height="121" width="649" /> </p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们发现su的所有者和所有组都是root，是其实是busybox的软链接，我们查看busybox的属性发现，其设置了SUID和SGID，并且所有者和所有组都是root。SUID和SGID的作用是什么呢？如果你不太清楚，请参考《</span><a href="http://my.unix-center.net/%7ESimon_fu/?p=607"><span style="font-size:18px">Linux进程的实际用户ID和有效用户ID</span></a><span style="font-size:18px">》，这样运行busybox的普通用户，busybox运行过程中获得的是root的有效用户。su程序则是把自己启动一个新的程序，并把自己权限提升至root（我们前面提到su其实就是busybox，运行期它的权限是root，当然也有权限来提升自己的权限）。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 再强调一下不光root手机上su需要设置SUID，所有的Linux系统上的su程序都需要设置SUID位。请参考一下UC服务器的su的权限情况：</span></p> <p><img src="http://api.photoshop.com/v1.0/accounts/a6dba90e84ba45f8aa3ec8f7953a00d0/assets/96ceaa76358442fe96cb08297e77a53d" alt="" height="69" width="446" /> </p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 我们发现su也设置了SUID位，这样普通用户也可以运行su程序，su程序会验证root密码，如果正确su程序可以把用户权限提高的root（因为其设置SUID位，运行期是root权限，这样其有权限提升自己的权限）。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;  这样我们就可以看出其实Android系统的破解的根本原理就是替换掉系统中的su程序，因为系统中的默认su程序需要验证实际用户权限（只有root和 shell用户才有权运行系统默认的su程序，其他用户运行都会返回错误）。而破解后的su将不检查实际用户权限，这样普通的用户也将可以运行su程序， 也可以通过su程序将自己的权限提升。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;  到这里大家对root破解不感到神秘了吧。root破解没有利用什么Linux内核漏洞（Linux内核不可能有这么大的漏洞存在），可以理解成root 破解就是在你系统中植入&#8220;木马su&#8221;，说它是&#8220;木马&#8221;一点儿都不为过，假如恶意程序在系统中运行也可以通过su来提升自己的权限的这样的结果将会是灾难性 的。所以一般情况下root过手机都会有一个SuperUser应用程序来让用户管理允许谁获得root权限，也算是给系统加了一层保险吧！ </span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 如上是Simon的个人对root破解的一些认识，如果有错误的地方，欢迎朋友们指正.</span></p>  </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-20 16:07 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[CyanogenMOD移植教程]第二章：android 源码总体结构 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 20 Feb 2013 06:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197952.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197952.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197952.html</trackback:ping><description><![CDATA[<div><div style="text-indent: 2em;">&#8211; Makefile (全局的Makefile文件)</div> <div style="text-indent: 2em;">&#8211; bionic (Bionic含义为仿生,这里面是一些基础的C库源代码)</div> <div style="text-indent: 2em;">&#8211; bootloader (引导加载器)</div> <div style="text-indent: 2em;"> build目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)</div> <div style="text-indent: 2em;">&#8211; build (build目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)</div> <div style="text-indent: 2em;">&#8211; cts (Android兼容性测试套件标准)</div> <div style="text-indent: 2em;">&#8211; libcore (核心库相关)</div> <div style="text-indent: 2em;">Dalvik虚拟机 针对嵌入式设备优化的Java</div> <div style="text-indent: 2em;">Java虚拟机)</div> <div style="text-indent: 2em;">&#8211; dalvik ( Dalvik虚拟机,针对嵌入式设备优化的Java虚拟机)</div> <div style="text-indent: 2em;">&#8211; development (创建应用程序所需要的模板和工具)</div> <div style="text-indent: 2em;">qcom,</div> <div style="text-indent: 2em;">&#8211; device (与具体设备相关的一些编译脚本和库,如htc,qcom,samsung等)</div> <div style="text-indent: 2em;">&#8211; external (Android使用的一些外部的开源框架和库)</div> <div style="text-indent: 2em;">(应用程序的框架层,SDK</div> <div style="text-indent: 2em;">SDK的接口基本都是在这里实现的)</div> <div style="text-indent: 2em;">&#8211; frameworks (应用程序的框架层,SDK的接口基本都是在这里实现的)</div> <div style="text-indent: 2em;">&#8211; hardware (与硬件相关的库)</div> <div style="text-indent: 2em;">Linux2.6</div> <div style="text-indent: 2em;">&#8211; kernel (Linux2.6的内核源代码)</div> <div style="text-indent: 2em;">&#8211; ndk (本地开发套件--C语言开发套件)</div> <div style="text-indent: 2em;">--C</div> <div style="text-indent: 2em;">Android的各种应用程序)</div> <div style="text-indent: 2em;">&#8211; packages (Android的各种应用程序)</div> <div style="text-indent: 2em;">&#8211; prebuilt (Android在各种平台下编译的预置脚本)</div> <div style="text-indent: 2em;">&#8211; sdk (SDK及模拟器)</div> <div style="text-indent: 2em;">Android的底层的一些库)</div> <div style="text-indent: 2em;">&#8211; system (Android的底层的一些库)</div> <div style="text-indent: 2em;">`&#8211; vendor (厂商私有的代码)</div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div> <div style="text-indent: 2em;"> <div>packages/</div> <div>|&#8211; apps (各种应用程序,如联系人、浏览器等)</div> <div>|&#8211; experimental (一些实验性的项目,如错误报告)</div> <div>|&#8211; inputmethods (输入法相关)</div> <div>|&#8211; providers (各种数据源实现,如联系人数据、媒体库等信息)</div> <div>|&#8211; wallpapers (各种壁纸程序)</div> </div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div>  <div style="text-indent: 2em;">Android Framework功能介绍</div> <div style="text-indent: 2em;">android.app :提供高层的程序模型和基本的运行环境。</div> <div style="text-indent: 2em;">android.content :包含对各种设备上的数据进行访问和发布。</div> <div style="text-indent: 2em;">android.database :通过内容提供者浏览和操作数据库。</div> <div style="text-indent: 2em;">android.graphics :底层图形库,包含画布、点、矩形等,可以将其直接绘制到屏幕上。</div> <div style="text-indent: 2em;">android.location :定位和相关服务的类。</div> <div style="text-indent: 2em;">android.media :提供一些类管理多种音频、视频的媒体接口。</div> <div style="text-indent: 2em;">android.net :提供帮助网络访问的类,超过通常的 java.net.* 接口。</div> <div style="text-indent: 2em;">android.os :提供了系统服务、消息传输和 IPC 机制。</div> <div style="text-indent: 2em;">android.opengl :提供 OpenGL 的工具。</div> <div style="text-indent: 2em;">android.provider :提供访问 Android 内容提供者的类。</div> <div style="text-indent: 2em;">android.telephony :提供与拨打电话相关的 API 交互。</div> <div style="text-indent: 2em;">android.view :提供基础的用户界面接口框架。</div> <div style="text-indent: 2em;">android.util :涉及工具性的方法,例如时间日期的操作。</div> <div style="text-indent: 2em;">android.webkit :默认浏览器操作接口。</div> <div style="text-indent: 2em;">android.widget :包含各种 UI 元素(大部分是可见的)在应用程序的布局中使用</div> <div>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div> <div> <div>build/</div> <div>|&#8211; buildspec.mk.default</div> <div>|&#8211; cleanspec.mk</div> <div>|&#8211; core (各种以mk为结尾的文件,它门是编译所需要的Makefile)</div> <div>|&#8211; envsetup.sh</div> <div>|&#8211; libs</div> <div>|&#8211; target (包含board和product两个目录,为目标所需要文件)</div> <div>|&#8211; tools (编译过程中主机所需要的工具,一些需要经过编译生成)</div> <div>其中,core中的Makefile是整个Android编译所需要的真正的<span style="text-indent: 2em;">Makefile,它被顶层目录的Makefile引用。</span></div> <div></div> </div> <div></div> <div>基本介绍到此，文章参考网络中各种文章，如果有侵权啥行为的，请联系删除。</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-20 14:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Linux Mint 13 的安装、配置及搭建Android源码编译环境(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/19/197940.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 19 Feb 2013 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/19/197940.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197940.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/19/197940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197940.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197940.html</trackback:ping><description><![CDATA[<div><p>用过ubuntu，现在想换换LinuxMint试试看。下面是我安装配置LinuxMint13的过程。</p> <h1>1、安装</h1> <p>安装LinuxMint13时，我尝试了好多种方法，都失败了。最后选用了硬盘安装。硬盘安装Linuxmint和安装ubuntu一样。</p> <h2>1.1、准备工作</h2> <p>1、从linux mint的官方网站<a href="http://www.linuxmint.com/">http://www.linuxmint.com/</a> 下载linux mint 13。</p> <p>2、下载grub4dos，<a href="http://www.linuxidc.com/Linux/2009-01/18027.htm">http://www.linuxidc.com/Linux/2009-01/18027.htm</a> 。</p> <h2>1.2、安装步骤</h2> <p>1、将下载的linuxmint-13-mate-dvd-64bit.iso 拷贝到系统的C盘根目录。</p> <p>2、从linuxmint-13-mate-dvd-64bit.iso的<span style="color: #ff0000;">casper</span>文件夹中提取出<span style="color: #ff0000;">vmlinuz、initrd.lz</span>文件。也放到C盘根目录下。</p> <p>3、解压grub4dos压缩包，会得到一个名为grub4dos-0.4.4的文件夹，将以下文件拷贝到C盘（其中前两个文件是必需的，后两个文件网上有些资料说不需要，为了保险起见还是放上吧，反正也没什么坏处～）：</p> <p>　　<span style="color: #ff0000;"><strong>grldr</strong></span>　<span style="color: #ff0000;"><strong>menu.lst</strong></span>　 grldr.mbr　 grub.exe</p> <p>4、修改menu.lst文件，在文件末尾添加以下内容</p> <blockquote> <p>title <strong>Install <a title="Ubuntu" href="http://www.linuxidc.com/topicnews.aspx?tid=2">Linux Mint</a></strong></p> <p>root (hd0,0)</p> <p>kernel (hd0,0)/vmlinuz boot=casper iso-scan/filename=/<strong>linuxmint-13-mate-dvd-64bit.iso</strong> locale=zh_CN.UTF-8</p> <p>initrd (hd0,0)/initrd.lz</p> </blockquote> <p>&nbsp;其中，title后面的内容随便写就是，kernel后面的那个突出显示的就是<a title="Ubuntu" href="http://www.linuxidc.com/topicnews.aspx?tid=2">Linux Mint</a>的镜像文件，需要与C盘中的文件名对应。</p> <p>5、修改C盘根目录下隐藏的boot.ini，打开文件后，在文件最后添加如下内容</p> <p>　　c:\grldr=&#8221;<a title="Ubuntu" href="http://www.linuxidc.com/topicnews.aspx?tid=2">Linux Mint</a> Install&#8221;</p> <p>以上工作完成后，重启系统即可开始XP硬盘安装<a title="Ubuntu" href="http://www.linuxidc.com/topicnews.aspx?tid=2">Linux Mint</a>的过程了！</p> <p>&nbsp;</p> <p>不过我安装花了好长的时候，时间主要是浪费在系统分区上了，每个分区的操作都要等上好久啊，蛋疼啊！</p> <p><span style="color: #ff0000;">注意：在重启后进入Linux Mint界面后就先卸载isodevices</span></p> <p><span style="color: #ff0000;">　　umount -l /isodevices</span></p> <p><span style="color: #ff0000;">这步很重要，未执行这步，分区无法成功。<br /></span></p> <p>&nbsp;</p> <h1>2、配置</h1> <p>安装完成之后可以进行配置了，由于安装是没有链接到网络，也就没有下载更新包、语言包。现在首要的就是进行安装语言包。</p> <p>MINT 13默认的更新源是真心慢啊，所以第一步要先处理更新源的问题。</p> <h2>2.1、更新源</h2> <p>LinuxMint 的镜像建立在中国科技大学的镜像站上了，中国科技大学 LinuxMint:<a href="http://mirrors.ustc.edu.cn/linuxmint/" target="_blank">http://mirrors.ustc.edu.cn/linuxmint/ </a>这是唯一也是主镜像。</p> <p>下面就说一下具体步骤</p> <p>1、登录 Linux Mint,打开终端。</p> <p>2、键入命令 sudo nano /etc/apt/sources.list，建议先备份下。</p> <p>3、打开文本后应该是这个样子<br /> deb http://packages.linuxmint.com/ maya main upstream import<br />deb http://archive.ubuntu.com/ubuntu/ precise main restricted universe multiverse<br />deb http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse<br />deb http://security.ubuntu.com/ubuntu/ precise-security main restricted universe multiverse<br />deb http://archive.canonical.com/ubuntu/ precise partner<br />deb http://packages.medibuntu.org/ precise free non-free<br />可以看出没有中国服务器的影子</p> <p>4、下面我们就来添加中国的源<br /> 添加以下文字<br /> deb http://mirrors.ustc.edu.cn/linuxmint/ maya main upstream import universe multiverse<br />deb http://mirrors.163.com/ubuntu/ precise main restricted universe multiverse<br />deb http://mirrors.163.com/ubuntu/ precise-security main restricted universe multiverse<br />deb http://mirrors.163.com/ubuntu/ precise-updates main restricted universe multiverse<br />并且将原来的源全部注释掉(就是封掉,不要用了)<br /> deb http://packages.linuxmint.com/ maya main upstream import<br />deb http://archive.ubuntu.com/ubuntu/ precise main restricted universe multiverse<br />deb http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse<br />deb http://security.ubuntu.com/ubuntu/ precise-security main restricted universe multiverse<br />deb http://archive.canonical.com/ubuntu/ precise partner<br />deb http://packages.medibuntu.org/ precise free non-free<br /> 注意就是在最前面多加了个#号即可<br /> 注:这里以 Linux Mint 13 maya 为例,其它举一反三即可。其实就是改个链接而已。后<br /> 面的文字保持原样即可。</p> <p>5、更新 APT<br /> 在终端输入命令 sudo apt-get update<br /> 等待执行完成即可。这时你会发现 Linux Mint 原来如此轻盈!</p> <p>&nbsp;</p> <h2>2.2、安装输入法</h2> <p>在这里我安装的是FCITX</p> <p>直接从软件管理器中搜索fcitx，然后安装。</p> <p>安装完成后到 控制中心 ---》Language Support 的键盘输入方式系统中选择fictx </p> <p>重启系统即可使用。</p> <p>&nbsp;</p> <h2>&nbsp;2.3、安装QQ</h2> <p>1、到以下网址下载deb安装包，<a href="http://www.longene.org/download/qq2011-for-wine_20120220.deb">http://www.longene.org/download/qq2011-for-wine_20120220.deb</a>，已经打包好的deb包，大小为150M左右；</p> <p><span style="color: #ff0000;">　　最新发布 6-1 号更新的 ：</span><a href="http://www.longene.org/download/WineQQ2012-20120531-Longene.deb"><span style="color: #ff0000;">http://www.longene.org/download/WineQQ2012-20120531-Longene.deb</span></a><span style="color: #ff0000;"> 有几个bug 已经修补啦 ！</span></p> <p>2、打开终端输入到目录中运行命令安装：</p> <p>　　sudo dpkg -i *.deb</p> <p>3、64位系统还需要运行以下命令：</p> <p>　　sudo apt-get install ia32-libs</p> <p>4、卸载的话运行以下命令：</p> <p>　　dpkg -r qq-for-wine</p> <p>&nbsp;</p> <h2><span style="color: #000000;">2.4、安装Google Chrome<br /></span></h2> <p><span style="color: #000000;">1、chrome</span></p> <p><span style="color: #000000;">到<a href="https://www.google.com/intl/en/chrome/browser/index.html">https://www.google.com/intl/en/chrome/browser/index.html</a> 下载最新的安装包。也可以通过下面的命令安装<br /></span></p> <p>32位系统：</p> <p>wget -O google-chrome_i386.deb <a href="http://goo.gl/itppy">http://goo.gl/itppy</a></p> <p>sudo dpkg -i google-chrome_i386.deb</p> <p>64位系统：</p> <p>wget -O google-chrome_amd64.deb http://goo.gl/iXDWk</p> <p>sudo dpkg -i google-chrome*.deb</p> <p>2、chromium</p> <p>sudo apt-get install chromium-browser</p> <p>chromium flash 插件失效的修复方法：</p> <p>　　查找flash插件</p> <p>　　　　$ sudo locate libflashplayer.so</p> <p>　　　　/usr/lib/adobe-flashplugin/libflashplayer.so</p> <p>　　拷贝flash插件到chromium-browser插件目录<br />　　　　$ sudo cp /usr/lib/adobe-flashplugin/libflashplayer.so <span style="color: #ff0000;">/usr/lib/chromium-browser/plugins</span></p> <p>&nbsp;</p> <h2><span style="color: #000000;">2.5、安装无线网卡</span></h2> <p><span style="color: #000000;">我的网卡是BCM4312，在网上找了好久，试过两三种方法都不行。最后找到以下方法解决：</span></p> <p><span style="color: #000000;">1、<span>先到Broadcom的官方网站去仔细的看看说明具体链接地址如下：<br /><a title="" href="http://www.broadcom.com/support/802.11/linux_sta.php" target="_blank">http://www.broadcom.com/support/802.11/linux_sta.php</a></span></span></p> <p><span style="color: #000000;">可以先查看自己的网卡的型号，下载对应的驱动。<span>在终端下输入：&#8220;lspci | grep Network" 确认网卡型号。</span></span></p> <p><span style="color: #000000;"><span>2、<span>解压缩<br />tar -xzf hybrid-portsrc-x86_32-v5.60.48.36.tar.gz</span></span></span></p> <p><span style="color: #000000;"><span><span>3、编译<br />make</span></span></span></p> <p><span style="color: #000000;"><span><span>编译时遇到下面的错误：</span></span></span></p> <p>/home/lgq/hybrid_wl/src/wl/sys/wl_linux.c:388:2: 错误： 初始值设定项里有未知的字段&#8216;ndo_set_multicast_list&#8217;<br />/home/lgq/hybrid_wl/src/wl/sys/wl_linux.c:388:2: 警告： 从不兼容的指针类型初始化 [默认启用]<br />/home/lgq/hybrid_wl/src/wl/sys/wl_linux.c:388:2: 警告： (在&#8216;wl_netdev_ops.ndo_validate_addr&#8217;的初始化附近) [默认启用]</p> <p><span style="color: #000000;">在google后发现 <span style="color: #ff0000;">&nbsp;ndo_set_multicast_list</span> 被<span style="color: #ff0000;">ndo_set_rx_mode</span>替换(在以下网站提到<a href="http://www.mindwerks.net/2011/11/wireless-bcm4312-3-2-kernel/">http://www.mindwerks.net/2011/11/wireless-bcm4312-3-2-kernel/</a></span></p> <p><span style="color: #000000;">再次编译通过。</span></p> <p><span style="color: #000000;">4、sudo make install</span></p> <p><span style="color: #000000;">5、sudo depmod</span></p> <p><span style="color: #000000;">6、sudo modprobe wl</span></p> <p><span style="color: #000000;"><span><span>Give Ubuntu a few seconds  after loading the &#8220;wl&#8221; kernel module, then eventually the Network  Manager will start looking for wireless networks.</span></span></span></p> <p><span style="color: #000000;">&nbsp;</span></p> <p><span style="color: #000000;">参考链接：<a href="http://blog.csdn.net/cs090506/article/details/7300526">http://blog.csdn.net/cs090506/article/details/7300526</a></span></p> <p><span style="color: #000000;">&nbsp;</span></p> <h2><span style="color: #000000;">2.6、安装词典星际译王</span></h2> <p>通过软件管理器安装星际译王stardict。</p> <p>词典下载路径：<a href="http://abloz.com/huzheng/stardict-dic/">http://abloz.com/huzheng/stardict-dic/</a></p> <p>&nbsp;</p> <h2><span style="color: #000000;">2.7、</span>编译安装最新的alsa驱动</h2> <p>刚安装好的linux mint，插上耳机后，笔记本的内置音箱仍然还有声音。</p> <p>1、查看自己声卡的codec型号。</p> <p>终端输入alsamixer，查看显示的chip值。或者<span>cat /proc/asound/card0/codec#0，查看显示结果的首行。</span></p> <p>2、到官方网站下载相应的驱动来安装。</p> <p>&nbsp;</p> <h1><span style="color: #000000;">3、搭建Android源码开发环境</span></h1> <p><span style="color: #000000;">在本节搭建的是Android4.0的源码开发环境。</span></p> <p><span style="color: #000000;">Linux Mint 13 中已经安装了 GNU Make 3.81、Python 2.7.3、Git 1.7.9.5。</span></p> <p><span style="color: #000000;">所以还需要安装jdk6。</span></p> <h2><span style="color: #000000;">3.1、安装jdk6</span></h2> <p><span style="color: #000000;">Linux Mint 13 中自带有OpenJDK，但这个不是我想要的，我们要的是sun-java6。</span></p> <p><span style="color: #000000;">1、在安装sun的jdk前，先删除OpenJDK，打开新立得，搜索OpenJDK，彻底删除所有的包。</span></p> <p><span style="color: #000000;">2、在sun的官网上<a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk6-downloads-1637591.html">http://www.oracle.com/technetwork/java/javase/downloads/jdk6-downloads-1637591.html</a>&nbsp;下载最新的<span>安装文件（<span>如：jdk-6u34-linux-x64.bin）。</span></span></span></p> <p><span style="color: #000000;"><span>增加执行权限：sudo chmod u+x jdk-6u34-linux-x64.bin</span></span></p> <p><span style="color: #000000;">将安装文件拷贝到&nbsp;/usr/lib/java/ 目录下</span></p> <p><span style="color: #000000;">执行安装命令 &nbsp;<span style="color: #ff0000;">./jdk-6u34-linux-x64.bin</span></span></p> <p>&nbsp;成功安装完JDK后，接下来我们将要进行ＪＤＫ的配置，使用命　<strong>$ sudo gedit /etc/environment</strong>　对environment文件进行修改并添加以下代码：</p> <p><span style="color: #888888;">&nbsp;　　　　PATH＝"/usr/lib/java/jdk1.6.0_34/bin"&nbsp;&nbsp;</span></p> <p><span style="color: #888888;">　　　　CLASSPATH="/usr/lib/java/jdk1.6.0_34/lib"</span></p> <p><span style="color: #888888;">　　　　JAVA_HOME=<span>"/usr/lib/java/jdk1.6.0_34"</span>&nbsp;&nbsp;&nbsp;</span></p> <p>&nbsp;若PATH已存在，则用冒号作间隔，将jdk的bin目录地址加上，这样java的环境变量将配置成功了，但这样默认使用的JDK可能还不是我们  刚才安装的，因为ubuntu可能还会有默认的jdk，如openjdk；所以，为了使默认使用的是我们安装的jdk，还需执行如下命令:</p> <p>&nbsp;　　　　$&nbsp;sudo&nbsp;update-alternatives&nbsp;--install&nbsp;/usr/bin/java&nbsp;java&nbsp;/usr/lib/java/jdk1.6.0_34/bin/java&nbsp;300</p> <p>　　　　$&nbsp;sudo&nbsp;update-alternatives&nbsp;--install&nbsp;/usr/bin/javac&nbsp;javac&nbsp;/usr/lib/java/jdk1.6.0_34/bin/javac&nbsp;300&nbsp;</p> <p><span>　　　　$&nbsp;sudo&nbsp;update-alternatives&nbsp;--config&nbsp;java&nbsp;&nbsp;&nbsp;&nbsp;<br /></span></p> <p>&nbsp;成功执行命令后，我们安装的JDK就是系统默认的了，执行命令&nbsp;$&nbsp;java&nbsp;-version&nbsp;&nbsp;就可以成功看到 JDK的相关信息了如：</p> <p>&nbsp;　　　　java version "1.6.0_34"</p> <p>　　　　Java(TM) SE Runtime Environment (build 1.6.0_34-b04)<br />　　　　Java HotSpot(TM) 64-Bit Server VM (build 20.9-b04, mixed mode)&nbsp;&nbsp;</p> <h2><span style="color: #000000;">&nbsp;3.2、安装必需的软件包</span></h2> <p>&nbsp;安装编译Android需要的工具包，这个步骤是关键，必须安装，否则编译会报莫名其妙的错误！！！！！！！！！！！！！！！！</p> <p><span>sudo apt-get install git-core gnupg flex bison gperf  build-essential&nbsp;&nbsp; zip curl zlib1g-dev libc6-dev lib32ncurses5-dev  ia32-libs&nbsp;&nbsp; x11proto-core-dev libx11-dev lib32readline-gplv2-dev  lib32z1-dev&nbsp;&nbsp; libgl1-mesa-dev gcc-multilib g++-multilib mingw32 tofrodos  python-markdown&nbsp;&nbsp; libxml2-utils&nbsp; xsltproc</span>&nbsp;</p> <h2><span style="color: #000000;">3.3、配置USB</span></h2> <p>lgq-laptop bin # lsusb<br />Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub<br />Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub<br />Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br />Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br />Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br />Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br />Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br />Bus 002 Device 003: ID 04f2:b008 Chicony Electronics Co., Ltd USB 2.0 Camera<br />Bus 006 Device 002: ID 1ea7:000b &nbsp;<br />Bus 002 Device 004: ID 05c6:9025 Qualcomm, Inc. <br /><br /></p> <p>$sudo vim /etc/udev/rules.d/70-android.rules</p> <p>增加下面内容</p> <p>SUBSYSTEM=="usb", ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="9025",MODE="0666"</p> <p>运行命令，重启udev：</p> <p>$sudo chmod a+rx /etc/udev/rules.d/70-android.rules<br />$sudo service udev restart</p> <p>&nbsp;</p> <h2><span style="color: #000000;">3.4、安装svn</span></h2> <p>1、安装subversion</p> <p>apt-get install subversion</p> <p>2、安装rabbitvcs</p> <p><code>sudo add-apt-repository ppa:rabbitvcs/ppa</code></p> <p>sudo apt-get update</p> <p>sudo apt-get install rabbitvcs-nautilus3</p> <p>nautilus -q</p> <p>nautilus</p> <p>rabbitvcs的界面比较习惯，但是，很卡。</p> <p>3、rapidsvn</p> <p>sudo apt-get install rapidsvn</p> <p>4、esvn</p> <p>&nbsp;</p> <h2>3.5、设置ccache</h2> <div>&#9312;安装ccache</div> <div>官网下载或apt安装&nbsp; sudo apt-get install ccache</div> <div>&nbsp;</div> <div>&#9313;$ which ccache</div> <div>查看安装路径, /usr/bin/ccache</div> <div>&nbsp;</div> <div>&#9314;$ mkdir ~/.bin</div> <div>&#9315; $ cd ~/.bin/</div> <div>&nbsp;&nbsp; $ ln -s /usr/bin/ccache gcc</div> <div>&nbsp;&nbsp;&nbsp;$ ln -s /usr/bin/ccache g++</div> <div>&nbsp;&nbsp;&nbsp;$ ln -s /usr/bin/ccache arm-linux-gcc</div> <div>&nbsp;&nbsp;&nbsp;$ ln -s /usr/bin/ccache&nbsp;arm-linux-g++</div> <div>&nbsp;</div> <div>&#9316;PATH设置，将~/.bin/放在&nbsp;arm-linux-gcc等的PATH的前面。</div> <div>原：PATH=/usr/local/arm-linux_pre4/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</div> <div>现：PATH=<span style="color: #ff0102;">/home/&lt;user&gt;/.bin</span>:/usr/local/arm-linux_pre4/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</div> <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gedit ~/.bashrc 添加 export PATH="/home/&lt;user&gt;/.bin:$PAHT" ，然后重启即可</div> <div>&nbsp;</div> <div> <div>&#9317;$ which&nbsp;arm-linux-gcc</div> <div>/home/&lt;user&gt;/.bin/arm-linux-gcc 确认</div> <div>&nbsp;</div> <div>&#9318;$ ccache -M 30G</div>                 </div> <p>&nbsp;</p> <h2>&nbsp;3.6、安装最新的eclipse</h2> <p>&nbsp;eclipse搭建方法参考：<a href="http://www.cnblogs.com/tnxk/archive/2012/07/09/2583800.html">http://www.cnblogs.com/tnxk/archive/2012/07/09/2583800.html</a></p> <p>eclipse的更新速度相当慢，这里收集一个加快更新的方法。</p> <p>解决办法只能是更换到Mirror站点，具体步骤：</p> <p>1.找个国内的站点-北方交通大学的不错<a href="http://mirror.bjtu.edu.cn/eclipse">http://mirror.bjtu.edu.cn/eclipse</a></p> <p>2.更换Eclipse更新服务器下载站点Windows -&gt; Preferences -&gt; Install/Update -&gt; Available Software Sites</p> <p>3.找到<strong>所有 The Eclipse&nbsp;</strong>开始的行，注意是<strong>所有的,</strong>因为不同版本的Eclipse官方项目比如 Web Tools Project，也都需要更改为镜像站点，否则将导致只有部分插件的站点得到更新，只能部分解决速度问题。</p> <p>4.点击&#8220;Edit&#8221;, 编辑Location部分，替换http://download.eclipse.org为<a href="http://mirror.bjtu.edu.cn/eclipse">http://mirror.bjtu.edu.cn/eclipse</a></p> <p>&nbsp;</p> <p>参考链接：<a href="http://blog.csdn.net/chenxihua/article/details/6423168">http://blog.csdn.net/chenxihua/article/details/6423168</a></p> <p>&nbsp;</p> <h1>4、问题及解决方法</h1> <h2>4.1、重启后出现&nbsp;waiting&nbsp;for&nbsp;network&nbsp;configuration&nbsp;问题</h2> <div><span><span>如今在 ubuntu 12.04 环境下接着拨号时，如果使用&nbsp;</span></span>sudo pppoeconf&nbsp;命令配置拨号，重启电脑后就会先显示 <span style="color: #ed1c24;">waiting for network configuration，然后是 <span style="color: #ed1c24;">waiting up to 60 more seconds for network configuration，</span>最后显示<span style="color: #ed1c24;">booting system without full network configuration.</span></span>并且进入桌面后网络连接状态图标也不见了。</div> <div><span style="color: #ffcc00; font-family: Arial;"><strong>问题原因：</strong></span></div>  <p><span><span>使用&nbsp;</span></span>sudo pppoeconf&nbsp;命令<span><span>时，会有信息写入</span><span style="font-family: Verdana, sans-serif;"><span><span>/etc/network/interfaces</span></span></span>&nbsp;<span>文件内，直接导致出现了上面的问题。</span></span></p> <p><span style="color: #ffcc00;"><strong>问题解决：</strong></span></p> <p>sudo gedit /etc/network/interfaces &nbsp;打开文件后，<span>将其中除</span></p> <p><strong>auto lo</strong></p> <p><span><span><span style="color: #6f3198;"><strong><span>iface lo inet loopback</span></strong></span><br /></span></span><span>外其他内容全部删除后，重启系统就可以了。</span></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-19 17:06 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/19/197940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android 启动Launcher </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 18 Feb 2013 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197913.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197913.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197913.html</trackback:ping><description><![CDATA[<div><span style="font-size:14px"><span style="border-collapse: collapse; color: #444444; font-family: 'DejaVu Sans', 'Lucida Grande', Tahoma, 'Hiragino Sans GB', STHeiti, SimSun, sans-serif; line-height: 21px; ">一LauncherApplication-&gt;onCreate<br style="word-wrap: break-word; " />　　1.//设置最小堆内存4M<br style="word-wrap: break-word; " />　　2.//建立应用图标缓存器<br style="word-wrap: break-word; " />　　3.//建立LauncherModel<br style="word-wrap: break-word; " />　　4.//注册Intent.ACTION_PACKAGE_ADDED，Intent.ACTION_PACKAGE_REMOVED，Intent.ACTION_PACKAGE_CHANGED事件监听器<br style="word-wrap: break-word; " />　　LauncherModel作为广播接收器对上面3中事件进行监听<br style="word-wrap: break-word; " />　　5.//添加对桌面favorites content provider 数据变化监听器<br style="word-wrap: break-word; " />　　二Launcher-&gt;onCreate<br style="word-wrap: break-word; " />　　1.获取LauncherApplication LauncherModel mIconCache等LauncherApplication初始化的对象<br style="word-wrap: break-word; " />　　2.新建拖放控制器new DragController（this）<br style="word-wrap: break-word; " />　　4.//获取桌面组件管理器，启动桌面组件host<br style="word-wrap: break-word; " />　　5.//从array.hotseats中加载所有的hotseats（热键 如挂机按钮，<a href="http://dev.10086.cn/cmdn/wiki/index.php?doc-view-1483">google</a>浏览器）<br style="word-wrap: break-word; " />　　6.从launcher.preferences加载本地设置<br style="word-wrap: break-word; " />　　7.//设置壁纸尺寸宽度=display.getWidth（）* WALLPAPER_SCREENS_SPAN，高度=display.getHeight（）<br style="word-wrap: break-word; " />　　8.//加载布局文件<br style="word-wrap: break-word; " />　　9.//初始化所有控件<br style="word-wrap: break-word; " />　　10.//从Bundle savedInstanceState获取桌面持久化数据 设置mRestoring = true；<br style="word-wrap: break-word; " />　　11.如果mRestoring == false，调用LauncherModel加载桌面项 mModel.startLoader（this， true，isLanguageChange）；<br style="word-wrap: break-word; " />　　a.LauncherModel.Loader.startLoader（） 代码同步处理<br style="word-wrap: break-word; " />　　b.新建LauncherModel.Loader.LoaderThread线程并启动线程（桌面项加载，详细见第三步）<br style="word-wrap: break-word; " />　　12.注册Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播监听<br style="word-wrap: break-word; " />　　三 桌面项加载 LauncherModel.Loader.LoaderThread.run：新线程执行<br style="word-wrap: break-word; " />　　1.等待主线程运行结束才开始加载<br style="word-wrap: break-word; " />　　2.判断是否先加载桌面；loadWorkspaceFirst = cbk ！= null ？ （！cbk.isAllAppsVisible（）） ： true；<br style="word-wrap: break-word; " />　　3.loadWorkspaceFirst==true<br style="word-wrap: break-word; " />　　a.loadAndBindWorkspace（）<br style="word-wrap: break-word; " />　　loadWorkspace（）：从数据库launcher.db中查询中所有桌面项构造对应类型的ItemInfo对象存入<br style="word-wrap: break-word; " />　　mItems，mAppWidgets，mFolders列表.<br style="word-wrap: break-word; " />　　bindWorkspace（）：<br style="word-wrap: break-word; " />　　1.laucher.startBinding（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　//do no things<br style="word-wrap: break-word; " />　　2.laucher.bindItems（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　1.根据ItemInfo对象创建桌面图标view对象<br style="word-wrap: break-word; " />　　2.获取item.screen， item.cellX， item.cellY， spanX， spanY，<br style="word-wrap: break-word; " />　　调用workspace.addInScreen添加到对应桌面的cell<br style="word-wrap: break-word; " />　　1.重新设置桌面图标view 的layoutparam（类型为cellLayout.layoutparam）<br style="word-wrap: break-word; " />　　2.根据item.screen获取桌面的celllayout对象，也就是workspace下5个用户桌面中的一个<br style="word-wrap: break-word; " />　　3.调用celllayout.addview方法把桌面图标view对象添加为celllayout的child，也就是为用户桌面添加一个桌面图标<br style="word-wrap: break-word; " />　　4.桌面图标view对象添加OnLongClickListener=laucher，由laucher负责监听桌面图标view的longclick事件<br style="word-wrap: break-word; " />　　5.如果桌面图标是DropTarget对象，拖放控制器mDragController添加该view到拖放目的地列表<br style="word-wrap: break-word; " />　　3.laucher.bindFolders（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　//launcher.mFolders.putAll（mFolders）；<br style="word-wrap: break-word; " />　　4.laucher.bindAppWidget（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　1.获取LauncherAppWidgetInfo的appWidgetId<br style="word-wrap: break-word; " />　　2.获取AppWidgetProviderInfo appWidgetInfo mAppWidgetManager.getAppWidgetInfo（appWidgetId）<br style="word-wrap: break-word; " />　　3.根据appWidgetInfo创建桌面组件的view AppWidgetHostView对象<br style="word-wrap: break-word; " />　　4.调用workspace.addInScreen添加到对应桌面的cell<br style="word-wrap: break-word; " />　　5.laucher.finishBindingItems（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　mWorkspaceLoading=false<br style="word-wrap: break-word; " />　　b.loadAndBindAllApps（）；<br style="word-wrap: break-word; " />　　如果没有加载apps或者改变了语言设置<br style="word-wrap: break-word; " />　　loadAllAppsByBatch（）；<br style="word-wrap: break-word; " />　　1.//设置package 查询条件Intent.ACTION_MAIN Intent.CATEGORY_LAUNCHER<br style="word-wrap: break-word; " />　　2.//清空mAllAppsList mAllAppsList.clear（）；<br style="word-wrap: break-word; " />　　3.//packageManager 查询所有应用pakages<br style="word-wrap: break-word; " />　　4.分批次mAllAppsList.add 应用pakages<br style="word-wrap: break-word; " />　　5.laucher.bindAllApplications（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.setApps（apps）<br style="word-wrap: break-word; " />　　6.若分多个批次加载 laucher.bindAppsAdded（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.addApps（apps）；<br style="word-wrap: break-word; " />　　否则<br style="word-wrap: break-word; " />　　onlyBindAllApps（）；<br style="word-wrap: break-word; " />　　1.mAllAppsList.data.clone（）；<br style="word-wrap: break-word; " />　　2.laucher.bindAllApplications（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.setApps（apps）<br style="word-wrap: break-word; " />　　4.loadWorkspaceFirst==false<br style="word-wrap: break-word; " />　　a.loadAndBindAllApps（）；<br style="word-wrap: break-word; " />　　b.loadAndBindWorkspace（）；<br /><br /></span></span></div><div>http://www.cnblogs.com/playing/archive/2011/04/22/2024980.html</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-18 17:37 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android各种访问权限Permission详解</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 18 Feb 2013 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197911.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197911.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197911.html</trackback:ping><description><![CDATA[<div><p>在Android的设计中，资源的访问或者网络连接，要得到这些服务都需要声明其访问权限，否则将无法正常工作。在Android中这样的权限有很多种，这里将各类访问权限一一罗列出来，供大家使用时参考之用。</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>android.permission.EXPAND_STATUS_BAR <br /> 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序</p> <p>android.permission.FACTORY_TEST <br /> 作为一个工厂测试程序，运行在root用户</p> <p>android.permission.FLASHLIGHT <br /> 访问闪光灯,android开发网提示HTC Dream不包含闪光灯</p> <p>android.permission.FORCE_BACK <br /> 允许程序强行一个后退操作是否在顶层activities</p> <p>android.permission.FOTA_UPDATE <br /> 暂时不了解这是做什么使用的，android开发网分析可能是一个预留权限.</p> <p>android.permission.GET_ACCOUNTS <br /> 访问一个帐户列表在Accounts Service中</p> <p>android.permission.GET_PACKAGE_SIZE <br /> 允许一个程序获取任何package占用空间容量</p> <p>android.permission.GET_TASKS <br /> 允许一个程序获取信息有关当前或最近运行的任务，一个缩略的任务状态，是否活动等等</p> <p>android.permission.HARDWARE_TEST <br /> 允许访问硬件</p> <p>android.permission.INJECT_EVENTS <br /> 允许一个程序截获用户事件如按键、触摸、轨迹球等等到一个时间流，android 开发网提醒算是hook技术吧</p> <p>android.permission.INSTALL_PACKAGES <br /> 允许一个程序安装packages</p> <p>android.permission.INTERNAL_SYSTEM_WINDOW <br /> 允许打开窗口使用系统用户界面</p> <p>android.permission.ACCESS_CHECKIN_PROPERTIES <br /> 允许读写访问&#8220;properties&#8221;表在checkin数据库中，改值可以修改上传。</p> <p>android.permission.ACCESS_COARSE_LOCATION <br /> 允许一个程序访问CellID或WiFi热点来获取粗略的位置</p> <p>android.permission.ACCESS_FINE_LOCATION <br /> 允许一个程序访问精良位置(如GPS)</p> <p>android.permission.WRITE_CONTACTS <br /> 允许程序写入但不读取用户联系人数据</p> <p>android.permission.WRITE_GSERVICES <br /> 允许程序修改Google服务地图</p> <p>android.permission.WRITE_OWNER_DATA <br /> 允许一个程序写入但不读取所有者数据</p> <p>android.permission.WRITE_SETTINGS <br /> 允许程序读取或写入系统设置</p> <p>android.permission.WRITE_SMS <br /> 允许程序写短信</p> <p>android.permission.WRITE_SYNC_SETTINGS <br /> 允许程序写入同步设置</p> <p>android.permission.ACCESS_LOCATION_EXTRA_COMMANDS <br /> 允许应用程序访问额外的位置提供命令</p> <p>android.permission.ACCESS_MOCK_LOCATION <br /> 允许程序创建模拟位置提供用于测试</p> <p>android.permission.ACCESS_NETWORK_STATE <br /> 允许程序访问有关GSM网络信息</p> <p>android.permission.ACCESS_SURFACE_FLINGER <br /> 允许程序使用SurfaceFlinger底层特性</p> <p>android.permission.ACCESS_WIFI_STATE <br /> 允许程序访问Wi-Fi网络状态信息</p> <p>android.permission.ADD_SYSTEM_SERVICE <br /> 允许程序发布系统级服务</p> <p>android.permission.BATTERY_STATS <br /> 允许程序更新手机电池统计信息</p> <p>android.permission.BLUETOOTH <br /> 允许程序连接到已配对的蓝牙设备</p> <p>android.permission.BLUETOOTH_ADMIN <br /> 允许程序发现和配对蓝牙设备</p> <p>android.permission.BROADCAST_PACKAGE_REMOVED <br /> 允许程序广播一个提示消息在一个应用程序包已经移除后</p> <p>android.permission.BROADCAST_STICKY <br /> 允许一个程序广播常用intents</p> <p>android.permission.CALL_PHONE <br /> 允许一个程序初始化一个电话拨号不需通过拨号用户界面需要用户确认</p> <p>android.permission.DELETE_CACHE_FILES <br /> 允许程序删除缓存文件</p> <p>android.permission.DELETE_PACKAGES <br /> 允许一个程序删除包</p> <p>android.permission.DEVICE_POWER <br /> 允许访问底层电源管理</p> <p>android.permission.DIAGNOSTIC <br /> 允许程序RW诊断资源</p> <p>android.permission.DISABLE_KEYGUARD <br /> 允许程序禁用键盘锁</p> <p>android.permission.DUMP <br /> 允许程序返回状态抓取信息从系统服务</p> <p>android.permission.CALL_PRIVILEGED <br /> 允许一个程序拨打任何号码，包含紧急号码无需通过拨号用户界面需要用户确认</p> <p>android.permission.CAMERA <br /> 请求访问使用照相设备</p> <p>android.permission.CHANGE_COMPONENT_ENABLED_STATE <br /> 允许一个程序是否改变一个组件或其他的启用或禁用</p> <p>android.permission.CHANGE_CONFIGURATION <br /> 允许一个程序修改当前设置，如本地化</p> <p>android.permission.CHANGE_NETWORK_STATE <br /> 允许程序改变网络连接状态</p> <p>android.permission.CHANGE_WIFI_STATE <br /> 允许程序改变Wi-Fi连接状态</p> <p>android.permission.CLEAR_APP_CACHE <br /> 允许一个程序清楚缓存从所有安装的程序在设备中</p> <p>android.permission.CLEAR_APP_USER_DATA <br /> 允许一个程序清除用户设置</p> <p>android.permission.CONTROL_LOCATION_UPDATES <br /> 允许启用禁止位置更新提示从无线模块</p> <p>android.permission.REBOOT <br /> 请求能够重新启动设备</p> <p>android.permission.RECEIVE_BOOT_COMPLETED <br /> 允许一个程序接收到 ACTION_BOOT_COMPLETED广播在系统完成启动</p> <p>android.permission.RECEIVE_MMS <br /> 允许一个程序监控将收到MMS彩信,记录或处理</p> <p>android.permission.RECEIVE_SMS <br /> 允许程序监控一个将收到短信息，记录或处理</p> <p>android.permission.RECEIVE_WAP_PUSH <br /> 允许程序监控将收到WAP PUSH信息</p> <p>android.permission.RECORD_AUDIO <br /> 允许程序录制音频</p> <p>android.permission.REORDER_TASKS <br /> 允许程序改变Z轴排列任务</p> <p>android.permission.RESTART_PACKAGES <br /> 允许程序重新启动其他程序</p> <p>android.permission.SEND_SMS <br /> 允许程序发送SMS短信</p> <p>android.permission.INTERNET <br /> 允许程序打开网络套接字</p> <p>android.permission.MANAGE_APP_TOKENS <br /> 允许程序管理(创建、催后、 z- order默认向z轴推移)程序引用在窗口管理器中</p> <p>android.permission.MASTER_CLEAR目前还没有明确的解释，android开发网分析可能是清除一切数据，类似硬格机</p> <p>android.permission.MODIFY_AUDIO_SETTINGS <br /> 允许程序修改全局音频设置</p> <p>android.permission.MODIFY_PHONE_STATE <br /> 允许修改话机状态，如电源，人机接口等</p> <p>android.permission.MOUNT_UNMOUNT_FILESYSTEMS <br /> 允许挂载和反挂载文件系统可移动存储</p> <p>android.permission.PERSISTENT_ACTIVITY <br /> 允许一个程序设置他的activities显示</p> <p>android.permission.PROCESS_OUTGOING_CALLS <br /> 允许程序监视、修改有关播出电话</p> <p>android.permission.READ_CALENDAR <br /> 允许程序读取用户日历数据</p> <p>android.permission.READ_CONTACTS <br /> 允许程序读取用户联系人数据</p> <p>android.permission.READ_FRAME_BUFFER <br /> 允许程序屏幕波或和更多常规的访问帧缓冲数据</p> <p>android.permission.READ_INPUT_STATE <br /> 允许程序返回当前按键状态</p> <p>android.permission.READ_LOGS <br /> 允许程序读取底层系统日志文件</p> <p>android.permission.READ_OWNER_DATA <br /> 允许程序读取所有者数据</p> <p>android.permission.READ_SMS <br /> 允许程序读取短信息</p> <p>android.permission.READ_SYNC_SETTINGS <br /> 允许程序读取同步设置</p> <p>android.permission.READ_SYNC_STATS <br /> 允许程序读取同步状态</p> <p>android.permission.SET_ACTIVITY_WATCHER <br /> 允许程序监控或控制activities已经启动全局系统中</p> <p>android.permission.SET_ALWAYS_FINISH <br /> 允许程序控制是否活动间接完成在处于后台时</p> <p>android.permission.SET_ANIMATION_SCALE <br /> 修改全局信息比例</p> <p>android.permission.SET_DEBUG_APP <br /> 配置一个程序用于调试</p> <p>android.permission.SET_ORIENTATION <br /> 允许底层访问设置屏幕方向和实际旋转</p> <p>android.permission.SET_PREFERRED_APPLICATIONS <br /> 允许一个程序修改列表参数PackageManager.addPackageToPreferred() 和PackageManager.removePackageFromPreferred()方法</p> <p>android.permission.SET_PROCESS_FOREGROUND <br /> 允许程序当前运行程序强行到前台</p> <p>android.permission.SET_PROCESS_LIMIT <br /> 允许设置最大的运行进程数量</p> <p>android.permission.SET_TIME_ZONE <br /> 允许程序设置时间区域</p> <p>android.permission.SET_WALLPAPER <br /> 允许程序设置壁纸</p> <p>android.permission.SET_WALLPAPER_HINTS <br /> 允许程序设置壁纸hits</p> <p>android.permission.SIGNAL_PERSISTENT_PROCESSES <br /> 允许程序请求发送信号到所有显示的进程中</p> <p>android.permission.STATUS_BAR <br /> 允许程序打开、关闭或禁用状态栏及图标Allows an application to open, close, or disable the status bar and its icons.</p> <p>android.permission.SUBSCRIBED_FEEDS_READ <br /> 允许一个程序访问订阅RSS Feed内容提供</p> <p>android.permission.SUBSCRIBED_FEEDS_WRITE <br /> 系统暂时保留改设置,android开发网认为未来版本会加入该功能。</p> <p>android.permission.SYSTEM_ALERT_WINDOW <br /> 允许一个程序打开窗口使用 TYPE_SYSTEM_ALERT，显示在其他所有程序的顶层</p> <p>android.permission.VIBRATE <br /> 允许访问振动设备</p> <p>android.permission.WAKE_LOCK <br /> 允许使用PowerManager的 WakeLocks保持进程在休眠时从屏幕消失</p> <p>android.permission.WRITE_APN_SETTINGS <br /> 允许程序写入API设置</p> <p>android.permission.WRITE_CALENDAR <br /> 允许一个程序写入但不读取用户日历数据</p> <p>可以看出Android中对资源以及服务的访问都非常严格，另外，在程序打包成APK的时候也需要对软件进行签名。</p><p><br /></p><p><div><table border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td bgcolor="#d8d8d8" valign="top" width="152">访问登记属性</td> <td bgcolor="#d8d8d8" valign="top" width="616">android.permission.ACCESS_CHECKIN_PROPERTIES ，读取或写入登记check-in数据库属性表的权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取错略位置</td> <td valign="top">android.permission.ACCESS_COARSE_LOCATION，通过WiFi或移动基站的方式获取用户错略的经纬度信息，定位精度大概误差在30~1500米</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">获取精确位置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_FINE_LOCATION，通过GPS芯片接收卫星的定位信息，定位精度达10米以内</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">访问定位额外命令</td> <td valign="top">android.permission.ACCESS_LOCATION_EXTRA_COMMANDS，允许程序访问额外的定位提供者指令</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">获取模拟定位信息</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_MOCK_LOCATION，获取模拟定位信息，一般用于帮助开发者调试应用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取网络状态</td> <td valign="top">android.permission.ACCESS_NETWORK_STATE，获取网络信息状态，如当前的网络连接是否有效</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">访问Surface Flinger</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_SURFACE_FLINGER，Android平台上底层的图形显示支持，一般用于游戏或照相机预览界面和底层模式的屏幕截图</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取WiFi状态</td> <td valign="top">android.permission.ACCESS_WIFI_STATE，获取当前WiFi接入的状态以及WLAN热点的信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">账户管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCOUNT_MANAGER，获取账户验证信息，主要为GMail账户信息，只有系统级进程才能访问的权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">验证账户</td> <td valign="top">android.permission.AUTHENTICATE_ACCOUNTS，允许一个程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">电量统计</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BATTERY_STATS，获取电池电量统计信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定小插件</td> <td valign="top">android.permission.BIND_APPWIDGET，允许一个程序告诉appWidget服务需要访问小插件的数据库，只有非常少的应用才用到此权限</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">绑定设备管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BIND_DEVICE_ADMIN，请求系统管理员接收者receiver，只有系统才能使用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定输入法</td> <td valign="top">android.permission.BIND_INPUT_METHOD ，请求InputMethodService服务，只有系统才能使用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">绑定RemoteView</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BIND_REMOTEVIEWS，必须通过RemoteViewsService服务来请求，只有系统才能用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定壁纸</td> <td valign="top">android.permission.BIND_WALLPAPER，必须通过WallpaperService服务来请求，只有系统才能用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用蓝牙</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BLUETOOTH，允许程序连接配对过的蓝牙设备</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">蓝牙管理</td> <td valign="top">android.permission.BLUETOOTH_ADMIN，允许程序进行发现和配对新的蓝牙设备</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">变成砖头</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BRICK，能够禁用手机，非常危险，顾名思义就是让手机变成砖头</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">应用删除时广播</td> <td valign="top">android.permission.BROADCAST_PACKAGE_REMOVED，当一个应用在删除时触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">收到短信时广播</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BROADCAST_SMS，当收到短信时触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">连续广播</td> <td valign="top">android.permission.BROADCAST_STICKY，允许一个程序收到广播后快速收到下一个广播</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">WAP PUSH广播</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BROADCAST_WAP_PUSH，WAP PUSH服务收到后触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">拨打电话</td> <td valign="top">android.permission.CALL_PHONE，允许程序从非系统拨号器里输入电话号码</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">通话权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CALL_PRIVILEGED，允许程序拨打电话，替换系统的拨号器界面</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">拍照权限</td> <td valign="top">android.permission.CAMERA，允许访问摄像头进行拍照</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变组件状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_COMPONENT_ENABLED_STATE，改变组件是否启用状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">改变配置</td> <td valign="top">android.permission.CHANGE_CONFIGURATION，允许当前应用改变配置，如定位</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变网络状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_NETWORK_STATE，改变网络状态如是否能联网</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">改变WiFi多播状态</td> <td valign="top">android.permission.CHANGE_WIFI_MULTICAST_STATE，改变WiFi多播状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变WiFi状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_WIFI_STATE，改变WiFi状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">清除应用缓存</td> <td valign="top">android.permission.CLEAR_APP_CACHE，清除应用缓存</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">清除用户数据</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CLEAR_APP_USER_DATA，清除应用的用户数据</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">底层访问权限</td> <td valign="top">android.permission.CWJ_GROUP，允许CWJ账户组访问底层信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">手机优化大师扩展权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CELL_PHONE_MASTER_EX，手机优化大师扩展权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">控制定位更新</td> <td valign="top">android.permission.CONTROL_LOCATION_UPDATES，允许获得移动网络定位信息改变</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">删除缓存文件</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DELETE_CACHE_FILES，允许应用删除缓存文件</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">删除应用</td> <td valign="top">android.permission.DELETE_PACKAGES，允许程序删除应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">电源管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DEVICE_POWER，允许访问底层电源管理</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">应用诊断</td> <td valign="top">android.permission.DIAGNOSTIC，允许程序到RW到诊断资源</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">禁用键盘锁</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DISABLE_KEYGUARD，允许程序禁用键盘锁</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">转存系统信息</td> <td valign="top">android.permission.DUMP，允许程序获取系统dump信息从系统服务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">状态栏控制</td> <td bgcolor="#d8d8d8" valign="top">android.permission.EXPAND_STATUS_BAR，允许程序扩展或收缩状态栏</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">工厂测试模式</td> <td valign="top">android.permission.FACTORY_TEST，允许程序运行工厂测试模式</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用闪光灯</td> <td bgcolor="#d8d8d8" valign="top">android.permission.FLASHLIGHT，允许访问闪光灯</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">强制后退</td> <td valign="top">android.permission.FORCE_BACK，允许程序强制使用back后退按键，无论Activity是否在顶层</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">访问账户Gmail列表</td> <td bgcolor="#d8d8d8" valign="top">android.permission.GET_ACCOUNTS，访问GMail账户列表</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">获取应用大小</td> <td valign="top">android.permission.GET_PACKAGE_SIZE，获取应用的文件大小</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">获取任务信息</td> <td bgcolor="#d8d8d8" valign="top">android.permission.GET_TASKS，允许程序获取当前或最近运行的应用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">允许全局搜索</td> <td valign="top">android.permission.GLOBAL_SEARCH，允许程序使用全局搜索功能</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">硬件测试</td> <td bgcolor="#d8d8d8" valign="top">android.permission.HARDWARE_TEST，访问硬件辅助设备，用于硬件测试</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">注射事件</td> <td valign="top">android.permission.INJECT_EVENTS，允许访问本程序的底层事件，获取按键、轨迹球的事件流</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">安装定位提供</td> <td bgcolor="#d8d8d8" valign="top">android.permission.INSTALL_LOCATION_PROVIDER，安装定位提供</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">安装应用程序</td> <td valign="top">android.permission.INSTALL_PACKAGES，允许程序安装应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">内部系统窗口</td> <td bgcolor="#d8d8d8" valign="top">android.permission.INTERNAL_SYSTEM_WINDOW，允许程序打开内部窗口，不对第三方应用程序开放此权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">访问网络</td> <td valign="top">android.permission.INTERNET，访问网络连接，可能产生GPRS流量</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">结束后台进程</td> <td bgcolor="#d8d8d8" valign="top">android.permission.KILL_BACKGROUND_PROCESSES，允许程序调用killBackgroundProcesses(String).方法结束后台进程</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">管理账户</td> <td valign="top">android.permission.MANAGE_ACCOUNTS，允许程序管理AccountManager中的账户列表</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">管理程序引用</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MANAGE_APP_TOKENS，管理创建、摧毁、Z轴顺序，仅用于系统</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">高级权限</td> <td valign="top">android.permission.MTWEAK_USER，允许mTweak用户访问高级系统权限</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">社区权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MTWEAK_FORUM，允许使用mTweak社区权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">软格式化</td> <td valign="top">android.permission.MASTER_CLEAR，允许程序执行软格式化，删除系统配置信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">修改声音设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MODIFY_AUDIO_SETTINGS，修改声音设置信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">修改电话状态</td> <td valign="top">android.permission.MODIFY_PHONE_STATE，修改电话状态，如飞行模式，但不包含替换系统拨号器界面</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">格式化文件系统</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MOUNT_FORMAT_FILESYSTEMS，格式化可移动文件系统，比如格式化清空SD卡</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">挂载文件系统</td> <td valign="top">android.permission.MOUNT_UNMOUNT_FILESYSTEMS，挂载、反挂载外部文件系统</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">允许NFC通讯</td> <td bgcolor="#d8d8d8" valign="top">android.permission.NFC，允许程序执行NFC近距离通讯操作，用于移动支持</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">永久Activity</td> <td valign="top">android.permission.PERSISTENT_ACTIVITY，创建一个永久的Activity，该功能标记为将来将被移除</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">处理拨出电话</td> <td bgcolor="#d8d8d8" valign="top">android.permission.PROCESS_OUTGOING_CALLS，允许程序监视，修改或放弃播出电话</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取日程提醒</td> <td valign="top">android.permission.READ_CALENDAR，允许程序读取用户的日程信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取联系人</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_CONTACTS，允许应用访问联系人通讯录信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">屏幕截图</td> <td valign="top">android.permission.READ_FRAME_BUFFER，读取帧缓存用于屏幕截图</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取收藏夹和历史记录</td> <td bgcolor="#d8d8d8" valign="top">com.android.browser.permission.READ_HISTORY_BOOKMARKS，读取浏览器收藏夹和历史记录</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取输入状态</td> <td valign="top">android.permission.READ_INPUT_STATE，读取当前键的输入状态，仅用于系统</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取系统日志</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_LOGS，读取系统底层日志</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取电话状态</td> <td valign="top">android.permission.READ_PHONE_STATE，访问电话状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取短信内容</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_SMS，读取短信内容</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取同步设置</td> <td valign="top">android.permission.READ_SYNC_SETTINGS，读取同步设置，读取Google在线同步设置</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取同步状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_SYNC_STATS，读取同步状态，获得Google在线同步状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">重启设备</td> <td valign="top">android.permission.REBOOT，允许程序重新启动设备</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">开机自动允许</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECEIVE_BOOT_COMPLETED，允许程序开机自动运行</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">接收彩信</td> <td valign="top">android.permission.RECEIVE_MMS，接收彩信</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">接收短信</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECEIVE_SMS，接收短信</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">接收Wap Push</td> <td valign="top">android.permission.RECEIVE_WAP_PUSH，接收WAP PUSH信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">录音</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECORD_AUDIO，录制声音通过手机或耳机的麦克</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">排序系统任务</td> <td valign="top">android.permission.REORDER_TASKS，重新排序系统Z轴运行中的任务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">结束系统任务</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RESTART_PACKAGES，结束任务通过restartPackage(String)方法，该方式将在外来放弃</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">发送短信</td> <td valign="top">android.permission.SEND_SMS，发送短信</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置Activity观察其</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_ACTIVITY_WATCHER，设置Activity观察器一般用于monkey测试</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置闹铃提醒</td> <td valign="top">com.android.alarm.permission.SET_ALARM，设置闹铃提醒</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置总是退出</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_ALWAYS_FINISH，设置程序在后台是否总是退出</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置动画缩放</td> <td valign="top">android.permission.SET_ANIMATION_SCALE，设置全局动画缩放</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置调试程序</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_DEBUG_APP，设置调试程序，一般用于开发</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置屏幕方向</td> <td valign="top">android.permission.SET_ORIENTATION，设置屏幕方向为横屏或标准方式显示，不用于普通应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置应用参数</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_PREFERRED_APPLICATIONS，设置应用的参数，已不再工作具体查看addPackageToPreferred(String) 介绍</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置进程限制</td> <td valign="top">android.permission.SET_PROCESS_LIMIT，允许程序设置最大的进程数量的限制</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置系统时间</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_TIME，设置系统时间</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置系统时区</td> <td valign="top">android.permission.SET_TIME_ZONE，设置系统时区</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置桌面壁纸</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_WALLPAPER，设置桌面壁纸</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置壁纸建议</td> <td valign="top">android.permission.SET_WALLPAPER_HINTS，设置壁纸建议</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">发送永久进程信号</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SIGNAL_PERSISTENT_PROCESSES，发送一个永久的进程信号</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">状态栏控制</td> <td valign="top">android.permission.STATUS_BAR，允许程序打开、关闭、禁用状态栏</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">访问订阅内容</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SUBSCRIBED_FEEDS_READ，访问订阅信息的数据库</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入订阅内容</td> <td valign="top">android.permission.SUBSCRIBED_FEEDS_WRITE，写入或修改订阅内容的数据库</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">显示系统窗口</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SYSTEM_ALERT_WINDOW，显示系统窗口</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">更新设备状态</td> <td valign="top">android.permission.UPDATE_DEVICE_STATS，更新设备状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用证书</td> <td bgcolor="#d8d8d8" valign="top">android.permission.USE_CREDENTIALS，允许程序请求验证从AccountManager</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">使用SIP视频</td> <td valign="top">android.permission.USE_SIP，允许程序使用SIP视频服务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用振动</td> <td bgcolor="#d8d8d8" valign="top">android.permission.VIBRATE，允许振动</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">唤醒锁定</td> <td valign="top">android.permission.WAKE_LOCK，允许程序在手机屏幕关闭后后台进程仍然运行</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入GPRS接入点设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_APN_SETTINGS，写入网络GPRS接入点设置</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入日程提醒</td> <td valign="top">android.permission.WRITE_CALENDAR，写入日程，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入联系人</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_CONTACTS，写入联系人，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入外部存储</td> <td valign="top">android.permission.WRITE_EXTERNAL_STORAGE，允许程序写入外部存储，如SD卡上写文件</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入Google地图数据</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_GSERVICES，允许程序写入Google Map服务数据</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入收藏夹和历史记录</td> <td valign="top">com.android.browser.permission.WRITE_HISTORY_BOOKMARKS，写入浏览器历史记录或收藏夹，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读写系统敏感设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_SECURE_SETTINGS，允许程序读写系统安全敏感的设置项</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读写系统设置</td> <td valign="top">android.permission.WRITE_SETTINGS，允许读写系统设置项</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">编写短信</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_SMS，允许编写短信</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入在线同步设置</td> <td valign="top">android.permission.WRITE_SYNC_SETTINGS，写入Google在线同步设置</td></tr></tbody></table></div><br /></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-18 15:58 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【APK教程】合并odex与apk至完整apk</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:57:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197883.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197883.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197883.html</trackback:ping><description><![CDATA[<div><strong>Android的 ROM中有很多odex文件，相对于APK中的dex文件而言这个odex有什么作用呢?  如果你仔细观察会发现文件名时一一对应的，同时那些对应的apk文件中没有dex文件。这样做可以使其厂商保证一定的反盗版，因为没有没有dex文件的  apk是无法正常安装的，而厂商直接将odex和不完整的apk文件放到手机rom固化到/system/bin中可以让一般用户无法正常导出使用<br /> <br /> 可能想到的是合并odex和apk变成apk中包含dex文件的，这样合并后最终apk文件安装在/data/中，而rom存放在 /system/app中，所以最终导致了用户可装在Android手机中的软件会变少，占用系统空间。<br /> &nbsp;&nbsp;1. 下载 </strong><a href="http://smali.googlecode.com/files/smali-1.2.2.jar" target="_blank"><strong>http://smali.googlecode.com/files/smali-1.2.2.jar</strong></a><strong>&nbsp;&nbsp;和 </strong><a href="http://smali.googlecode.com/files/baksmali-1.2.2.jar" target="_blank"><strong>http://smali.googlecode.com/files/baksmali-1.2.2.jar</strong></a><strong> ，既然是需要盗版，还需要odex所在rom中的一些引用类，一般在 /system/framework 目录中<br /> <br /> &nbsp;&nbsp;2 .&nbsp;&nbsp;通过odex生成class文件<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; java -jar baksmali-1.2.2.jar -x android123.odex<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;执行完上面这行命令后，会生成一个out 文件夹里面是android123.odex的class文件。出现问题，根据提示可以从rom的 /system/framework 中的**.jar放到pc上的java环境变量中一起生成。<br /> <br /> &nbsp;&nbsp;3. 通过class生成classes.dex 文件。<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex<br /> <br /> &nbsp;&nbsp;4. 将classes.dex放到apk文件<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;因为apk是zip的mime编码类型，使用winzip或winrar直接拖入到apk改名为zip的压缩包中即可。<br /> <br /> &nbsp;&nbsp;5. 不要忘记了签名，使用jdk中的arsigner和keytool打包重新签名即可。 <br /> 有时候发现别人手机里有一款 apk 挺好，想弄出来装自己手机上，可是却发现那个 apk 是残缺的，里面没有 classes.dex  文件，却有个跟 apk 同名的 odex 文件。残缺的 apk 是装不了的，只能把这个 apk 跟 odex 合并成一个完整的 apk  才能安装。 需要的工具： <br /> 1 ． smali-1.2.2.jar 和 baksmali-1.2.2.jar <br /> 2 ． 还需要这个 apk 所在的 rom 里面的一些 jar 文件，都在 /system/framework 里面： core.jar,  ext. jar, framework. jar, android.policy. jar, services. Jar 。 <br /> 当然，这五个是最基本的，有可能还不够，这种情况下面会讲到。 <br /> <br /> <br /> 总共分四步： <br /> 1 ． 把下载好的 smali-1.2.2.jar 和 baksmali-1.2.2.jar ，还有 rom 里面抠出来的 5 个 jar ，放到工作目录，然后 apk 和 odex 也放到一起。 <br /> 2 ． 分解 odex 文件为 class 文件。命令： java -jar baksmali-1.2.2.jar -x 处是你要分解的  odex 文件的名字，命令完成之后，会生成一个 out 文件夹，里面就是所有的 class  文件。如果出现问题，比如什么异常，缺少包什么的，就更到 rom 里面把出错信息里面要求的包拿出来，放到当前目录下。 <br /> 3． 将 class 生成为 classes.dex 文件。命令： java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex 这一步应该不会有什么问题，然后会生成 classes.dex 文件。 <br /> 4． 把 classes.dex 放入 apk 里面，把盖子盖上。最后这一步最简单了，用解压缩软件打开 apk ，然后把千辛万苦生成的  classes.dex 塞进去，就 ok 了。这个 apk 就能用了。如果想给他重新签个名的话，去找个 Auto Sign  签名工具签署一下就行。 </strong></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:57 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android Rom修改制作工具软件集合</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:56:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197882.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197882.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197882.html</trackback:ping><description><![CDATA[<div><p><strong>1.SIN2IMG</strong>&nbsp;&nbsp; &nbsp;</p> <p>　　用于固件ftf中system.sin的解包&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址: SIN2IMG.rar &nbsp;</p> <p>　　使用方法:将固件ftf文件用rar打开，解压出system.sin文件，将该文件于SIN2IMG.exe放在同一个文件夹里面，比如说 X:\下，进入CMD，用cd命令进入X:\目录，输入SIN2IMG.exe system.sin  system.img稍等一会，system.img就解包出来了。</p> <p><strong>2.unyaffs&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　用于system.img文件的解包&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:&nbsp; Unyaffs.rar &nbsp;</p> <p>　　使用方法:将上一步解包出来的system.img文件与下载好的unayffs.exe文件放在同一个文件夹里面，比如说X:\下，进入 CMD，用cd命令进入X:\目录，输入unyaffs.exe  system.img稍等一会，system.img中的内容即可解包出来，包含有rom的全部程序和其他内容。</p> <p><strong>3.Cygwin&nbsp;&nbsp;</strong></p> <p>　　Htc厨房，适用于win环境下自制rom(非linux下使用的版本)，包括预root、创建刷机脚本、App2SD、开机脚本设定等以及rom打包签名。&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhzeovtf ( 已修复不能解压问题 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　使用方法:解压下载好的rar文件，比如解压到X:\目录下。进入X:\Cygwin目录，找到Cygwin.bat文件，右键选择编辑,看到 这一行:chdir d:\cygwin\bin，将其改为chdir  X:\cygwin\bin，然后进入X:\Cygwin\home，将user目录改名为你当前操作系统用户的名字（即登录windows时候显示的用 户名），然后返回上级目录双击Cygwin.bat即可打开厨房</p> <p><strong>4.Rom-Sign&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　rom签名工具&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Rom-Sign.rar &nbsp;</p> <p>　　使用方法:解压到X:\目录下，将需要签名的rom包(zip包)改名为update.zip，然后双击Sign.bat，生成的update_sign.zip就是签名好的rom。</p> <p>　　5.APKtool&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　反编译和回编译以及签名apk工具(如何修改框架、布局、资源文件请自行学习)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址: 1) Apktool_v1.rar这版画面比较亲和适合小白使用&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</p> <p>　　2) APKtoolv132.rar 这版比较给力，使用说明程序已经很直白了，就不多说了</p> <p><strong>6.Xtemp&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　dex解包和打包工具&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Xtemp.rar &nbsp;</p> <p>　　使用方法:将需要解包的.dex文件放置于Xtemp目录下，将.dex文件拖动至dex.bat文件，即可出现批处理窗口，然后选择1解包即 可。解压后是一个完整的文件夹，打包的时候将文件夹拖动至dex.bat文件，即可出现批处理窗口，选择2打包即可完成打包，之后生成打包好的.dex文 件</p> <p><strong>7.APK manager&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　批量处理APK工具&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Apk Manager.rar &nbsp;</p> <p>　　使用方法:程序本身已经写的很清楚了，不再过多解释</p> <p><strong>8.draw9patch&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　用于索引png文件修改和打包工具&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: 9png.rar &nbsp;</p> <p>　　使用方法:先用PS等软件处理图片，然后再用9png来处理，最后用X那个软件打包。</p> <p><strong>9.Java JDK&nbsp;</strong></p> <p>　　Java环境安装程序，这个必须装，不然以上以下的程序有可能运行不了。&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhze9xyf</p> <p><strong>10.Android-sdk</strong></p> <p>　　安卓SDK这个就不说了，下了选择你需要的API下载&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/clg28r43</p> <p><strong>11.eclipse&nbsp;&nbsp;&nbsp;</strong></p> <p>　　最新的Eclipse JAVA编译环境&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhzeezng</p> <p><strong>12.ADT&nbsp;&nbsp;&nbsp;&nbsp;</strong>&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhze92e2</p> <p><strong>13.Repo:</strong></p> <div> <pre><span style="color: #008080;">1</span> mkdir -p ~/bin <br /><span style="color: #008080;">2</span> curl <span style="color: #800000;">"</span><span style="color: #800000;">http://php.webtutor.pl/en/wp-content/uploads/2011/09/repo</span><span style="color: #800000;">"</span>&gt; ~/bin/repo <br /><span style="color: #008080;">3</span> chmod a+x ~/bin/repo</pre> </div> <p><strong>14.ROM源代码</strong></p> <p>CM7完整源码:</p> <div> <pre><span style="color: #008080;">1</span> mkdir -p ~/android/system<br /><span style="color: #008080;">2</span> cd ~/android/system/<br /><span style="color: #008080;">3</span> repo init -u git:<span style="color: #008000;">//</span><span style="color: #008000;">github.com/CyanogenMod/android.git -b gingerbread</span><span style="color: #008000;"><br /></span><span style="color: #008080;">4</span> repo sync</pre> </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:56 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Android软件破解的经验总结 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:52:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197881.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197881.html</trackback:ping><description><![CDATA[<div>android软件破解的工具：<br /> smali.jar&#8212;&#8212;google官方提供，主要作用是把smali文件打包成class.dex文件<br /> baksmali.jar&#8212;&#8212;google官方提供，主要作用是把*.odex文件反编译为smali文件<br /> apktool.jar&#8212;&#8212;第三方提供？用于解析*.apk文件，生成smali文件和解析资源文件<br /> signapk.jar&#8212;&#8212;apk签名工具<br /> ddms&#8212;&#8212;ADT中的一个调试工具<br /> <br /> <br /> 破解工具的使用方法：<br /> http://sin90lzc.iteye.com/blog/1198173<br /> <br /> <br /> 除了这些破解工具之外，还需要对smali语法有一定的了解。下面的网址对smali的语法有详细的说明：<br /> http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html<br /> <br /> <br /> 最后，最好对Android的应用开发有一定的了解，至少对Android的四大组件有深刻的认识：Activity,Service,ContentProvider,BroadcastReceiver<br /> <br /> <br /> Android应用程序在某些机器上不能运行、崩溃的原因不外乎以下几点：<br /> 原因一：该应用程序需要依赖于生产厂商的框架（像三星，它对android的framework做过大量的修改）<br /> 错误提示：找不到field，找不到对应的方法，找不到相应的类<br /> 解决途径：<br /> 1.在smali中尝试屏蔽掉相应的field,method,或类的调用，然后进行大量测试，确保不影响正常使用<br /> 2.反编译framework，找到缺少的field,method,类的相应smali文件，根据smali文件编写java源码。（当smali文件比较小的时候，这个方法才可行，否则尽量避免用这种方法）<br /> 3.实在无招的情况下，只能把第三方的framework的smali文件复制到自己的framework里面（非常槽糕的方法）。<br /> 4.对于应用程序需要依赖第三方低层的功能实现时，而我们的低层却没有这样的功能（比如说视频通话等），此时可以使用上面的方法一解决，也可以参考技术四。<br /> <br /> <br /> 原因二：资源文件不存在，像color，drawable,string等等的资源<br /> 错误提示：资源文件找不到<br /> 解决途径：<br /> 在技巧一中有详细说明。<br /> <br /> <br /> 原因三：应用程序需要一些函数库的支持（在目录/system/lib中缺少相应的函数库）。<br /> 错误提示：一般都会抛出UnSatisfiedException异常，后面紧跟所缺函数库的库名。<br /> 解决途径：<br /> 1.在第三方的函数库中找到对应的so文件，然后复制到自己的函数库中。<br /> 2.如果函数库与函数库之间有着各种耦合的时候，方法一可能就会不适用了（看运气呗）。这时候就只能反编译so文件了（这个是C/C++的反编译的应用了，需要再学习）<br /> <br /> <br /> 原因四：应用程序没有相应的权限<br /> 错误提示：nopermission<br /> 解决途径：<br /> 1.在AndroidMenifest.xml文件中添加&lt;user-permision /&gt;添加相应的权限<br /> <br /> <br /> 原因五：由于应用程序本身的一些安全机制或条件判断影响程序的表现<br /> 解决途径：<br /> 1.反编译成smali文件，使用技巧三的方法跟踪程序的运行，耐心地分析程序的逻辑，找到可疑smali代码，屏蔽或修改代码。<br /> <br /> <br /> 原因六：数据库的结构不一样<br /> 错误提示：缺少某个字段或类型不匹配<br /> 场情：比如android的音乐播放器与三星的音乐播放器，它们的数据库结构由MediaProvider.apk这个包提供。然而两者在MediaProvider.apk中关于数据库结构的定义是不一样的，三星音乐播放器需要更多的字段去保存信息。<br /> 解决途径：<br /> 1.拿上面场情为例，反编译MediaProvider.apk，从smali文件中找到组件ContentProvider的定义（smali文件）， 在该smali文件中找到关于SQL生成表结构的字符串（如：create  table...)，修改该SQL语句来适合三星音乐播放器的需要，然后重新打包回apk文件。<br /> <p><br /> </p> <p>原因七：应用程序需要引用第三方提供商自定义的框架（比如，三星的/system/framework目录下有twframework.jar、twframework-res.apk，这个就是三星的UI框架)</p> 错误提示：<br /> 解决途径：<br /> 1.屏蔽AndroidMenifest.xml文件中&lt;uses-library android:name="sec_feature" /&gt;的代码，一般这样改动是不可行的。<br /> 2.在/system/etc/permission目录下添加库的声明，如添加touchwiz.xml文件，文件内容如下：<br /> &lt;?xml version="1.0" encoding="utf-8"?&gt;<br /> &lt;permissions&gt;<br /> &nbsp; &nbsp; &lt;library name="touchwiz" file="/system/framework/twframework.jar"/&gt;<br /> &lt;/permissions&gt;<br /> 最后，还需要把三星的twframework.jar、twframework-res.apk复制到/system/framework目录下<br /> <br /> 反编译或破解的技巧总结：<br /> 一、对无应用程序源码的情况下，对资源文件的增删改。<br /> 概述：在无程序源码，不重新编译的情况下，删除或修改资源文件都是非常简单的一件事情，网上也有很多的文章提到过。但是网上却找不到在不重新编译的情况下添加资源文件的方法。<br /> 在不重新编译的情况下添加资源文件的步骤：<br /> 1.按正常的应用程序开发添加资源。比如，要添加一个string资源，在values/strings.xml上加上：<br /> &lt;string name="newstring"&gt;content&lt;/string&gt;<br /> <br /> <br /> 2.一个编译后的apk会在values目录下多生成了一个public.xml文件，这个文件记录了每个资源的引用编号。以添加string资源为例， 在public.xml文件中找到&lt;public type="string" ...&gt;中最后一个元素，在这个元素后添加<br /> &lt;public type="string" name="newstring" id="0x7f0700a0"  /&gt;&lt;!--此时id就是string资源newstring的引用编号，注意该id应该是public.xml文件中是唯一值--&gt;<br /> <br /> <br /> 3.修改smali文件，使用新增的资源<br /> invoke-virtual {p0}, Lcom/sini/SfsdfsActivity;-&gt;getResources()Landroid/content/res/Resources;<br /> <br /> <br /> move-result-object v0<br /> <br /> <br /> const v1, 0x7f0700a0<br /> <br /> <br /> invoke-virtual {v0, v1}, Landroid/content/res/Resources;-&gt;getString(I)Ljava/lang/String;<br /> <br /> <br /> 二、编写smali文件<br /> 概述：自己一手一脚去写smali文件是件超级困难的事情，如何快速地得到smali代码呢？<br /> 技巧：使用eclipse开发工具，新建一个Android项目，用正常的开发方式写一段java代码（这个代码就是你想在smali中完成的东西）。使 用eclipse的run-&gt;Android Application选项  生成apk文件，再把apk文件反编译，找到需要的smali代码，然后复制这段代码到需要的地方。NOTIC：复制的时候需要注意smali的变量 v0,v1...的正确性。<br /> <br /> <br /> 三、跟踪程序运行<br /> 概述：没源码=寸步难行！为了能跟踪无源码的apk程序的运行，只能辛苦地修改smali添加跟踪信息了。值得庆幸的是，android本身自带有方便的日志API(Log.i()\Log.w()...);<br /> 技巧：按技巧二的方法得到Log.i()的smali代码，然后把这段代码插入到你想跟踪信息的地方。<br /> <br /> <br /> 四、只修改smali中影响UI的代码，保留功能代码（适用于必须得把smali写回java源码的情况）<br /> 概述：这里最好的例子就是破解三星的通话界面。三星的通话界面程序Phone.apk中包含了视频通话的功能，这个功能又需要依赖三星的一些低层实现。而 我们的系统中没有视频通话的功能，也没有相应的低层实现。但Phone.apk的主要功能是打电话，而这个功能android本身就自带的。也就是说三星 的Phone.apk与android的Phone.apk的核心功能是一样的，只是UI不太一样而已。此时应该只修改smali中的影响UI的代码，屏 蔽掉<br /> smali中对视频通话的调用。<br /> 技巧：找到程序中影响UI的Actvity，然后根据smali文件的内容，写java源码  </div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:52 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让你自己写的Android的Launcher成为系统中第一个启动的，也是唯一的Launcher. (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:51:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197880.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197880.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197880.html</trackback:ping><description><![CDATA[<div><span style="font-size: 14px; line-height: 21px; font-family: verdana, sans-serif">原文:<div>http://1622511.blog.51cto.com/1612511/581011</div><br />如果你要定制一个Android系统，你想用你自己的Launcher(Home)作主界面来替换Android自己的Home，而且不希望用户安装的Launcher来替换掉你的Launcher.<br /> 我们可以通过修改Framework来实现这样的功能。<br /> <br /> 这里以Android2.1的源代码为例来实际说明。<br /> <br /> 1)首先了解一下Android的启动过程。<br /> &nbsp; Android系统的启动先从Zygote开始启动，然后......(中间的过程就不说了).....一直到了SystemServer(framework)这个地方，看到这段代码：<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br /> &nbsp;&nbsp;&nbsp;&nbsp; * This method is called from Zygote to initialize the system. This will cause the native<br /> &nbsp;&nbsp;&nbsp;&nbsp; * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back<br /> &nbsp;&nbsp;&nbsp;&nbsp; * up into init2() to start the Android services.<br /> &nbsp;&nbsp;&nbsp;&nbsp; */<br /> &nbsp;&nbsp;&nbsp; native public static void init1(String[] args);<br /> <br /> &nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SamplingProfilerIntegration.isEnabled()) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SamplingProfilerIntegration.start();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer = new Timer();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer.schedule(new TimerTask() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SamplingProfilerIntegration.writeSnapshot("system_server");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // The system server has to run all of the time, so it needs to be<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // as efficient as possible with its memory usage.<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.loadLibrary("android_servers");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init1(args);<br /> &nbsp;&nbsp;&nbsp; }<br /> <br /> &nbsp;&nbsp;&nbsp; public static final void init2() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.i(TAG, "Entered the Android system server!");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread thr = new ServerThread();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thr.setName("android.server.ServerThread");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thr.start();<br /> &nbsp;&nbsp;&nbsp; }<br /> }<br /> <br /> 从SystemServer的main函数开始启动各种服务。<br /> 首先启动init1,然后启动init2.<br /> 从上面的注释可以看到：init1这个方法时被Zygote调用来初始化系统的，init1会启动native的服务如SurfaceFlinger,AudioFlinger等等，这些工作做完以后会回调init2来启动Android的service。<br /> <br /> 这里我们主要来关注init2的过程。<br /> init2中启动ServerThread线程，<br /> ServerThread中启动了一系列的服务，比如这些：<br /> <br /> ActivityManagerService<br /> EntropyService<br /> PowerManagerService<br /> TelephonyRegistry<br /> PackageManagerService<br /> AccountManagerService<br /> BatteryService<br /> HardwareService<br /> Watchdog<br /> SensorService<br /> BluetoothService<br /> StatusBarService<br /> ClipboardService<br /> InputMethodManagerService<br /> NetStatService<br /> ConnectivityService<br /> AccessibilityManagerService<br /> NotificationManagerService<br /> MountService<br /> DeviceStorageMonitorService<br /> LocationManagerService<br /> SearchManagerService<br /> FallbackCheckinService<br /> WallpaperManagerService<br /> AudioService<br /> BackupManagerService<br /> AppWidgetService<br /> <br /> 这些大大小小的服务起来以后，开始<br /> &nbsp;((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()<br /> 在systemReady后开始开始启动Launcher。<br /> <br /> 在寻找Launcher的时候是根据HOME的filter（在Manifest中定义的&lt;category android:name="android.intent.category.HOME" /&gt;）来过滤。<br /> 然后根据filter出来的HOME来启动，如果只有一个HOME，则启动这个HOME，如果用户自己装了HOME，那就会弹出来一个列表供用户选择。<br /> <br /> 我们现在希望从这里弹出我们自己定制的Launcher,同时也不希望弹出选择HOME的界面，我们不希望用户修改我们的home，比如我们的home上放了好多广告，以及强制安装的程序，不希望用户把它干掉。<br /> <br /> 我们可以通过这样来实现：<br /> <br /> 2) 定义一个私有的filter选项，然后用这个选项来过滤HOME.<br /> &nbsp;&nbsp; 一般情况下我们使用Manifest中定义的&lt;category android:name="android.intent.category.HOME"来过滤的，我们现在增加一个私有的HOME_FIRST过滤。<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp; 在Intent.java(frameworks/base/core/java/android/content/Intent.java)中添加两行代码<br /> <br /> &nbsp;&nbsp;&nbsp; //lixinso:添加CATEGORY_HOME_FIRST<br /> &nbsp;&nbsp;&nbsp; @SdkConstant(SdkConstantType.INTENT_CATEGORY)<br /> &nbsp;&nbsp;&nbsp; public static final String CATEGORY_HOME_FIRST = "android.intent.category.HOME_FIRST";<br /> <br /> 3）修改和CATEGORY_HOME相关的所有的地方，都改成HOME_FIRST，主要是framework中的这几个地方：<br /> <br /> &nbsp;&nbsp;&nbsp; frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中<br /> &nbsp;&nbsp;&nbsp; //intent.addCategory(Intent.CATEGORY_HOME);<br /> &nbsp;&nbsp;&nbsp; 改成intent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:<br /> &nbsp;&nbsp;&nbsp; //if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {<br /> &nbsp;&nbsp;&nbsp; 改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -&gt; Intent.CATEGORY_HOME_FIRST<br /> &nbsp;<br /> &nbsp;&nbsp; frameworks/base/services/java/com/android/server/am/HistoryRecorder.java中<br /> &nbsp;&nbsp; // _intent.hasCategory(Intent.CATEGORY_HOME) &amp;&amp;<br /> &nbsp;&nbsp; 改成 _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) &amp;&amp; //lixinso: Intent.CATEGORY_HOME-&gt;Intent.CATEGORY_HOME_FIRST<br /> <br /> &nbsp;&nbsp; frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java中<br /> &nbsp;&nbsp; //mHomeIntent.addCategory(Intent.CATEGORY_HOME);&nbsp;<br /> &nbsp;&nbsp; 改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso<br /> &nbsp;<br /> &nbsp; frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java中<br /> &nbsp;&nbsp; //new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);<br /> &nbsp;&nbsp; 改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso<br /> <br /> &nbsp; frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中<br /> &nbsp;&nbsp; //mHomeIntent.addCategory(Intent.CATEGORY_HOME);<br /> &nbsp;&nbsp; 改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso<br /> <br /> &nbsp; frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java中<br /> &nbsp;&nbsp; //ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);<br /> &nbsp;&nbsp; 改成 ResolveInfo homeInfo = pm.resolveActivity(new  Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0);  //lixinso<br /> <br /> <br /> <br /> 4) 写一个自己的Launcher.<br /> &nbsp;&nbsp; 可以参考android sample中的Launcher，或者android源代码中的 /packages/apps/Launcher 来写。<br /> &nbsp;&nbsp; 在Launcher中标记其是不是Launcher的最关键的代码时Manifest中的filter:android:name="android.intent.category.HOME"<br /> &nbsp;&nbsp; 现在我们定义了自己的filter,那么，我们在我们自己写的Launcher中将Manifest改为：<br /> &nbsp;&nbsp;&nbsp; &lt;application&nbsp; android:process="android.process.acore3" android:icon="@drawable/icon" android:label="@string/app_name"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".FirstAppActivity"<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:label="@string/app_name"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;intent-filter&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action android:name="android.intent.action.MAIN" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.HOME_FIRST" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.DEFAULT" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.MONKEY" /&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/intent-filter&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/application&gt;<br /> <br /> 然后将编译好的apk放到/out/target/product/generic/system/app目录下。<br /> <br /> 5)将Android自带的Launcher删除掉，包括源代码(packages/apps/Launcher)和apk(/out/target/product/generic/system/app/Launcher.apk)。<br /> <br /> 6)<br /> 做完这些工作，就可以重新编译Android了，我们可以编译修改过的几个相关的包。<br /> 如果之前编译过了Android源码，可以用mmm命令来编译部分的改动。<br /> 这里需要这样编译：<br /> <br /> $ . build/envsetup.sh&nbsp;<br /> $ mmm frameworks/base<br /> $ mmm frameworks/base/services/java<br /> $ mmm frameworks/policies/base/mid<br /> $ mmm frameworks/policies/base/phone<br /> <br /> 7)<br /> 编译完成后重新生成img文件。<br /> $ make snod<br /> <br /> 8) 现在可以启动Android模拟器来看效果了。<br /> 首先设置环境变量：<br /> $ export ANDROID_PRODUCT_OUT= ./out/target/product/generic<br /> 然后切换到<br /> $ cd ./out/host/linux-x86/bin<br /> 运行<br /> $ ./emulator<br /> <br /> 这样我们启动的模拟器里面用的image就是我们刚才编译好的自己定制的东西了。<br /> 从模拟器上可以看到启动的Launcher是我们自己的Launcher，不会出现默认的Launcher了，也不会出现选择界面。<br /> <br /> 9)我们再验证一下，如果用户装上了一个其他的Launcher(Home)会怎么样。<br /> &nbsp; 从网上找一个一般的Launcher或者自己写一个一般的Launcher装上去，重新启动，不会出现选择界面。<br /> &nbsp; 按HOME键也不会出来两个HOME来选择。<br /> <br /> <br /> 这样我们就牢牢控制了用户的桌面。<br /> 只有我们自己定制的HOME才能装上。 这对于定制Android设备的厂商很有用处。</span></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:51 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 移植 (1)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:48:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197879.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197879.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197879.html</trackback:ping><description><![CDATA[<div>要移植，就要了解系统的结构和打包解包：<br /> 打包很容易，只需要制作成ZIP格式的压缩包就行了，里面包含2个文件夹和1个boot.img文件，boot.img是内核，没有内核的系统是不能运行 的，另外两个文件夹一个是system，也就是Android系统所在地，另一个是META-INF，这里一般存放是刷机脚本，我们移植一般需要改的就是 system文件夹里的内容。<br /> 解包就是解压缩。<br /> 首先说结构，system下有：<br /> App文件夹（存放内置软件的地方，每个软件都有自己的名字标注着，很容易识别，在移植上除USB.apk必须用咱们自己的版本以外，其他可以用同分辨率机型的APP直接替换）<br /> Bin文件夹（本文件夹一般存放的是开机运行的脚本和一些系统必备代码，一般移植出了问题不能开机就是这里的问题，一般我们用702的或者720的ROM 里的，注意除了NETD需要用701的外，其他也可以直接用702或者720ROM的，不过一般系统升级不会修改这里，在移植的时候，要删除2nd- init以及所有.sh脚本文件，这些对701是没有效果的，如果电池显示？，那么可以通过替换battd文件来修複）<br /> Etc文件夹（本文件夹里存放着这种配置文件，包括WIFI，蓝牙和基带{\etc\motorola\bp_nvm_default}配置文件，A- GPS的文件和Hosts文件也在这里，media_profiles.xml可以控制录像质量，cameraCalFileDef5M.bin与 cameraCalFileDef8M.bin是照相的数据库文件，都可以修改，子文件夹init.d文件夹下可以写入自己的开机脚本，来实现一些程序或 者脚本开机啓动，如果想要执行某模块，可以添加一个文件，不要有后缀名，格式爲00aaa&nbsp;&nbsp;00是执行序号，系统开机时会按顺序执行，aaa是爲了区别 每个脚本的名称，可以随便写）<br /> Font文件夹（字体文件夹，没什么好解释的，你可以替换爲你喜欢的字体）<br /> Framework文件夹（系统框架结构文件目录，这个目录下是系统服务和系统界面的所在地，一般不可以单独替换，要移植的话必须全部替换，不然会卡 M，framework-res.apk文件就是系统语言，界面的所在文件，修改他就可以直接修改系统界面，framework-res.apk必须与 app文件夹中systemui.apk配套，不然开机会出现状态栏FC，不同版本不可以乱用，比如CM7.1.0.5不能用CM7.1.0.4的文件）<br /> Lib文件夹（本文件夹是系统所需要用到的驱动，库文件的所在，如果某程序FC或者无法正常运转，可能是这里的问题，我把我知道的一些文件的用途说一下：<br /> ***Lib/dsp文件夹 DSP驱动所在，一般不需要改<br /> ***lib/egl 显示芯片驱动，一般不需要改<br /> ***libaudio.so 话筒及音频驱动 必须用701的<br /> ***libaudioflinger.so 音频附属驱动 必须用701的<br /> ***libbridge.so 相机方面 <br /> ***libbattd.so&nbsp;&nbsp;电池驱动<br /> ***libcamera.so 相机驱动 必须用701的<br /> ***libcameraservice.so 相机服务驱动<br /> ***libfmradio.so FM驱动<br /> ***libHPImgApi.so 图片接口驱动 必须用701的<br /> ***libLCML.so 未知驱动&nbsp;&nbsp;必须用701的<br /> ***liboemcamera.so 相机驱动&nbsp;&nbsp;必须用701的<br /> ***libOMX.TI.JPEG.Encoder.so 照片编码器&nbsp;&nbsp;必须用701的 否则照片黑<br /> ***libOMX.TI.AAC.decode.so&nbsp;&nbsp;此类型的都是编码器和解码器驱动（多媒体）<br /> 除上述红色文件必须用701外，其他文件可以直接用702或者720的。<br /> Media文件夹（铃声及开机动画）<br /> TTS文件夹（文字转语音文件夹）<br /> Usr文件夹（键盘文件与各类数据库）<br /> Xbin文件夹（系统工具文件夹）<br /> Build.prop文件（系统参数文件，修改这里可以调节系统部分参数与性能）<br /> 如：默认虚拟机大小，铃声延迟，系统版本等</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:48 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JS文本域换行符和HTML换行标签的相互替换(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197712.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 04 Feb 2013 07:41:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197712.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197712.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197712.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197712.html</trackback:ping><description><![CDATA[<div>		<div fix"=""> 			<div fix"=""> <p>在项目中，我们经常要实现以下编辑器的所见所得效果，当然也要支持回车，在此做下记录，对正则表达式还不是很熟练。</p> <p>将HTML换行标签替换为文本域换行符：<br /> textereaContext = divHTML.replace(/(&lt;br&gt;)/g, &#8220;\r\n&#8221;);</p>  <div> <div>将文本域换行符替换为HTML换行标签：</div> <div>divHTML =&nbsp; textereaContext&nbsp;.replace(/\n|\r|(\r\n)|(\u0085)|(\u2028)|(\u2029)/g, &#8220;&lt;br&gt;&#8221;);</div> </div></div></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-04 15:41 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UTF-8 BOM</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197711.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 04 Feb 2013 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197711.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197711.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197711.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197711.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197711.html</trackback:ping><description><![CDATA[<div><p><div><p>在PHP中查找中文字符，有两种方案。</p> <p>1、中文字符是gbk（gb2312）</p> <p>有两种解决方法</p> <p>第一种：</p> <p>将PHP保存为ASCII编码，然后使用strpos查找，如：</p> <blockquote><p>strpos($curl_res, &#8216;哈哈&#8217;)</p> </blockquote> <p>第二种：</p> <p>将PHP保存为UTF-8无BOM编码，然后转换字符串编码为UTF-8，再查找，如：</p> <blockquote><p>$curl_res = mb_convert_encoding($curl_res, &#8216;utf-8&#8242;, &#8216;gbk&#8217;);</p> <p>mb_strpos($curl_res, &#8216;哈哈&#8217;);</p> </blockquote> <p>2、中文字符是UTF-8</p> <p>有两种解决方法</p> <p>第一种：</p> <p>将PHP保存为UTF-8无BOM编码，然后使用strpos查找，如：</p> <blockquote><p>strpos($curl_res, &#8216;哈哈&#8217;)</p> </blockquote> <p>第二种：</p> <p>将PHP保存为ASCII编码，然后转换字符串编码为gbk，再查找，如：</p> <blockquote><p>$curl_res = mb_convert_encoding($curl_res, &#8216;gbk&#8217;, &#8216;utf-8&#8242;);</p> <p>mb_strpos($curl_res, &#8216;哈哈&#8217;);</p> </blockquote> <p>应该可以看出一些规律，就是：函数中的中文字符串参数的编码和PHP文件保存格式的编码一致，在使用函数时要考虑到！</p></div></p><p><br /></p><p>&nbsp;  <wbr>&nbsp;<wbr>&nbsp;<wbr> 我生成的那个html文件被EmEditor认为UTF-8 with Signature。而好用的那个html文件被EmEditor认为UTF-8 without Signature.<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 对于这两种UTF－8格式的转换，我查看了网上信息，点击记事本，EmEditor等文本编辑器的另存为，当选择了UTF-8的编码格式时，Add a Unicode Signature(BOM)这个选项被激活，只要选择上，我的文件就可以存为UTF-8 with Signature的格式。可是，问题就在于，我用java怎么让我的文件直接生成为 UTF-8 with Signature的格式。<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 开始上google搜索UTF-8 with Signature,BOM,Add a Unicode Signature等关键字。<br /> <a href="http://www.unicode.org/unicode/faq/utf_bom.html#BOM">http://www.unicode.org/unicode/faq/utf_bom.html#BOM</a><br />  我大致了解了他们两个的区别。<br /> Q: What is a BOM?</p> <p>A: A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol.<br /> <a href="http://mindprod.com/jgloss/bom.html">http://mindprod.com/jgloss/bom.html</a><br />  BOM<br /> Byte Order Marks are special characters at the beginning of a Unicode file to indicate whether it is big or little endian, in other words does the high or low order byte come first. These codes also tell whether the encoding is 8, 16 or 32 bit. You can recognise Unicode files by their starting byte order marks, and by the way Unicode-16 files are half zeroes and Unicode-32 files are three-quarters zeros. Unicode Endian Markers<br /> Byte-order mark Description<br /> EF BB BF UTF-8<br /> FF FE UTF-16 aka UCS-2, little endian<br /> FE FF UTF-16 aka UCS-2, big endian<br /> 00 00 FF FE UTF-32 aka UCS-4, little endian.<br /> 00 00 FE FF UTF-32 aka UCS-4, big-endian.<br /> There are also variants of these encodings that have an implied endian marker.<br /> Unfortunately, often applications, even Javac.exe, choke on these byte order marks. Java Readers don't automatically filter them out. There is not much you can do but manually remove them.</p> <p><br /> <a href="http://cache.baidu.com/c?word=java%2Cbom&amp;url=http%3A//tgdem530%2Eblogchina%2Ecom/&amp;b=0&amp;a=1&amp;user=baidu"> http://cache.baidu.com/c?word=java%2Cbom&amp;url=http%3A//tgdem530%2Eblogchina%2Ecom/&amp;b=0&amp;a=1&amp;user=baidu</a><br />  c、UTF的字节序和BOM<br /> UTF-8以字节为编码单元，没有字节序的问题。UTF-16以两个字节为编码单元，在解释一个UTF-16文本前，首先要弄清楚每个编码单元的字节序。 例如收到一个&#8220;奎&#8221;的Unicode编码是594E，&#8220;乙&#8221;的Unicode编码是4E59。如果我们收到UTF-16字节流&#8220;594E&#8221;，那么这是 &#8220;奎&#8221;还是&#8220;乙&#8221;？</p> <p>Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是&#8220;Bill Of Material&#8221;的BOM表，而是Byte Order Mark。BOM是一个有点小聪明的想法：</p> <p>在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符，它的编码是FEFF。而FFFE在UCS中是不存在的字符，所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前，先传输字符"ZERO WIDTH NO-BREAK SPACE"。</p> <p> 这样如果接收者收到FEFF，就表明这个字节流是Big-Endian的；如果收到FFFE，就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。</p> <p>UTF-8不需要BOM来表明字节顺序，但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF（读者可以用我们前面介绍的编码方法验证一下）。所以如果接收者收到以EF BB BF开头的字节流，就知道这是UTF-8编码了。</p> <p>Windows就是使用BOM来标记文本文件的编码方式的。</p> <p><br /> 原来BOM是在文件的开始加了几个字节作为标记。有了这个标记，一些协议和系统才能识别。好，看看怎么加上这写字节。<br /> 终于在这里找到了<br /> <a href="http://mindprod.com/jgloss/encoding.html">http://mindprod.com/jgloss/encoding.html</a>&nbsp;<wbr><br />  UTF-8&nbsp;<wbr><br /> 8-bit encoded Unicode. ne&#233; UTF8. Optional marker on front of file: EF BB BF for reading. Unfortunately, OutputStreamWriter does not automatically insert the marker on writing. Notepad can't read the file without this marker. Now the question is, how do you get that marker in there? You can't just emit the bytes EF BB BF since they will be encoded and changed. However, the solution is quite simple. prw.write( '\ufeff' ); at the head of the file. This will be encoded as EF BB BF.<br /> DataOutputStreams have a binary length count in front of each string. Endianness does not apply to 8-bit encodings. Java DataOutputStream and ObjectOutputStream uses a slight variant of kosher UTF-8. To aid with compatibility with C in JNI, the null byte '\u0000' is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls. Only the 1-byte, 2-byte, and 3-byte formats are used. Supplementary characters, (above 0xffff), are represented in the form of surrogate pairs (a pair of encoded 16 bit characters in a special range), rather than directly encoding the character.<br /> &nbsp;<wbr><br /> prw.write( '\ufeff' );就是这个。<br /> 于是我的代码变为：<br /> public void htmlWrite(String charsetName) {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> try {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out = new BufferedWriter(new OutputStreamWriter(<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> new FileOutputStream(outFileName), "UTF-8"));<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out.write('\ufeff');<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out.write(res);<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out.flush();</p> <p> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (out != null) {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out.close();<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> } catch (Exception e) {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> try {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if (out != null) {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> out.close();<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> } catch (IOException e1) {<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print("write errors!" + e);<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> System.out.print("write errors!" + e);<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br /> 问题解决。</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-04 15:38 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/04/197711.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii RBAC(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 15 Jan 2013 11:38:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197298.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197298.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197298.html</trackback:ping><description><![CDATA[<div><h2>写在前面</h2> <ul><li>以下内容适合Yii 1.0.x，其他版本可能有略微的差别。 </li><li>根据您的评论和反馈，本文会不断进行修改和补充，以方便新学习者。 </li></ul> <h2><a name="t1"></a>开始准备</h2> <p>Yii提供了强大的配置机制和很多现成的类库。在Yii中使用RBAC是很简单的，完全不需要再写RBAC代码。所以准备工作就是，打开编辑器，跟我来。</p> <h2><a name="t2"></a>设置参数、建立数据库</h2> <p>在配置数组中，增加以下内容：</p> <div style="line-height: 12px; font-family: courier new; font-size: 12px;"> <table style="width: 100%; border-width: 0px; padding: 0px;" border="0" cellspacing="0"> <tbody> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">components</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <strong><span style="color: #00008b;">array</span></strong><span style="color: #000000;">(</span></td> </tr> <tr> <td><span style="color: #008000;">//</span><span style="color: #008000;">&#8230;&#8230;</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">authManager</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #000000;">array</span><span style="color: #000000;">(</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">class</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">CDbAuthManager</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证类名称</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">defaultRoles</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #000000;">array</span><span style="color: #000000;">(</span><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">guest</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">)</span><span style="color: #000000;">,</span><span style="color: #008000;">//默认角色</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">itemTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_item</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项表名称</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">itemChildTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_item_child</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项父子关系</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">assignmentTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_assignment</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项赋权关系</span></td> </tr> <tr> <td><span style="color: #000000;">)</span><span style="color: #000000;">,</span></td> </tr> <tr> <td><span style="color: #008000;">//</span><span style="color: #008000;">&#8230;&#8230;</span></td> </tr> </tbody> </table> </div> <p>那这三个数据表怎么建立呢？很简单，去看framework/web/auth/schema.sql。注意要和你的自定义的表名称对应起来。比如SQL文件中的AuthItem你要修改为pre_auth_item。然后在数据库中运行这个SQL文件中的语句。</p> <h2><a name="t3"></a>了解概念</h2> <p>你可能要问，剩下的代码呢？我告诉你，没有啦。RBAC系统就这样建立起来了。但是为了使用它，你需要了解它的运行机制。我会尽量讲的啰嗦一点&#8230;&#8230;（官方的RBAC文档在<a href="http://www.yiiframework.com/doc/guide/zh_cn/topics.auth" target="_blank">这里</a>，但是我曾经看了4-5遍才明白。）</p> <h3><a name="t4"></a>三个概念</h3> <p>你需要了解的是，授权项目可分为<em>operations</em>（行动）,<em>tasks</em>（任务）和 <em>roles</em>（角色）。</p> <p>一个用户拥有一个或者多个角色，比如，我们这里有三个角色：<strong>银行行长</strong>、<strong>银行职员</strong>、<strong>顾客</strong>。我们假设：</p> <ul><li><strong>张行长 </strong>有角色：银行行长、银行职员、顾客（人家自己可以存钱嘛）。 </li><li><strong>王职员 </strong>有角色：银行职员、顾客。 </li><li><strong>小李 </strong>有角色：顾客。 </li></ul> <p>那么，相应的，只要顾客可以做的事情，小李就可以做，王职员和张行长也可以。银行职员可以做的事情，王职员和张行长都可以做，小李就不可以了。</p> <p>比如，一个&#8220;顾客&#8221;可以存钱，那么拥有&#8220;顾客&#8221;角色的张行长、王职员、小李都可以存钱。&#8220;银行职员&#8221;可以打印顾客的交易记录，那么有&#8220;银行职员&#8221;角 色的张行长和王职员都可以，而小李不行，必须找一个有&#8220;银行职员&#8221;角色的人才可以打印详细的交易记录。一个&#8220;银行行长&#8221;才可以进入银行钱库提钱，那么只有 张行长可以，因为它才有&#8220;银行行长&#8221;的角色。</p> <p>这就是基于角色的认证体系，简称RBAC。</p> <h3><a name="t5"></a>角色的继承</h3> <p>角色是可以继承的，比如我们规定如下：</p> <ul><li>凡是&#8220;银行行长&#8221;都是&#8220;银行职员&#8221;，也就是说，只要银行职员可以做的事情，银行行长都可以做。 </li><li>凡是&#8220;银行职员&#8221;都是顾客，同上，顾客可以做的事情银行职员也可以做。 </li></ul> <p>那么角色关系就变成了：</p> <ul><li><strong>张行长 </strong>有角色：银行行长。 </li><li><strong>王职员 </strong>有角色：银行职员。 </li><li><strong>小李 </strong>有角色：顾客。 </li></ul> <p>这样更简单了，这就是角色的继承。</p> <h3><a name="t6"></a>任务的继承</h3> <p>一个任务（task）是可以包含另外一个任务的，我们举个例子，比如&#8220;进入银行&#8221;。</p> <p>我们设定&#8220;顾客&#8221;这个角色有&#8220;进入银行&#8221;的权限。也就是说，&#8220;顾客&#8221;可以执行&#8220;进入银行&#8221;的任务。接下来，我们假设&#8220;进入柜台&#8221;是进入银行的父权 限，也就是说，&#8220;进入柜台&#8221;包含&#8220;进入银行&#8221;。只要能&#8220;进入柜台&#8221;的人都可以&#8220;进入银行&#8221;。我们把&#8220;进入柜台&#8221;这个任务权限给&#8220;银行职员&#8221;。</p> <p>那么从角色上来说，王职员可以进入银行，因为王职员的角色是&#8220;银行职员&#8221;，而&#8220;银行职员&#8221;包含了&#8220;顾客&#8221;的角色。那么&#8220;顾客&#8221;可以进行的&#8220;任务&#8221;对于&#8220;银行职员&#8221;来说也是可以进行的。而&#8220;顾客&#8221;可以&#8220;进入银行&#8221;，那么王职员也可以&#8220;进入银行&#8221;。这是角色的继承带来的。</p> <p>我们再假设有个<strong>赵领导</strong>，是上级领导，可以进入柜台进行视察。那么，我们的任务关系是：</p> <ul><li><strong>赵领导</strong> 有任务：进入柜台。 </li></ul> <p>那么，赵领导就可以&#8220;进入银行&#8221;。因为&#8220;进入银行&#8221;是被&#8220;进入柜台&#8221;包含的任务。只要可以执行&#8220;进入柜台&#8221;的人都可以执行&#8220;进入银行&#8221;。这就是任务的继承。</p> <h3><a name="t7"></a>关于行动</h3> <p>行动是不可划分的一级。也就是说。而一个行动是不能包含其他行动的。假设我们有个行动叫&#8220;从银行仓库中提钱&#8221;。我们把这个行动作包含&#8220;进入柜台&#8221;。那么只要可以执行&#8220;从银行仓库中提钱&#8221;的角色都可以执行&#8220;进入柜台&#8221;这个任务。</p> <h3><a name="t8"></a>三者关系</h3> <ul><li>一个角色可以包含另外一个或者几个角色。 </li><li>一个角色可以包含另外一个或者几个任务。 </li><li>一个角色可以包含另外一个或者几个行动。 </li><li>一个任务可以包含另外一个或者几个任务。 </li><li>一个任务可以包含另外一个或者几个行动。 </li><li>一个行动只能被角色或者任务包含，行动是不可以包含其他，也不可再分。 </li></ul> <p>这样，就形成了一个权限管理体系。关于&#8220;任务&#8221;和&#8220;行动&#8221;，你不必思考其字面上的意义。这两者就是形成两层权限。</p> <h2><a name="t9"></a>进行赋权</h2> <p>我们建立了RBAC权限管理，就需要进行对权限的WEB管理。这些就需要你自己写代码了。</p> <p>根据不同种类的项目调用下列方法之一定义授权项目：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createRole">CAuthManager::createRole</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createTask">CAuthManager::createTask</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createOperation">CAuthManager::createOperation</a> </li></ul> <p>一旦我们拥有一套授权项目，我们可以调用以下方法建立授权项目关系：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#addItemChild">CAuthManager::addItemChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#removeItemChild">CAuthManager::removeItemChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthItem#addChild">CAuthItem::addChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthItem#removeChild">CAuthItem::removeChild</a> </li></ul> <p>最后，我们调用下列方法来分配角色项目给各个用户：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#assign">CAuthManager::assign</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#revoke">CAuthManager::revoke</a> </li></ul> <p>下面我们将展示一个例子是关于用所提供的API建立一个授权等级：</p> <blockquote> <pre>$auth=Yii::app()-&gt;authManager;  <br />$auth-&gt;createOperation('createPost','create a post'); <br />$auth-&gt;createOperation('readPost','read a post'); <br />$auth-&gt;createOperation('updatePost','update a post'); <br />$auth-&gt;createOperation('deletePost','delete a post');  <br /><br />$bizRule='return Yii::app()-&gt;user-&gt;id==$params["post"]-&gt;authID;'; <br />$task=$auth-&gt;createTask('updateOwnPost','update a post by author himself',$bizRule); <br />$task-&gt;addChild('updatePost');  <br /><br />$role=$auth-&gt;createRole('reader'); <br />$role-&gt;addChild('readPost');  <br /><br />$role=$auth-&gt;createRole('author'); <br />$role-&gt;addChild('reader'); <br />$role-&gt;addChild('createPost'); <br />$role-&gt;addChild('updateOwnPost'); <br /><br />$role=$auth-&gt;createRole('editor'); <br />$role-&gt;addChild('reader'); <br />$role-&gt;addChild('updatePost');  <br /><br />$role=$auth-&gt;createRole('admin'); <br />$role-&gt;addChild('editor'); <br />$role-&gt;addChild('author');<br />$role-&gt;addChild('deletePost');  <br /><br />$auth-&gt;assign('reader','readerA'); <br />$auth-&gt;assign('author','authorB'); <br />$auth-&gt;assign('editor','editorC'); <br />$auth-&gt;assign('admin','adminD');</pre> </blockquote> <pre>也就是说，你需要自己写一个管理界面，来列出你的角色、任务、行动，然后可以在这个界面上进行管理。比如增加、删除、修改。</pre> <h2><a name="t10"></a>权限检查</h2> <p>假设你在你的管理界面进行了赋权，那么可以在程序里面进行权限检查：</p> <pre>if(  Yii::app()-&gt;user-&gt;checkAccess('createPost')  )</pre> <pre>{</pre> <blockquote> <pre>// 这里可以显示表单等操作</pre> </blockquote> <pre>} else　{</pre> <blockquote> <pre>// 检查没有通过的可以跳转或者显示警告</pre> </blockquote> <pre>}</pre> <pre>上面的代码就检查了用户是否可以执行&#8220;createPost&#8221;，这createPost可能是一个任务，也可以是一个行动。</pre> <h2><a name="t11"></a>其他的</h2> <p>对于很多说Yii权限体系RBAC不好用的人其实都没有看懂文档。综合我的体验，我感觉Yii框架的RBAC是我用过的框架里面最好用的。而且是需要自己写代码最少的。</p> <p>Yii的RBAC有更加高级的用法，比如&#8220;业务规则&#8221;，&#8220;默认角色&#8221;。你可以去参考官方文档。</p> <p>我知道，会有部分人仍旧不理解RBAC，或者不会用Yii的RBAC。没有关系，你可以在下方的评论框里提问。</p> <p>happy Yii ！</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-15 19:38 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 信号详解</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/13/197232.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 13 Jan 2013 04:31:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/13/197232.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197232.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/13/197232.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197232.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197232.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 信号的种类 可靠信号与不可靠信号, 实时信号与非实时信号 可靠信号就是实时信号, 那些从UNIX系统继承过来的信号都是非可靠信号, 表现在信号 不支持排队,信号可能会丢失, 比如发送多次相同的信号, 进程只能收到一次. 信号值小于 SIGRTMIN的都是非可靠信号. 非可靠信号就是非实时信号, 后来, Linux改进了信号机制, 增加了32种新的信号, 这些信 号都是可靠信号, 表现在信号支持...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2013/01/13/197232.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-13 12:31 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/13/197232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>centos 上安装gearman</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 07 Jan 2013 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197076.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197076.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197076.html</trackback:ping><description><![CDATA[<div><div>官网：http://gearman.org/</div><br />跨多种环境部署 Gearman<br /> http://www.ibm.com/developerworks/cn/opensource/os-gearman/index.html<br /> 利用开源的Gearman框架构建分布式图片处理平台－张宴<br /> http://blog.s135.com/dips/<br /> 监控：<br /> https://github.com/yugene/Gearman-Monitor <br /> <br /> 一、简介<br /> Gearman是一个分发任务的程序架构，由三部分组成：<br /> Gearman client：提供gearman client API给应用程序调用。API可以使用C,PHP,PERL,MYSQL UDF等待呢个语言，它是请求的发起者。<br /> Gearman job server：将客户端的请求分发到各个gearman worker的调度者，相当于中央控制器，但它不处理具体业务逻辑。<br /> Gearman worker：提供gearman worker API给应用程序调用，具体负责客户端的请求，并将处理结果返回给客户端。<br /> Mogilefs的分布式文件系统的核心就是用gearman实现的。<br /> 这个软件的应用场景很多，比如视频网站的视频处理，分布式日志处理，电子邮件处理，文件同步处理，图片处理等等，只要是可以放开，不影响体验和响应的场 景，需要并行进行大量计算和处理的程序都是可以的。Yahoo在60或更多的服务器上使用gearman每天处理600万个作业。新闻聚合器digg构建 了一个相同规模的gearman网络，每天可处理400000个作业。<br /> Gearman不但可以做为任务分发，还可以做为应用方面的负载均衡。可以让worker放在不同的一堆服务器上，也可以启动放在同一个cpu的多个核 上。比如，应用视频转换程序，不希望web服务器来处理视频格式转换，这时，可以在这一堆服务器上进行任务分发，在上面加载worker处理视频格式，对 外的web服务器就不会被视频转换过程影响。而且扩展方便，加一台服务器到任务调度中心，注册成worker即可，这时job  server会在请求到来的时候，将请求发送给空闲的worker。还可以运行多个job server，组成ha架构，如果一个job  server当掉了，client和worker会自动迁移到另一台job server上。<br /> <br /> 二、安装<br /> [Job Server (gearmand) -- 172.16.1.183]<br /> 1.首先安装libdrizzle<br /> &nbsp;&nbsp;&nbsp; #yum install libdrizzle libdrizzle-devel<br /> 2.安装gearman（两种方法1.yum2.源码包）。（c版的server）<br /> &nbsp;&nbsp;&nbsp; 1）yum安装<br /> &nbsp;&nbsp;&nbsp; #rpm -ivh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm<br /> &nbsp;&nbsp;&nbsp; #yum install -y gearmand<br /> &nbsp;&nbsp;&nbsp; 2）源码包安装<br /> &nbsp;&nbsp;&nbsp; #cd /opt/build/<br /> &nbsp;&nbsp;&nbsp; #wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz<br /> &nbsp;&nbsp;&nbsp; #tar zxf gearmand-0.34.tar.gz<br /> &nbsp;&nbsp;&nbsp; #cd gearmand-0.34<br /> &nbsp;&nbsp;&nbsp; #./configure<br /> &nbsp;&nbsp;&nbsp; #make &amp;&amp; make install<br /> 3.启动gearman服务<br /> &nbsp;&nbsp;&nbsp; 1）yum安装方式<br /> &nbsp;&nbsp;&nbsp; #/etc/init.d/gearmand start<br /> &nbsp;&nbsp;&nbsp; 2）源码包安装方式<br /> &nbsp;&nbsp;&nbsp; #/opt/build/gearmand-0.34/sbin/gearmand -d<br /> <br /> &nbsp;&nbsp;&nbsp; #gearmand -vvv -u root <br /> &nbsp;&nbsp;&nbsp; INFO Starting up<br /> &nbsp;&nbsp;&nbsp; INFO Listening on :::4730 (6)<br /> &nbsp;&nbsp;&nbsp; INFO Creating wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Creating IO thread wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Adding event for listening socket (6)<br /> &nbsp;&nbsp;&nbsp; INFO Adding event for wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Entering main event loop<br /> <br /> worker&amp;&amp;client以php方式<br /> [worker --&nbsp; 172.16.1.180]<br /> 安装gearmand如上所示<br /> <br /> 安装 Gearman PHP extension<br /> 1.下载gearman-0.8.0.tgz并安装<br /> &nbsp;&nbsp;&nbsp; #cd /opt/build/<br /> &nbsp;&nbsp;&nbsp; #wget http://pecl.php.net/get/gearman-0.8.0.tgz<br /> &nbsp;&nbsp;&nbsp; # yum install -y libgearman-devel.x86_64<br /> &nbsp;&nbsp;&nbsp; # yum install -y re2c <br /> &nbsp;&nbsp;&nbsp; #tar zxf gearman-0.8.0.tgz <br /> &nbsp;&nbsp;&nbsp; #cd gearman-0.8.0.tgz<br /> &nbsp;&nbsp;&nbsp; #phpize<br /> &nbsp;&nbsp;&nbsp; # ./configure<br /> &nbsp;&nbsp;&nbsp; # make &amp;&amp; make install<br /> 2.编辑php.ini配置文件加载相应模块并使之生效<br /> &nbsp;&nbsp;&nbsp; # vim /etc/php.ini<br /> &nbsp;&nbsp;&nbsp; extension = "gearman.so"<br /> 3.查看gearman.so模块是否加载<br /> &nbsp;&nbsp;&nbsp; # php --info | grep gearman<br /> &nbsp;&nbsp;&nbsp; gearman<br /> &nbsp;&nbsp;&nbsp; gearman support =&gt; enabled<br /> &nbsp;&nbsp;&nbsp; libgearman version =&gt; 0.14<br /> &nbsp;&nbsp;&nbsp; PWD =&gt; /opt/build/gearman-0.8.0<br /> &nbsp;&nbsp;&nbsp; _SERVER["PWD"] =&gt; /opt/build/gearman-0.8.0<br /> &nbsp;&nbsp;&nbsp; # php -m | grep gearman<br /> &nbsp;&nbsp;&nbsp; gearman<br /> 4.启动job<br /> gearmand -d<br /> 如果当前用户是 root 的话，则需要这样操作：<br /> gearmand -d -u root<br /> 缺省会使用 4730 端口，下面会用到。<br /> &nbsp;&nbsp;&nbsp; 注意：如果找不到 gearmand 命令的路径，别忘了用 whereis gearmand 确认<br /> <br /> [client -- 172.16.1.181]<br /> &nbsp;&nbsp;&nbsp; 安装如work同。如上所示。<br /> <br /> 三、测试：<br /> [Job Server (gearmand) -- 172.16.1.183]<br /> 启动gearmand<br /> <br /> 以命令行工具来验证gearman的功能<br /> 启动 Worker：gearman -h 172.16.1.183 -w -f wc -- wc -l &amp;<br /> 运行Client：gearman -h 172.16.1.183 -f wc &lt; /etc/passwd<br /> 42<br /> 可以看到验证成功。<br /> <br /> 以php验证gearman的功能<br /> 编写 Worker<br /> worker.php 文件内容如下：<br /> &lt;?php<br /> $worker= new GearmanWorker();<br /> $worker-&gt;addServer('172.16.1.183', 4730);<br /> $worker-&gt;addFunction('reverse', 'my_reverse_function');<br /> while ($worker-&gt;work());<br /> function my_reverse_function($job) {<br /> return strrev($job-&gt;workload());<br /> }<br /> ?&gt;<br /> 设置后台运行 work<br /> php worker.php &amp;<br /> 编写 Client<br /> client.php 文件内容如下：<br /> &lt;?php<br /> $client= new GearmanClient();<br /> $client-&gt;addServer('172.16.1.183', 4730);<br /> echo $client-&gt;do('reverse', 'Hello World!'), "\n";<br /> ?&gt;<br /> 运行 client<br /> php client.php<br /> 输出：!dlroW olleH<br /><br />Q:<br /><div><div itemprop="description">         <p>I've been trying to get Gearman compiled on CentOS 5.8 all  afternoon. Unfortunately I am restricted to this version of CentOS by my  CTO and how he has our entire network configured. I think it's simply  because we don't have enough resources to upgrade our network... But  anyways, the problem at hand.</p>  <p>I have searched through Server Fault, Stack Overflow, Google, and am  unable to locate a working solution. What I have below is stuff I have  pieced together from my searching.</p>  <p>Searches have told said to install the following via <code>yum</code>:</p>  <pre><code>yum -y install --enablerepo=remi boost141-devel libgearman-devel e2fsprogs-devel e2fsprogs gcc44 gcc-c++ </code></pre>  <p>To get the Boost headers working correctly I did this:</p>  <pre>cp -f /usr/lib/boost141/* /usr/lib/ cp -f /usr/lib64/boost141/* /usr/lib64/ rm -f /usr/include/boost ln -s /usr/include/boost141/boost /usr/include/boost </pre>  <p>With all of the dependancies installed and paths setup I then download and compile <code>gearmand-1.1.2</code> just fine.</p>  <pre>wget -O /tmp/gearmand-1.1.2.tar.gz https://launchpad.net/gearmand/1.2/1.1.2/+download/gearmand-1.1.2.tar.gz cd /tmp &amp;&amp; tar zxvf gearmand-1.1.2.tar.gz ./configure &amp;&amp; make -j8 &amp;&amp; make install </pre>  <p>That works correctly. So now I need to install the Gearman library  for PHP. I have attempted through PECL and downloading the source  directly, both result in the same error:</p>  <pre>checking whether to enable gearman support... yes, shared not found configure: error: Please install libgearman </pre>  <p>What I don't understand is I installed the <code>libgearman-devel</code> package which also installed the core <code>libgearman</code>. The installation installs <code>libgearman-devel-0.14-3.el5.x86_64</code>, <code>libgearman-devel-0.14-3.el5.i386</code>, <code>libgearman-0.14-3.el5.x86_64</code>, and <code>libgearman-0.14-3.el5.i386</code>.</p>  <p>Is it possible the package version is lower than what is required?  I'm still poking around with this, but figured I'd throw this up to see  if anyone has a solution while I continue to research a fix.</p>  <p>Thanks!</p>      </div></div><br />A:<br /><div><div><p>This should do the trick:</p>  <pre><code>export GEARMAN_LIB_DIR=/usr/include/libgearman <br />export GEARMAN_INC_DIR=/usr/include/libgearman </code></pre>  <p>That should work, if not you'll have to do some minor edits to config.m4.</p><p><br /></p><p>other:</p><p><div>http://gearman.org/gearman_php_extension</div><div>http://blog.csdn.net/aidenliu/article/details/7406390</div><div>http://www.php.net/manual/en/gearmanclient.dobackground.php</div><div>http://www.wenzizone.com/2012/09/27/how_to_fix_rpm_filedigests_payloadisxz_is_needed.html</div><div>http://www.2cto.com/os/201206/136785.html</div><div>http://blog.s135.com/dips</div><div>http://blog.csdn.net/hfahe/article/details/5519582</div><div>http://hi.baidu.com/sunjiujiu/item/4406281c952cf47a7b5f2594</div><br /></p> </div></div><div></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-07 16:39 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用awstats自动分析Nginx日志(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/06/197024.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 06 Jan 2013 10:05:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/06/197024.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197024.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/06/197024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197024.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197024.html</trackback:ping><description><![CDATA[<div>转自: https://www.akii.org/use-awstats-automatic-analysis-nginx-log.html<br />使用awstats可以分析apache日志，同样也可以分析nginx日志。本文将详细介绍自动定时切割nginx的访问日志，并使用awstats来定时分析nginx的日志的实现方法。</div><div><h2><strong>前言</strong></h2> <p>本文中使用的是awstats 7.0版本。<br /> 此版本增加了对win7的支持以及一些更新的特性。</p> <blockquote><p>New features/improvements:<br /> - Detect Windows 7.<br /> - Can format numbers according to language.<br /> - More mime types.<br /> - Added geoip_asn_maxmind plugin.<br /> - Geoip Maxmind city plugin have now override file capabilities to complete<br /> missing entries in geoip maxmind database.<br /> - Added graphgooglechartapi to use online Google chart api to build graph.<br /> - Can show map of country to report countries when using graphgooglechartapi.<br /> - Part of codes was change to use more functions and have a cleaner code.<br /> - Added parameter to ignore missing log files when merging for a site on<br /> multiple servers where a single server may not have created a log for a given day.<br /> - Update robots database.<br /> - Added Download tracking where certain mime types are defined as downloads<br /> and HTTP status 206 is tracked as download continuation</p></blockquote> <p>Awstats 是在 SourceForge 上发展很快的一个基于 Perl 的 WEB 日志分析工具，一个充分的日志分析让  Awstats 显示您下列资料:</p> <ul><li> 访问次数、独特访客人数,</li><li> 访问时间和上次访问,</li><li> 使用者认证、最近认证的访问,</li><li> 每周的高峰时间(页数,点击率,每小时和一周的千字节),</li><li> 域名/国家的主机访客(页数,点击率,字节,269域名/国家检测, geoip 检测),</li><li> 主机名单,最近访问和未解析的 IP 地址名单</li><li> 大多数看过的进出页面,</li><li> 档案类型,</li><li> 网站压缩统计表(mod_gzip 或者 mod_deflate),</li><li> 使用的操作系统 (每个操作系统的页数,点击率 ,字节, 35 OS detected),</li><li> 使用的浏览器,</li><li> 机器人访问(检测 319 个机器人),</li><li> 蠕虫攻击 (5 个蠕虫家族),</li><li> 搜索引擎，利用关键词检索找到你的地址,</li><li> HTTP 协议错误(最近查阅没有找到的页面),</li><li> 其他基于 URL 的个性报导,链接参数, 涉及综合行销领域目的.</li><li> 贵网站被加入&#8221;最喜爱的书签&#8221;.次数.</li><li> 屏幕大小(需要在索引页补充一些 HTML 标签).</li><li> 浏览器的支持比例:  Java, Flash, RealG2 reader, Quicktime reader, WMA reader, PDF  reader.</li><li> 负载平衡服务器比率集群报告.</li></ul> <p>Awstats 的运行是需要 PERL 环境的支持，从 awstats 的文档来看，它对 Apache HTTP Server   的支持是非常完美的，而当我们把 Web 服务器换成 Nginx 后，要运行 awstats 变得很麻烦。首先 Nginx 本身对 Perl   的支持是比较弱的，甚至官方也不建议使用；另外在日志格式上有需要修改后才能运行。</p> <h2><strong>日志切割</strong></h2> <p>本文主要介绍通过让 awstats 对日志统计的结果生成静态页面，然后通过 Nginx 输出以达到统计 Nginx  访问日志的效果，其中还包括如何让 Nginx 自动切割日志文件。对于nginx的日志，我的做法是按天切割。然后存入日期形式的目录中并压缩。</p> <p>需要注意的是，nginx的日志应该遵循以下格式，才可以被awstats识别，如定义日志格式</p> <div><div id="highlighter_888201"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">log_format&nbsp; main&nbsp; </code><code string"="">'$remote_addr - $remote_user [$time_local] "$request" '</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code string"="">'$status $body_bytes_sent "$http_referer" '</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code string"="">'"$http_user_agent" "$http_x_forwarded_for"'</code><code plain"="">;</code></div></div></td></tr></tbody></table></div></div> <p>使用日志格式</p> <div><div id="highlighter_628218"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">access_log&nbsp; </code><code plain"="">/home/www/logs/access</code><code plain"="">.log&nbsp; main;</code></div></div></td></tr></tbody></table></div></div> <p>这里需要有一个小技巧的提示：把log_format这段代码放在你nginx的http的定义段中，可以在下面的每一个server中引用此格式。不必在每个server里面都去定义格式。<br /> 本文不讲如何安装nginx，稍后我将发布我的lnmp一键安装包(linux nginx mysql php)。全编译+优化自动化安装，使用php-fpm运行php的fastcgi进程。</p> <p>我写了一个定时切割日志的脚本。每天0:00开始执行，切割昨天的日志（交由awstats分析），压缩前天的日志（压缩日志可减小存储空间，为防 止awstats没有分析完就被压缩，所以只压缩前天的日志）。如果你的nginx和log文件放的路径和我的不一样，请对应修改。</p> <div><div id="highlighter_666635"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">vim cut_log.sh</code></div></div></td></tr></tbody></table></div></div> <p>输入以下内容</p> <div><div id="highlighter_698905"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div></td><td><div><div number1="" index0=""  alt2"=""><code preprocessor=""  bold"="">#!/bin/bash</code></div><div number2="" index1=""  alt1"=""><code comments"=""># This script run at 00:00</code></div><div number3="" index2=""  alt2"=""><code comments"=""># cut yesterday log and gzip the day before yesterday log files.</code></div><div number4="" index3=""  alt1"=""><code comments"=""># yesterday logs to awstats</code></div><div number5="" index4=""  alt2"="">&nbsp;</div><div number6="" index5=""  alt1"=""><code comments"=""># The Nginx logs path</code></div><div number7="" index6=""  alt2"=""><code plain"="">logs_path=</code><code string"="">"/home/www/logs/"</code></div><div number8="" index7=""  alt1"=""><code plain"="">date_dir=${logs_path}$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"yesterday"</code> <code plain"="">+</code><code string"="">"%Y"</code><code plain"="">)/$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"yesterday"</code> <code plain"="">+</code><code string"="">"%m"</code><code plain"="">)/$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"yesterday"</code> <code plain"="">+</code><code string"="">"%d"</code><code plain"="">)/</code></div><div number9="" index8=""  alt2"=""><code plain"="">gzip_date_dir=${logs_path}$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"-2 day"</code> <code plain"="">+</code><code string"="">"%Y"</code><code plain"="">)/$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"-2 day"</code> <code plain"="">+</code><code string"="">"%m"</code><code plain"="">)/$(</code><code functions"="">date</code> <code plain"="">-d </code><code string"="">"-2 day"</code> <code plain"="">+</code><code string"="">"%d"</code><code plain"="">)/</code></div><div number10="" index9=""  alt1"="">&nbsp;</div><div number11="" index10=""  alt2"=""><code functions"="">mkdir</code> <code plain"="">-p $date_dir</code></div><div number12="" index11=""  alt1"=""><code functions"="">mv</code> <code plain"="">${logs_path}*access.log $date_dir</code></div><div number13="" index12=""  alt2"=""><code plain"="">/usr/local/nginx/sbin/nginx</code> <code plain"="">-s reopen</code></div><div number14="" index13=""  alt1"=""><code plain"="">/usr/bin/gzip</code> <code plain"="">${gzip_date_dir}*.log</code></div></div></td></tr></tbody></table></div></div> <p>然后让它每天0时起开始进行，执行crontab -e加入以下代码再按:wq保存退出，这里我将此脚本放在/root/下，切记要给它可执行权限（chmod +x cut_log.sh）.</p> <div><div id="highlighter_56696"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">00 00 * * * </code><code plain"="">/bin/bash</code> <code plain"="">/root/cut_log</code><code plain"="">.sh</code></div></div></td></tr></tbody></table></div></div> <p>这样就可以每天凌里自动切割昨天的日志到以日期为目录结构的目录中。可以留存以后查询。留着昨天的日志交给下面的awstats来分析，压缩前天的日志（前天的已经被分析过了）。</p> <h2><strong>安装和配置awstats</strong></h2> <p>下载最新的 awstats，我使用的是迄今为止最新的7.0版本</p> <p>安装到/usr/local下，这个路径是习惯。大部分人保持的良好习惯。</p> <div><div id="highlighter_444650"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">wget http:</code><code plain"="">//awstats</code><code plain"="">.sourceforge.net</code><code plain"="">/files/awstats-7</code><code plain"="">.0.</code><code functions"="">tar</code><code plain"="">.gz</code></div><div number2="" index1=""  alt1"=""><code functions"="">tar</code> <code plain"="">-zxvf awstats-7.0.</code><code functions"="">tar</code><code plain"="">.gz</code></div><div number3="" index2=""  alt2"=""><code functions"="">mv</code> <code plain"="">awstats-7.0 </code><code plain"="">/usr/local/awstats</code></div></div></td></tr></tbody></table></div></div> <p>修改权限，wget下载下来的包中权限是非root的，赋予过权限之后，.pl的文件也就可以运行了。</p> <div><div id="highlighter_780887"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">chown</code> <code plain"="">-R root:root </code><code plain"="">/usr/local/awstats</code></div><div number2="" index1=""  alt1"=""><code functions"="">chmod</code> <code plain"="">-R =rwX </code><code plain"="">/usr/local/awstats</code></div><div number3="" index2=""  alt2"=""><code functions"="">chmod</code> <code plain"="">+x </code><code plain"="">/usr/local/awstats/tools/</code><code plain"="">*.pl</code></div><div number4="" index3=""  alt1"=""><code functions"="">chmod</code> <code plain"="">+x </code><code plain"="">/usr/local/awstats/wwwroot/cgi-bin/</code><code plain"="">*.pl</code></div></div></td></tr></tbody></table></div></div> <p>然后执行 tools 目录中的 awstats_configure.pl 配置向导，创建一个新的统计</p> <p>运行(注意这里要在当前目录运行。否则会有一些关于标准目录的提示。)</p> <div><div id="highlighter_545974"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">cd</code> <code plain"="">/usr/local/awstats/tools</code></div><div number2="" index1=""  alt1"=""><code plain"="">.</code><code plain"="">/awstats_configure</code><code plain"="">.pl</code></div></div></td></tr></tbody></table></div></div> <p>将会有如下一些提示：</p> <div><div id="highlighter_691818"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">-----&gt; Running OS detected: Linux, BSD or Unix</code></div><div number2="" index1=""  alt1"="">&nbsp;</div><div number3="" index2=""  alt2"=""><code plain"="">-----&gt; Check </code><code keyword"="">for</code> <code plain"="">web server </code><code functions"="">install</code></div><div number4="" index3=""  alt1"="">&nbsp;</div><div number5="" index4=""  alt2"=""><code plain"="">Enter full config </code><code functions"="">file</code> <code plain"="">path of your Web server.</code></div><div number6="" index5=""  alt1"=""><code plain"="">Example: </code><code plain"="">/etc/httpd/httpd</code><code plain"="">.conf</code></div><div number7="" index6=""  alt2"=""><code plain"="">Example: </code><code plain"="">/usr/local/apache2/conf/httpd</code><code plain"="">.conf</code></div><div number8="" index7=""  alt1"=""><code plain"="">Example: c:\Program files\apache group\apache\conf\httpd.conf</code></div><div number9="" index8=""  alt2"=""><code plain"="">Config </code><code functions"="">file</code> <code plain"="">path (</code><code string"="">'none'</code> <code plain"="">to skip web server setup):</code></div><div number10="" index9=""  alt1"=""><code plain"="">&gt;none </code><code comments"="">#这里添none并回车，因为我们没有使用apache</code></div></div></td></tr></tbody></table></div></div> <p>回车之后下一个选项</p> <div><div id="highlighter_8026"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">Your web server config </code><code functions"="">file</code><code plain"="">(s) could not be found.</code></div><div number2="" index1=""  alt1"=""><code plain"="">You will need to setup your web server manually to </code><code functions"="">declare</code> <code plain"="">AWStats</code></div><div number3="" index2=""  alt2"=""><code plain"="">script as a CGI, </code><code keyword"="">if</code> <code plain"="">you want to build reports dynamically.</code></div><div number4="" index3=""  alt1"=""><code plain"="">See AWStats setup documentation (</code><code functions"="">file</code> <code plain"="">docs</code><code plain"="">/index</code><code plain"="">.html)</code></div><div number5="" index4=""  alt2"="">&nbsp;</div><div number6="" index5=""  alt1"=""><code plain"="">-----&gt; Update model config </code><code functions"="">file</code> <code string"="">'/usr/local/awstats/wwwroot/cgi-bin/awstats.model.conf'</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;</code><code plain"="">File awstats.model.conf updated.</code></div><div number8="" index7=""  alt1"="">&nbsp;</div><div number9="" index8=""  alt2"=""><code plain"="">-----&gt; Need to create a new config </code><code functions"="">file</code> <code plain"="">?</code></div><div number10="" index9=""  alt1"=""><code plain"="">Do you want me to build a new AWStats config</code><code plain"="">/profile</code></div><div number11="" index10=""  alt2"=""><code functions"="">file</code> <code plain"="">(required </code><code keyword"="">if</code> <code plain"="">first </code><code functions"="">install</code><code plain"="">) [y</code><code plain"="">/N</code><code plain"="">] ?</code></div></div></td></tr></tbody></table></div></div> <p>#这里选Y，创建一个新的配置文件</p> <div><div id="highlighter_583825"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">-----&gt; Define config </code><code functions"="">file</code> <code plain"="">name to create</code></div><div number2="" index1=""  alt1"=""><code plain"="">What is the name of your web site or profile analysis ?</code></div><div number3="" index2=""  alt2"=""><code plain"="">Example: www.mysite.com</code></div><div number4="" index3=""  alt1"=""><code plain"="">Example: demo</code></div><div number5="" index4=""  alt2"=""><code plain"="">Your web site, virtual server or profile name:</code></div><div number6="" index5=""  alt1"=""><code plain"="">&gt;akii.org&nbsp; </code><code comments"="">#这里输入你要分析的域名，或是随便一个你易记的配置名并回车</code></div></div></td></tr></tbody></table></div></div> <p>接下来要定义你的配置文件存放的路径，可用默认</p> <div><div id="highlighter_293190"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">-----&gt; Define config </code><code functions"="">file</code> <code plain"="">path</code></div><div number2="" index1=""  alt1"=""><code plain"="">In </code><code functions"="">which</code> <code plain"="">directory </code><code keyword"="">do</code> <code plain"="">you plan to store your config </code><code functions"="">file</code><code plain"="">(s) ?</code></div><div number3="" index2=""  alt2"=""><code plain"="">Default: </code><code plain"="">/etc/awstats</code></div><div number4="" index3=""  alt1"=""><code plain"="">Directory path to store config </code><code functions"="">file</code><code plain"="">(s) (Enter </code><code keyword"="">for</code> <code plain"="">default):</code></div><div number5="" index4=""  alt2"=""><code plain"="">&gt; </code><code comments"="">#直接回车，使用默认路径/etc/awstats</code></div></div></td></tr></tbody></table></div></div> <p>回车后的提示</p> <div><div id="highlighter_413648"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">-----&gt; Create config </code><code functions"="">file</code> <code string"="">'/etc/awstats/awstats.akii.org.conf'</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;</code><code plain"="">Config </code><code functions"="">file</code> <code plain"="">/etc/awstats/awstats</code><code plain"="">.akii.org.conf created.</code></div><div number3="" index2=""  alt2"="">&nbsp;</div><div number4="" index3=""  alt1"=""><code plain"="">-----&gt; Add update process inside a scheduler</code></div><div number5="" index4=""  alt2"=""><code plain"="">Sorry, configure.pl does not support automatic add to </code><code functions"="">cron</code> <code plain"="">yet.</code></div><div number6="" index5=""  alt1"=""><code plain"="">You can </code><code keyword"="">do</code> <code plain"="">it manually by adding the following </code><code functions"="">command</code> <code plain"="">to your </code><code functions"="">cron</code><code plain"="">:</code></div><div number7="" index6=""  alt2"=""><code plain"="">/usr/local/awstats/wwwroot/cgi-bin/awstats</code><code plain"="">.pl -update -config=akii.org</code></div><div number8="" index7=""  alt1"=""><code plain"="">Or </code><code keyword"="">if</code> <code plain"="">you have several config files and prefer having only one </code><code functions"="">command</code><code plain"="">:</code></div><div number9="" index8=""  alt2"=""><code plain"="">/usr/local/awstats/tools/awstats_updateall</code><code plain"="">.pl now</code></div><div number10="" index9=""  alt1"=""><code plain"="">Press ENTER to </code><code keyword"="">continue</code><code plain"="">... </code><code comments"="">#按回车继续</code></div><div number11="" index10=""  alt2"="">&nbsp;</div><div number12="" index11=""  alt1"=""><code plain"="">A SIMPLE config </code><code functions"="">file</code> <code plain"="">has been created: </code><code plain"="">/etc/awstats/awstats</code><code plain"="">.akii.org.conf</code></div><div number13="" index12=""  alt2"=""><code plain"="">You should have a </code><code functions"="">look</code> <code plain"="">inside to check and change manually main parameters.</code></div><div number14="" index13=""  alt1"=""><code plain"="">You can </code><code keyword"="">then</code> <code plain"="">manually update your statistics </code><code keyword"="">for</code> <code string"="">'yuyuanchun.com'</code> <code plain"="">with </code><code functions"="">command</code><code plain"="">:</code></div><div number15="" index14=""  alt2"=""><code plain"="">&gt; perl awstats.pl -update -config=akii.org</code></div><div number16="" index15=""  alt1"=""><code plain"="">You can also build static report pages </code><code keyword"="">for</code> <code string"="">'akii.org'</code> <code plain"="">with </code><code functions"="">command</code><code plain"="">:</code></div><div number17="" index16=""  alt2"=""><code plain"="">&gt; perl awstats.pl -output=pagetype -config=akii.org</code></div><div number18="" index17=""  alt1"="">&nbsp;</div><div number19="" index18=""  alt2"=""><code plain"="">Press ENTER to finish... </code><code comments"="">#回车完成配置文件的创建</code></div></div></td></tr></tbody></table></div></div> <p>完成配置文件的创建后，我们还要修改一下。因为我们是按天切割的日志，切割完成后交由awstats去分析。并不是让awstats去分时正在时时 增长的也就是正在被写入的日志，这样的好处是不至于遗漏数据，并且分析已经切割完成的日志，更不用担心会有冲突。坏处是我一天切割一次日志，你要等第二天 才能看昨天的一些详细数据。</p> <p>修改/etc/awstats/awstats.akii.org.conf，执行：</p> <div><div id="highlighter_810222"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">vi</code> <code plain"="">/etc/awstats/awstats</code><code plain"="">.akii.org.conf</code></div></div></td></tr></tbody></table></div></div> <p>找到</p> <div><div id="highlighter_683035"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">LogFile=</code><code string"="">"/var/log/httpd/mylog.log"</code></div></div></td></tr></tbody></table></div></div> <p>修改为：</p> <div><div id="highlighter_673331"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">LogFile=</code><code string"="">"/home/www/logs/%YYYY-24/%MM-24/%DD-24/akii.org_access.log"</code></div></div></td></tr></tbody></table></div></div> <p>如果你的日志路径和我的不一样，请修改成对应的日志文件名。以上的完整路径是切割后保存的nginx日志文件。其中%YYYY-24/%MM-24/%DD-24表示年月日都减去24小时，也就是昨天的日志目录。修改完成后按:wq保存退出。</p> <p>接下来可以测试一下awstats分析日志了（前提是你已经有了切割过的日志，没有的话可以先退行一下切割日志的脚本/root/cut_log.sh）</p> <p>首先，还要创建一个awstats用于记录数据的目录</p> <div><div id="highlighter_653449"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">mkdir</code> <code plain"="">-p </code><code plain"="">/var/lib/awstats</code></div></div></td></tr></tbody></table></div></div> <p>然后运行awstats的wwwroot目录中的awatsts.pl来测试一下</p> <div><div id="highlighter_211542"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">/usr/local/awstats/wwwroot/cgi-bin/awstats</code><code plain"="">.pl -update -config=akii.org</code></div></div></td></tr></tbody></table></div></div> <p>你如果看到类似下面的提示就说明配置文件都正确了。</p> <div><div id="highlighter_50440"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">Create</code><code plain"="">/Update</code> <code plain"="">database </code><code keyword"="">for</code> <code plain"="">config </code><code string"="">"/etc/awstats/awstats.akii.org.conf"</code> <code plain"="">by AWStats version 7.0 (build 1.964)</code></div><div number2="" index1=""  alt1"=""><code plain"="">From data </code><code keyword"="">in</code> <code plain"="">log </code><code functions"="">file</code> <code string"="">"/home/www/logs/2010/07/24/akii.org_access.log"</code><code plain"="">...</code></div><div number3="" index2=""  alt2"=""><code plain"="">Phase 1 : First bypass old records, searching new record...</code></div><div number4="" index3=""  alt1"=""><code plain"="">Direct access after last parsed record (after line 43260)</code></div><div number5="" index4=""  alt2"=""><code plain"="">Jumped lines </code><code keyword"="">in</code> <code functions"="">file</code><code plain"="">: 43260</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;</code><code plain"="">Found 43260 already parsed records.</code></div><div number7="" index6=""  alt2"=""><code plain"="">Parsed lines </code><code keyword"="">in</code> <code functions"="">file</code><code plain"="">: 0</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 dropped records,</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 comments,</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 blank records,</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 corrupted records,</code></div><div number12="" index11=""  alt1"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 old records,</code></div><div number13="" index12=""  alt2"=""><code spaces"="">&nbsp;</code><code plain"="">Found 0 new qualified records</code></div></div></td></tr></tbody></table></div></div> <p>统计分析完成后，结果还在 Awstats 的数据库中。在 Apache 上，可以直接打开 Perl 程序的网页查看统计。  但本文开始时已经提到，Nginx 对 Perl 支持并不好，所以我们要换个方法，利用 awstats   的工具将统计的结果生成静态文件，具体的步骤如下：</p> <ul><li>首先在 webroot 目录下创建一个文件夹。例：/home/www/awstats</li><li>写一个脚本，定期执行让 Awstats 把静态页面生成到该目录中</li></ul> <p>先生成存放awstats生成的静态文件的目录，我这里用的是/home/www/awstats</p> <div><div id="highlighter_170519"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">mkdir</code> <code plain"="">-p </code><code plain"="">/home/www/awstats</code></div></div></td></tr></tbody></table></div></div> <p>我们来写一个脚本</p> <div><div id="highlighter_641756"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">vim </code><code plain"="">/root/awstats</code><code plain"="">.sh</code></div></div></td></tr></tbody></table></div></div> <p>然后输入以下内容</p> <div><div id="highlighter_644924"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div></td><td><div><div number1="" index0=""  alt2"=""><code preprocessor=""  bold"="">#!/bin/bash</code></div><div number2="" index1=""  alt1"=""><code functions"="">mkdir</code> <code plain"="">-p </code><code plain"="">/home/www/awstats/akii</code><code plain"="">.org</code></div><div number3="" index2=""  alt2"=""><code plain"="">/usr/local/awstats/tools/awstats_buildstaticpages</code><code plain"="">.pl -update&nbsp; \</code></div><div number4="" index3=""  alt1"=""><code plain"="">-config=akii.org -lang=cn -</code><code functions"="">dir</code><code plain"="">=</code><code plain"="">/home/www/awstats/akii</code><code plain"="">.org&nbsp; \</code></div><div number5="" index4=""  alt2"=""><code plain"="">-awstatsprog=</code><code plain"="">/usr/local/awstats/wwwroot/cgi-bin/awstats</code><code plain"="">.pl</code></div></div></td></tr></tbody></table></div></div> <p>上述命令的具体意思如下：</p> <ul><li>/usr/local/awstats/tools/awstats_buildstaticpages.pl	Awstats  静态页面生成工具</li><li>-update -config=akii.org			更新配置项</li><li>-lang=cn				语言为中文</li><li>-dir=/home/www/awstats	统计结果输出目录</li><li>-awstatsprog=/usr/local/awstats/wwwroot/cgi-bin/awstats.pl	Awstats  日志更新程序路径。</li></ul> <p>然后在你的nginx的配置文件中，在你想要安置awstats或默认的ip或域名的server段中，加入关于awstats和icon的两个目录配置。</p> <p>如一个完整案例：</p> <div><div id="highlighter_660898"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">server {</code></div><div number2="" index1=""  alt1"=""><code plain"="">listen&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 80;</code></div><div number3="" index2=""  alt2"=""><code plain"="">server_name&nbsp; localhost;</code></div><div number4="" index3=""  alt1"=""><code plain"="">root </code><code plain"="">/home/www</code><code plain"="">;</code></div><div number5="" index4=""  alt2"=""><code plain"="">index index.html;</code></div><div number6="" index5=""  alt1"="">&nbsp;</div><div number7="" index6=""  alt2"=""><code plain"="">location ~ ^</code><code plain"="">/awstats/</code> <code plain"="">{&nbsp;&nbsp;&nbsp;&nbsp; </code><code comments"=""># awstats&nbsp; 静态页面目录</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">root&nbsp;&nbsp; </code><code plain"="">/home/www/awstats</code><code plain"="">;</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">autoindex on; </code><code comments"="">#可以目录浏览你的多个域名的目录用于分析</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">index&nbsp; index.html;</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">access_log off;</code></div><div number12="" index11=""  alt1"=""><code plain"="">}</code></div><div number13="" index12=""  alt2"="">&nbsp;</div><div number14="" index13=""  alt1"=""><code plain"="">location ~ ^</code><code plain"="">/icon/</code> <code plain"="">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code comments"=""># 图标目录</code></div><div number15="" index14=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">root&nbsp;&nbsp; </code><code plain"="">/usr/local/awstats/wwwroot</code><code plain"="">;</code></div><div number16="" index15=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">index&nbsp; index.html;</code></div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">access_log off;</code></div><div number18="" index17=""  alt1"=""><code plain"="">}</code></div><div number19="" index18=""  alt2"=""><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <p>接下来可以测试一下脚本是否可以正确执行</p> <p>还是别忘了给它可执行权限</p> <div><div id="highlighter_826775"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">chmod</code> <code plain"="">+x </code><code plain"="">/root/awstats</code><code plain"="">.sh</code></div><div number2="" index1=""  alt1"=""><code plain"="">/root/awstats</code><code plain"="">.sh</code></div></div></td></tr></tbody></table></div></div> <p>如果你看到它生成了一堆网页，那就说明成功了。</p> <p>输出信息部分例如</p> <div><div id="highlighter_321786"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">Launch update process : </code><code string"="">"/usr/local/awstats/wwwroot/cgi-bin/awstats.pl"</code> <code plain"="">-config=akii.org -update -configdir=</code></div><div number2="" index1=""  alt1"=""><code plain"="">......</code></div><div number3="" index2=""  alt2"=""><code plain"="">Build keywords page: </code><code string"="">"/usr/local/awstats/wwwroot/cgi-bin/awstats.pl"</code> <code plain"="">-config=akii.org -staticlinks -lang=cn -output=keywords</code></div><div number4="" index3=""  alt1"=""><code plain"="">Build errors404 page: </code><code string"="">"/usr/local/awstats/wwwroot/cgi-bin/awstats.pl"</code> <code plain"="">-config=akii.org -staticlinks -lang=cn -output=errors404</code></div><div number5="" index4=""  alt2"=""><code plain"="">20 files built.</code></div><div number6="" index5=""  alt1"=""><code plain"="">Main HTML page is </code><code string"="">'awstats.akii.org.html'</code><code plain"="">.</code></div></div></td></tr></tbody></table></div></div> <p>然后可以把它加入自动运行了。</p> <h2><strong>配置awstats脚本自动运行</strong></h2> <div><div id="highlighter_799610"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">crontab</code> <code plain"="">-e</code></div></div></td></tr></tbody></table></div></div> <p>加入</p> <div><div id="highlighter_408861"  shell"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">00 1 * * * </code><code plain"="">/root/awstats</code><code plain"="">.sh</code></div></div></td></tr></tbody></table></div></div> <p>然后保存退出。</p> <p>这样就可以每天在凌晨自动分割日志，并且开始自动用awstats分析nginx的日志了。</p> <h2><strong>认证访问</strong></h2> <p>如果你想给你的awstats加上访问密码，可以见这里：<a href="https://www.akii.org/nginx-auth_basic-website-dir.html" target="_blank">nginx为目录或网站加上密码认证</a></p> <p>原创文章，写的辛苦。如果你要转载，请保留出处及链接。</p> <p>参考资料:<a href="http://www.ibm.com/developerworks/cn/linux/l-cn-awstats-nginx/index.html" target="_blank">http://www.ibm.com/developerworks/cn/linux/l-cn-awstats-nginx/index.html</a></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-06 18:05 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/06/197024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下编译安装php的参数</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/05/196985.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sat, 05 Jan 2013 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/05/196985.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196985.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/05/196985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196985.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196985.html</trackback:ping><description><![CDATA[<div><div id="cnblogs_post_body"><p>Fast-CGI:<br /> ./configure --prefix=/usr/local/php --enable-fastcgi  --enable-force-cgi-redirect --with-config-file-path=/etc --with-zlib  --with-mysql --with-xml --with-gd --enable-gd-native-ttf  --enable-gd-jis-conv --with-freetype-dir --with-jpeg-dir --with-png-dir  --enable-mbstring</p> <p>PHP4-Server:<br /> ./configure --prefix=/usr/local/php  --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql  --with-config-file-path=/etc --with-gd --enable-gd-native-ttf  --enable-gd-jis-conv --with-freetype-dir --with-jpeg-dir --with-png-dir  --with-zlib --enable-xml --enable-mbstring</p> <p>PHP4-Max:<br /> ./configure --prefix=/usr/local/php  --with-apxs2=/usr/local/apache/bin/apxs --mandir=/usr/share/man  --with-mysql=/usr/local/mysql --with-config-file-path=/usr/local/php/etc  --with-openssl=/usr/local/openssl-0.9.7e --with-gd  --enable-gd-native-ttf --enable-gd-jis-conv --with-freetype-dir  --with-jpeg-dir --with-png-dir --with-zlib --with-bz2 --with-inifile  --with-hyperwave --enable-xml --enable-track-vars --enable-dba  --enable-dbase --enable-filepro --enable-ftp --enable-versioning  --enable-memory-limit --enable-calendar --enable-session  --enable-sockets --enable-sysmsg --enable-sysvsem --enable-sysvshm  --enable-tokenizer --enable-overload --enable-ctype --enable-sigchild  --enable-magic-quotes --enable-roxen-zts --enable-fastcgi --enable-dbx  --enable-dio --enable-shmop --enable-mbstring</p> <p>PHP5-Server:<br /> ./configure --prefix=/usr/local/php  --with-apxs2=/usr/local/apache2/bin/apxs --with-zlib-dir --with-bz2  --with-tiff-dir --with-libxml-dir --with-gd --with-freetype-dir  --with-jpeg-dir --with-png-dir --with-ttf --enable-mbstring  --with-mysql=/usr/lib/mysql --with-config-file-path=/etc --disable-ipv6  --enable-gd-native-ttf</p> <p>PHP5-Standard:<br /> ./configure --prefix=/usr/local/php  --with-apxs2=/usr/local/apache/bin/apxs --mandir=/usr/share/man  --with-openssl=/usr/local/openssl-0.9.7e --with-zlib --with-bz2  --with-tiff-dir --with-libxml-dir --enable-dio --enable-ftp --with-gd  --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib-dir  --with-bz2-dir --with-ttf --enable-mbstring  --with-mysql=/usr/local/mysql --with-config-file-path=/usr/local/php/etc  --disable-ipv6 --enable-gd-native-ttf</p> <p>PHP5-Max:<br /> ./configure --prefix=/usr/local/php  --with-apxs2=/usr/local/apache/bin/apxs --mandir=/usr/share/man  --with-openssl=/usr/local/openssl-0.9.7e --with-zlib --with-bz2  --with-tiff-dir --with-libxml-dir --enable-dio --enable-ftp --with-gd  --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib-dir  --with-bz2-dir --with-ttf --with-inifile --enable-dba --enable-dbase  --enable-filepro --enable-versioning --enable-memory-limit  --enable-calendar --enable-sockets --enable-sysvsem --enable-sigchild  --enable-magic-quotes --enable-roxen-zts --enable-fastcgi --enable-dbx  --enable-shmop --enable-mbstring --with-mysql=/usr/local/mysql  --with-config-file-path=/usr/local/php/etc --disable-ipv6  --enable-gd-native-ttf</p>  </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-05 17:37 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/05/196985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mint 下codeblocks 编译libapue </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/04/196955.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 04 Jan 2013 12:23:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/04/196955.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196955.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/04/196955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196955.html</trackback:ping><description><![CDATA[codeblocks很轻巧也很好用对于c/c++编写在linux下相对于eclipse.<br />于是乎下了一个，由于是乎想写几个sample玩玩。于是乎拿&lt;unix 高级环境编程&gt; sample来测试。<br /><br />于是乎建了一个c++ project. <div>&lt;unix 高级环境编程&gt;里的例子有个apue.h头文件。不是系统自带的。是作者自己写的几个util函数。<br />网上找编译apue.h头文件一大片。但是都是考来考去，不过核心的都差不多。不过有个方法是编译完<br />libapue.a静态库后，还需要在apute.h头文件尾巴加"error.c"。。完了拷贝error.c实现到目录。。<br />看完后。我惊了呆。。好吧。。这库还能这么用。。<br /><br />既然libapue.a编译完后，apue.h里的函数声明在libapue.a都已经实现，当然包括err_xxx系列的。所以<br />在apue.h加"error.c"是画蛇添足。。这里不推荐此方法。。<br /><br />我的环境是mint14下, IDE用的是 codeblocks. 方法中基本都有这么一个步骤：<br /><div> <div>先在这个网站&nbsp;http://www.apuebook.com/src.tar.gz  下载tar.gz格式的源码包，然后解压至某个目录，比如说/home/xiaoguozi/下，然后进入目录apue.2e，把文件  Make.defines.linux 中的 WKDIR=/home/xxx/apue.2e 修改为  WKDIR=/home/xiaoguozi/apue.2e  ，然后再进入apue.2e目录下的std目录，打开linux.mk，将里面的nawk全部替换为awk</div></div>如果用vim编辑的话，可以用 :1,%s/nawk/awk/g 替换字符窜<br /><br />完了make, 过程中，还遇到了几个问题。(mint下,其他os不太清楚)<br /><div><p><span style="font-size:18px">1: /usr/include/bits/timex.h:31:7:error: expect ':' , ',' , ';' , '}' or '__attribute__'&nbsp; &nbsp; <br /></span><span style="font-size:18px">&nbsp;apue.2e/ipp/ipp.h中 #define status u.st 与 timex.h中的 status 冲突，更改 #define Status u.st</span></p> <p><span style="font-family:Arial; line-height:26px"><span style="font-size:14px">&nbsp;&nbsp;</span></span></p> <p><span style="font-family:Arial; line-height:26px"><span style="font-size:14px"><span style="margin:0px; padding:0px; border:none; font-family:Consolas,'Courier New',Courier,mono,serif; line-height:17.600000381469727px">2：ARG_MAX 未定义</span></span></span></p> <p><span style="font-family:Consolas,Courier New,Courier,mono,serif; font-size:14px"><span style="line-height:17.600000381469727px">&nbsp; &nbsp;在include/apue.h中加入 #define ARG_MAX 4096</span></span></p> <p><span style="font-family:Consolas,Courier New,Courier,mono,serif; font-size:14px"><span style="line-height:17.600000381469727px">&nbsp; &nbsp;在threadctl/getenv1.c 加入 #include "../include/apue.h"</span></span></p> <p><span style="font-family:Consolas,Courier New,Courier,mono,serif; font-size:14px"><span style="line-height:17.600000381469727px">&nbsp; &nbsp;在threadctl/getenv3.c 加入 #include "../include/apue.h"</span></span></p></div>完了之后，make应该就可以成功了<br /><br />完了在codeblocks项目里引用刚编译完的库，有几个方法:<br />1)将编译完的库,头文件apue.h拷贝/usr/include,库文件libapue.a拷贝到/usr/lib下，这个是系统目录，gcc编译的时候会在这目录搜寻<br />2)在项目属性添加静态库引用<br /><div>添加头文件：依次点击project-&gt;bulid options-&gt;Search directories，在该标签页中点击Compiler，单击Add按钮添加头文件路径<br />添加静态库路径：依次点击project-&gt;bulid options-&gt;Linker setting，在该标签页中点击Add按钮添加静态库路径。<br /><br />如果之前你建的是c project的话，应该就可以顺利编译通过了，但是对于建立c++的project,仍然提示链接错误，找不到函数实现，<br />原因是libapue.a是c库，用g++编译的时候要引用c库的话，因为c++编译的时候会在函数加一些额外字符，所以当然会链接错误。</div><div>解决也简单的在函数库前加 extern "C",或者直接把apue.h用extern "C"包含，不清楚的补下相应知识。<br /><br />加点额外的知识关于gcc/g++：<br /><div>gcc和g++的区别<p>误区一:gcc只能编译c代码,g++只能编译c++代码<br />两者都可以，但是请注意：<br />1.后缀为.c的，gcc把它当作是C程序，而g++当作是c++程序；后缀为.cpp的，两者都会认为是c++程序，注意，虽然c++是c的超集，但是两者对语法的要求是有区别的。C++的语法规则更加严谨一些。<br />2.编译阶段，g++会调用gcc，对于c++代码，两者是等价的，但是因为gcc命令不能自动和C＋＋程序使用的库联接，所以通常用g++来完成链接，为了统一起见，干脆编译/链接统统用g++了，这就给人一种错觉，好像cpp程序只能用g++似的。<br /><br />误区二:gcc不会定义__cplusplus宏，而g++会<br />实际上，这个宏只是标志着编译器将会把代码按C还是C++语法来解释，如上所述，如果后缀为.c，并且采用gcc编译器，则该宏就是未定义的，否则，就是已定义。<br /><br />误区三:编译只能用gcc，链接只能用g++<br />严格来说，这句话不算错误，但是它混淆了概念，应该这样说：编译可以用gcc/g++，而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C＋＋程序使用的库联接，所以通常使用g++来完成联接。但在编译阶段，g++会自动调用gcc，二者等价。</p>                                                                                                                          gcc和g++的区别                                                                                                                                                                                                                                                                                                                                                                       我们在编译c/c++代码的时候，有人用gcc，有人用g++，于是各种说法都来了，譬如c代码用gcc，而c++代码用g++，或者说编译用  gcc，链接用g++，一时也不知哪个说法正确，如果再遇上个extern  "C"，分歧就更多了，这里我想作个了结，毕竟知识的目的是令人更清醒，而不是更糊涂。</div></div><br /></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-04 20:23 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/04/196955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Installing Gearman and gearmand on Windows with Cygwin </title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/28/196743.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 28 Dec 2012 03:17:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/28/196743.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196743.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/28/196743.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196743.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196743.html</trackback:ping><description><![CDATA[<div><p>Recently I've come face-to-face with a significant processing task  for a web application written in PHP.&nbsp; I haven't worked with process  control very much, so I started researching ways of distributing the  calculations to multiple processes.&nbsp; PHP offers several libraries for  doing this (<a href="http://php.net/pcntl">pcntl</a>, <a href="http://php.net/posix">POSIX</a>),  but it quickly became clear that if you're running Windows these  libraries are not an option, and unfortunately at work I have a Windows  machine.&nbsp; After a lot more research, I came across <a href="http://gearman.org">Gearman</a>.</p> <p>Gearman is essentially a distributed processing framework, and seems  to have community support for many programming languages.&nbsp; It consists  of two main components: the job server, and a Client and Worker API.&nbsp;  The Client and Worker API can be used in a wide variety of languages,  but the job server is only available as a C library or a Perl library.&nbsp;  This makes it a bit tougher to get the server running on Windows,  especially when you start running into some of the dependencies that it  requires to build.&nbsp; As well, the Client/Worker API for PHP can only be  installed as a PECL extension, or a very-out-of-date PEAR extension  called Net_Gearman.</p> <p>Nonetheless, after yet more research I decided that I would give it a shot by using <a href="http://www.cygwin.com">Cygwin</a>  to get the job server running (if you haven't used Cygwin before, be  sure to read about it before attempting to install Gearman this way),  and PEAR to use the API.&nbsp; Pre-built PECL extensions aren't available for  Windows anymore, and the  build process for PHP extensions can be  pretty painful, so it makes PEAR  look good by comparison even if the  code will be out of date.</p> <p>I had a pretty frustrating time finally getting everything up and  running due to various dependency issues, so I went back through the  whole process and wrote it out step-by-step.&nbsp; I used a Windows XP SP3  machine for this, but I also got it working on a Windows 7 machine as  well.</p> <h2>Installing the Gearman job server (gearmand) on Windows with Cygwin</h2> <h4>Installing Cygwin</h4> <ol><li>If you don't have Cygwin already, you can get it from <a href="http://www.cygwin.com/">http://www.cygwin.com</a>.&nbsp; The setup file is located <a href="http://cygwin.com/setup.exe">here</a>,  and the setup process is pretty straightforward; run it and follow the  wizard.&nbsp; Full installation instructions are available at the Cygwin  site.</li><li>Keep the Cygwin setup.exe file handy after you've installed the  default software packages, as you'll need it in the future to add  packages, similar to apt-get, yum, and other Linux/UNIX package  managers.</li><li>Cygwin installs with some basic packages, including a Cygwin Bash  Shell that goes into your Start Menu.&nbsp; I prefer the mintty emulator  instead, as it has less of a DOS Command Prompt feel and better terminal  features.&nbsp; Feel free to use whatever shell you like of course.&nbsp; You can  get mintty by re-running the setup.exe, and at the package selection  screen, type 'mintty' into the Search bar at the top left.&nbsp; Expand the  "Shells" category, and click on the word "Skip" under the "New" column  beside the mintty package to select it before continuing the install  process.</li></ol> <h4>Installing Cygwin Package Dependencies needed for Gearman</h4> <p>If you're not already in the Cygwin setup, re-run the Cygwin  setup.exe and go through to the package selection screen.&nbsp; The following  is a list of dependency packages you will need in order to build the  Gearman job server (gearmand).&nbsp; None of these packages were installed by  default with Cygwin:</p> <ul><li>gcc</li><li> make</li><li> libuuid1-devel</li><li> libiconv</li></ul> <p>There's a good <a href="http://www.eecg.utoronto.ca/%7Eaamodt/ece242/cygwin.html">installation tutorial here</a>  that walks through getting gcc and make installed for people unfamiliar  with Cygwin.&nbsp; Finding the others is pretty straightforward, the Search  bar in the package selector works well.</p> <h4>Installing libevent</h4> <p>Gearmand requires an event notification library called <a href="http://monkey.org/%7Eprovos/libevent/">libevent </a>that you cannot get as a Cygwin package, which means it has to be installed from source.&nbsp; You can get the source <a href="http://monkey.org/%7Eprovos/libevent/">here</a>.</p> <ol><li>Download and unpack the latest <a href="http://monkey.org/%7Eprovos/libevent/">libevent </a>stable release.&nbsp; At the time of this writing, I used libevent-1.4.14b-stable.<br /> <em><strong>NOTE</strong></em>: Download and unpack to a <strong>directory that does not contain spaces in the name</strong>,  such as "C:/cygwin/home/Zombat/libevent-1.4.14b-stable".&nbsp; If you unpack  to something with spaces like "C:/Documents and Settings/Zombat/", the  build process might not be able to install libevent correctly (libtool  has a hard time with spaces)!</li><li>Open a Cygwin shell and <code>cd</code> to the unpacked libevent directory.</li><li>Run the following commands:</li></ol> <p style="padding-left: 60px;"><code>./configure<br /> make<br /> make install</code></p> <p>libevent should now be installed and ready to be used when compiling the Gearman job server.</p> <h4>Installing the Gearman job server, gearmand.exe</h4> <ol><li>Download and unpack the C implementation of gearmand from http://gearman.org/index.php?id=download</li><li>Open a cygwin shell and cd to your unpacked gearmand directory.&nbsp;  Same rules apply as before, make sure you've unpacked in a directory  with no spaces in the path!&nbsp; libtool hates that, and your build may  fail.</li><li>Run the following commands:</li></ol> <p style="padding-left: 60px;"><code>./configure<br /> make<br /> make install</code></p> <p>The Gearman job server should now be installed and ready to use!&nbsp;  Mine was installed at /usr/local/sbin/gearmand.exe, and running it with a  "triple verbose" flag (<code>-vvv</code>) should produce the following:</p> <p><a href="http://www.phpvs.net/wp-content/uploads/2010/10/gearmand-output.png"><img wp-image-248=""  aligncenter"="" title="gearmand-output" src="http://www.phpvs.net/wp-content/uploads/2010/10/gearmand-output.png" alt="gearmand.exe startup debug output" height="144" width="355" /></a></p> <p>That's it for the job server.&nbsp; When you want to start it, simply open a Cygwin shell and run <code>gearmand.exe</code>.&nbsp;  Running it with the -d flag will cause the server to run as a daemon in  the background, and running with --help will show you the full option  list.</p> <h3>Installing the Gearman Client and Worker API (Net_Gearman)<strong><br /> </strong></h3> <p>I chose to install the PEAR Client and  Worker API, as it is native PHP and doesn't involve compiling PECL  extensions.&nbsp; The PEAR package is called Net_Gearman, and was originally  written by Joe Stump at Digg.com.&nbsp; It is old and out of date now,  although there appears to be a more recent fork at  http://github.com/brianlmoon/net_gearman.&nbsp; I stuck with the older  version, as I suspect it will meet my needs, and was readily available  as a PEAR package.</p> <p>This also makes installation relatively  painless.&nbsp; Assuming you've previously set PEAR up, then all you have to  do is open a command window (not a Cygwin shell) and run:</p> <blockquote> <p><code>pear install Net_Gearman-alpha</code></p> </blockquote> <p>The "-alpha" portion is necessary, as  Net_Gearman apparently never made it to a stable release version.&nbsp; That  being said, it has functioned well for me so far.&nbsp; Perhaps someone will  pick the project up in the future.</p> <p>I'll write more about getting started with  the Client and Worker API in the next article, so we can actually use  Gearman to get some work done.</p></div>转自:<div>http://www.phpvs.net/2010/11/30/installing-gearman-and-gearmand-on-windows-with-cygwin/</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-28 11:17 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/28/196743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>