<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CQ-CSER &#187; OS</title>
	<atom:link href="http://cq-cser.cn/category/os/feed/" rel="self" type="application/rss+xml" />
	<link>http://cq-cser.cn</link>
	<description>计算机爱好者</description>
	<lastBuildDate>Sun, 15 Jan 2012 08:17:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>VNC IN DEBIAN</title>
		<link>http://cq-cser.cn/2010/10/vnc-in-debian/</link>
		<comments>http://cq-cser.cn/2010/10/vnc-in-debian/#comments</comments>
		<pubDate>Sun, 10 Oct 2010 04:06:37 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[linux/unix]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[vnc]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1391</guid>
		<description><![CDATA[debian 下Vnc 学习笔记 1 VNC（Virtual Network Computing，虚拟网络计算）最早是一套由英国剑桥大学AT&#38;T实验 室在 2002年开发的轻量型的远程控制计算机软件，其采用了 GPL 授权条款，任何人都可免 费取得该软件。VNC软件主要由两个部分组成：VNC server及VNC viewer。用户需先将VNC server安装在被控端的计算机上后，才能在主控端执行 VNC viewer 控制被控端。 VNC server 与 VNC viewer 支持多种操作系统，如 windows，Linux，MacOS 及 Unix 系 列（Unix，Solaris等），因此可将 VNC server 及 VNC viewer 分别安装在不同的操 作系统中进行控制。 整 个 VNC 一般运行的工作流程如下： （1） VNC 客户端通过浏览器或 VNC Viewer 连接至 VNC Server。 （2） VNC Server 传送一对话窗口至客户端，要求输入连接密码（可能为空），以及存 取的 VNC Server [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2011/09/samba4_smbclient_linux_winnt_share_file/' rel='bookmark' title='Permanent Link: samba4_smbclient_linux_winnt_share_file'>samba4_smbclient_linux_winnt_share_file</a></li>
<li><a href='http://cq-cser.cn/2010/05/%e5%9c%a8mac-os-x%e4%b8%ad%e8%bf%90%e8%a1%8capache-%ef%bc%8b-php-%ef%bc%8b-mysql/' rel='bookmark' title='Permanent Link: 在Mac OS X中运行Apache ＋ PHP ＋ MySQL'>在Mac OS X中运行Apache ＋ PHP ＋ MySQL</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td height="25" align="center"><span style="color: #02368d;"><strong>debian 下Vnc 学习笔记</strong></span><span id="more-1391"></span></td>
</tr>
<tr>
<td height="1" bgcolor="#d2dee2"></td>
</tr>
<tr>
<td height="1" bgcolor="#ffffff"></td>
</tr>
<tr>
<td align="center">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td width="100%">
<div id="art">1<br />
VNC（Virtual Network Computing，虚拟网络计算）最早是一套由英国剑桥大学AT&amp;T实验<br />
室在 2002年开发的轻量型的远程控制计算机软件，其采用了 GPL 授权条款，任何人都可免<br />
费取得该软件。VNC软件主要由两个部分组成：VNC  server及VNC viewer。用户需先将VNC<br />
server安装在被控端的计算机上后，才能在主控端执行 VNC viewer  控制被控端。<br />
VNC server 与 VNC viewer 支持多种操作系统，如 windows，Linux，MacOS 及 Unix<br />
系 列（Unix，Solaris等），因此可将 VNC server 及 VNC viewer 分别安装在不同的操<br />
作系统中进行控制。<br />
整 个 VNC 一般运行的工作流程如下：<br />
（1） VNC 客户端通过浏览器或 VNC Viewer 连接至 VNC Server。<br />
（2）  VNC Server 传送一对话窗口至客户端，要求输入连接密码（可能为空），以及存<br />
取的 VNC Server 显示装置。<br />
（3）  在客户端输入连接密码后，VNC Server 验证客户端是否具有存取权限。<br />
（4） 若是客户端通过 VNC Server  的验证，客户端即要求 VNC Server 显示桌面环境。<br />
（5） 被控端将画面显示控制权交由 VNC Server 负责。<br />
（6）  VNC Server 将把被控端的桌面环境利用 VNC 通信协议送至客户端，并且允许客户<br />
端控制 VNC Server  的桌面环境及输入装置。</p>
<p>2<br />
other<br />
windows 的XServer 软件有：X-win、Exceed  和cywin 等。<br />
linux下面有了rdesktop,windows下有了x-win32<br />
sudo apt-get install  rdesktop<br />
rdesktop 192.168.100.x<br />
3<br />
sudo axel  -n 11  http://jaist.dl.sourceforge.net/sourceforge/vnc-tight/<br />
tightvnc-1.3.9-setup.exe<br />
install   windowsxp</p>
<p>4<br />
apt-get install xvncviewer<br />
vncviewer  192.168.1.236</p>
<p>5<br />
versions of VNC are available:<br />
* The  original VNC developed by and available from AT&amp;T (Britain)<br />
Home  page: http://www.realvnc.com/<br />
* Tight VNC: Optimized and uses  compression for use over slow networks.<br />
Home page:  http://www.tightvnc.com/</p></div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2011/09/samba4_smbclient_linux_winnt_share_file/' rel='bookmark' title='Permanent Link: samba4_smbclient_linux_winnt_share_file'>samba4_smbclient_linux_winnt_share_file</a></li>
<li><a href='http://cq-cser.cn/2010/05/%e5%9c%a8mac-os-x%e4%b8%ad%e8%bf%90%e8%a1%8capache-%ef%bc%8b-php-%ef%bc%8b-mysql/' rel='bookmark' title='Permanent Link: 在Mac OS X中运行Apache ＋ PHP ＋ MySQL'>在Mac OS X中运行Apache ＋ PHP ＋ MySQL</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/10/vnc-in-debian/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>X Window原理详解</title>
		<link>http://cq-cser.cn/2010/10/x-window%e5%8e%9f%e7%90%86%e8%af%a6%e8%a7%a3/</link>
		<comments>http://cq-cser.cn/2010/10/x-window%e5%8e%9f%e7%90%86%e8%af%a6%e8%a7%a3/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 11:24:04 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[C/S]]></category>
		<category><![CDATA[X Window]]></category>
		<category><![CDATA[出/s]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1385</guid>
		<description><![CDATA[原文：http://blog.chinaunix.net/u2/66903/showart_1409379.html 第一次在Debian下装XFree86，startx启动了twm，装了 gnome 后startx启动了gnome环境，为什么？装gnome 时修改了什么文件以及X环境是怎么起来的？本来是想搞清这几个文题开始研究这个题目的，没想到还学到了很多别的东西^_^本文主要说明X Window System的基本运行原理，其启动过程，及常见的跨网络运行X Window System。 一) 基本运行原理 X Window System采用C/S结构，但和我们常见的C/S不同。常见的C/S结构中，称提供服务的一方为server，即服务器端(如HTTP服务，FTP服务等)，使用服务的称为client，即客户端。但在X Window System中，client是执行程序的一方，在上面执行各种X程序，而server则是负责显示client运行程序的窗口的一方。 X Window System的组成可以分为X server，X client，X protocol三部分。X server主要控制输入输出，维护字体，颜色等相关资源。它接受输入设备的输入信息并传递给X client，X client将这些信息处理后所返回的信息，也由X server负责输出到输出设备(即我们所见的显示器)上。X server传递给X client的信息称为Event，主要是键盘鼠标输入和窗口状态的信息。X client传递给X server的信息则称为Request，主要是要求X server建立窗口，更改窗口大小位置或在窗口上绘图输出文字等。X client主要是完成应用程序计算处理的部分，并不接受用户的输入信息，输入信息都是输入给X server，然后由X server以Event的形式传递给X client(这里感觉类似Windows的消息机制，系统接收到用户的输入信息，然后以消息的形式传递给窗口，再由窗口的消息处理过程处理)。X client对收到的Event进行相应的处理后，如果需要输出到屏幕上或更改画面的外观等，则发出Request给X server，由X server负责显示。 常见的情况是X server与X client都在同一台电脑上运行，但他们也可分别位于网络上不同的电脑上。在X Window System中，X client是与硬件无关的，它并不关心你使用的是什么显卡什么显示器什么键盘鼠标，这些只与X server相关。我们平常安装完XFree86后运行xf86config或xf86cfg进行的配置实际上只是与X server有关，可以说就是配置X server吧，不配置照样可以运行X client程序(如：xeyes -display xserver:0就可以在xserver这台机器上的0号屏幕(屏幕编号displaynumber为0)上显示那对大眼睛了)。 X protocol就是X server于X client之间通信的协议了。X protocol支持现在常用的网络通信协议。我只能测试TCP/IP，可以看到X [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2010/10/pxe%e7%bd%91%e7%bb%9c%e5%ae%89%e8%a3%85linux/' rel='bookmark' title='Permanent Link: PXE网络安装LINUX'>PXE网络安装LINUX</a></li>
<li><a href='http://cq-cser.cn/2010/04/sliverlight%e6%b5%8b%e8%af%95-%e9%9a%8f%e7%ac%94/' rel='bookmark' title='Permanent Link: sliverlight测试-随笔'>sliverlight测试-随笔</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div id="art">
<div><span style="color: #000000;">原文：<a href="http://blog.chinaunix.net/u2/66903/showart_1409379.html">http://blog.chinaunix.net/u2/66903/showart_1409379.html</a><span id="more-1385"></span></span></div>
<div><span style="color: #000000;">第一次在Debian下装XFree86，startx启动了twm，装了 gnome 后startx启动了gnome环境，为什么？装gnome 时修改了什么文件以及X环境是怎么起来的？本来是想搞清这几个文题开始研究这个题目的，没想到还学到了很多别的东西^_^本文主要说明X Window System的基本运行原理，其启动过程，及常见的跨网络运行X Window System。</span></div>
<div><span style="color: #000000;">一) 基本运行原理<br />
X Window System采用C/S结构，但和我们常见的C/S不同。常见的C/S结构中，称提供服务的一方为server，即服务器端(如HTTP服务，FTP服务等)，使用服务的称为client，即客户端。但在X Window System中，client是执行程序的一方，在上面执行各种X程序，而server则是负责显示client运行程序的窗口的一方。<br />
X Window System的组成可以分为X server，X client，X protocol三部分。X server主要控制输入输出，维护字体，颜色等相关资源。它接受输入设备的输入信息并传递给X client，X client将这些信息处理后所返回的信息，也由X server负责输出到输出设备(即我们所见的显示器)上。X server传递给X client的信息称为Event，主要是键盘鼠标输入和窗口状态的信息。X client传递给X server的信息则称为Request，主要是要求X server建立窗口，更改窗口大小位置或在窗口上绘图输出文字等。X client主要是完成应用程序计算处理的部分，并不接受用户的输入信息，输入信息都是输入给X server，然后由X server以Event的形式传递给X client(这里感觉类似Windows的消息机制，系统接收到用户的输入信息，然后以消息的形式传递给窗口，再由窗口的消息处理过程处理)。X client对收到的Event进行相应的处理后，如果需要输出到屏幕上或更改画面的外观等，则发出Request给X server，由X server负责显示。<br />
常见的情况是X server与X client都在同一台电脑上运行，但他们也可分别位于网络上不同的电脑上。在X Window System中，X client是与硬件无关的，它并不关心你使用的是什么显卡什么显示器什么键盘鼠标，这些只与X server相关。我们平常安装完XFree86后运行xf86config或xf86cfg进行的配置实际上只是与X server有关，可以说就是配置X server吧，不配置照样可以运行X client程序(如：xeyes -display xserver:0就可以在xserver这台机器上的0号屏幕(屏幕编号displaynumber为0)上显示那对大眼睛了)。<br />
X protocol就是X server于X client之间通信的协议了。X protocol支持现在常用的网络通信协议。我只能测试TCP/IP，可以看到X server侦听在tcp 6000端口上。那X protocol就是位于运输层以上了，应该属于应用层吧？。<br />
总结下运行过程吧：<br />
(1) 用户通过鼠标键盘对X server下达操作命令<br />
(2) X server利用Event传递用户操作信息给X client<br />
(3) X client进行程序运算<br />
(4) X client利用Request传回所要显示的结果<br />
(5) X server将结果显示在屏幕上</span></div>
<div><span style="color: #000000;">二) 启动过程<br />
我们从控制台进入X一般是用startx命令。下面就从startx分析起。首先man startx和man xinit可以看到staratx和xinit的使用方法：<br />
startx [[client] options &#8230;..] [-- [server] options &#8230;.]<br />
xinit [[client] options ] [-- [server] [display] options]<br />
把上面[client]和[server]分别称为client程序和server程序。man手册里写明其必须以/或者./开头。<br />
下面看看startx这个脚本，中文为我加的注释，这个脚本是安装x-window-system-core后得到的，都是XFree86，不同发行版的linux里该脚本应该大同小异：</span><br />
<span style="color: #000000;">代码:<br />
#!/bin/sh<br />
userclientrc=$HOME/.xinitrc #用户的client定义文件<br />
userserverrc=$HOME/.xserverrc #用户的server定义文件<br />
sysclientrc=/usr/X11R6/lib/X11/xinit/xinitrc #系统的client<br />
sysserverrc=/usr/X11R6/lib/X11/xinit/xserverrc #系统的server<br />
defaultclient=/usr/X11R6/bin/xterm #默认的client程序<br />
defaultserver=/usr/X11R6/bin/X #默认的server程序<br />
defaultclientargs=&#8221;" #下面定义了client和server的参数变量<br />
defaultserverargs=&#8221;"<br />
clientargs=&#8221;"<br />
serverargs=&#8221;"<br />
#如果用户client文件存在则使用用户文件里定义的client，否则使用系统定义的client<br />
if [ -f $userclientrc ]; then<br />
defaultclientargs=$userclientrc<br />
elif [ -f $sysclientrc ]; then<br />
defaultclientargs=$sysclientrc<br />
fi<br />
#如果用户server文件存在则使用用户文件里定义的server，否则使用系统定义的server<br />
if [ -f $userserverrc ]; then<br />
defaultserverargs=$userserverrc<br />
elif [ -f $sysserverrc ]; then<br />
defaultserverargs=$sysserverrc<br />
fi<br />
#下面循环处理client和server的参数<br />
whoseargs=&#8221;client&#8221;<br />
while [ x"$1" != x ]; do #若第一个参数为空，退出循环<br />
case &#8220;$1&#8243; in<br />
# &#8221; required to prevent cpp from treating &#8220;/*&#8221; as a C comment.<br />
/&#8221;*|\./&#8221;*) #如果$1是/*或者./*形式(xinit程序要求其参数里的client程序和server程序必须以/或./开头，否则会被视为client程序和server程序的参数，见man xinit)<br />
if [ "$whoseargs" = "client" ]; then #如果当前是在处理client的参数<br />
if [ x"$clientargs" = x ]; then #如果clientargs为空,则赋值$1给client变量，也即上面#startx使用方法里的[client]参数<br />
client=&#8221;$1&#8243;<br />
else<br />
clientargs=&#8221;$clientargs $1&#8243; #否则clientargs赋值为$clientargs $1，即上面#startx使用#方法里的options参数<br />
fi<br />
else #当前在处理server的参数，代码的含义同上<br />
if [ x"$serverargs" = x ]; then<br />
server=&#8221;$1&#8243;<br />
else<br />
serverargs=&#8221;$serverargs $1&#8243;<br />
fi<br />
fi<br />
;;<br />
&#8211;)#如果$1为&#8211;，则表示开始处理server的参数，&#8211;为client和server参数的分界<br />
whoseargs=&#8221;server&#8221;<br />
;;<br />
*)<br />
if [ "$whoseargs" = "client" ]; then #处理给client程序的参数<br />
clientargs=&#8221;$clientargs $1&#8243;<br />
else #处理给server程序的参数<br />
# display must be the FIRST server argument<br />
#屏幕编号必须为第一个给server程序的参数，以:x的形式(x为数字)，这可从上面startx和xinit<br />
的使用方法的区别看出,xinit多了个[display]，这里即过滤出这个[display]。试试看这两个命令：<br />
xinit /usr/bin/X11/xeyes -display localhost:1 &#8212; /usr/bin/X11/X :1 -dpi 70&amp;<br />
xinit /usr/bin/X11/xeyes -display localhost:1 &#8212; /usr/bin/X11/X -dpi 70 :1&amp;<br />
即可看出不把屏幕编号作为第一个server参数的后果<br />
if [ x"$serverargs" = x ] &amp;&amp; expr &#8220;$1&#8243; : &#8216;:[0-9][0-9]*$&#8217; &gt; /dev/null 2&gt;&amp;1; then</span></div>
<div><span style="color: #000000;">display=&#8221;$1&#8243;<br />
else #处理屏幕编号以外的参数<br />
serverargs=&#8221;$serverargs $1&#8243;<br />
fi<br />
fi<br />
;;<br />
esac<br />
shift #所有参数左移一次<br />
done<br />
# process client arguments<br />
if [ x"$client" = x ]; then #如果client程序为空<br />
# if no client arguments either, use rc file instead<br />
if [ x"$clientargs" = x ]; then #且clientargs为空，赋值$defaultclientargs给client程序<br />
client=&#8221;$defaultclientargs&#8221;<br />
else<br />
client=$defaultclient #使用默认的client程序<br />
fi<br />
fi<br />
# process server arguments处理server参数，同上<br />
if [ x"$server" = x ]; then<br />
# if no server arguments or display either, use rc file instead<br />
if [ x"$serverargs" = x -a x"$display" = x ]; then<br />
server=&#8221;$defaultserverargs&#8221;<br />
else<br />
server=$defaultserver<br />
fi<br />
fi<br />
#…………省略授权代码若干</span></div>
<div><span style="color: #000000;">xinit $client $clientargs &#8212; $server $display $serverargs #把处理过的参数交由xinit程序处理<br />
#………… 由上面代码可以得出startx主要是置X client和X server所在的位置，并处理相关参数，最后交给xinit处理。可以看出startx 设置X client的位置是先搜寻$HOME/.xinitrc，然后是/etc/X11/xinit/xinitrc；设置X server的位置是先搜寻$HOME/.xserverrc，然后是/etc/X11/xinit/xserverrc。这就解释了我们平常为什么说启动X Window时用户目录下的.xinitrc和.xserverrc文件优先级要高。所以我们用startx命令启动X时，如果用户目录存在. xinitrc和.xserverrc文件，则实际上等价于命令xinit $HOME/.xinitrc &#8212; $HOME/.xserverrc 。如果用户目录不存在那两个文件，则等价于xinit /usr/X11R6/lib/X11/xinit/xinitrc &#8212; /usr/X11R6/lib/X11/xinit/xserver。别的情况类推。<br />
至于xinit，则根据startx传过来的参数启动X server，成功后根据xinitrc启动X client。<br />
以上即为X Window System的启动过程，startx只是负责一些参数传递，真正的X启动由xinit实现。实际上可以分为启动X server和启动X client两部分。</span></div>
<div><span style="color: #000000;">下面在用户目录下构造.xinitrc(即X client)和.xserverrc(即X server)文件。在.xserverrc里写入/usr/bin/X11/X :1。.xinitrc里写入/usr/bin/X11/xeyes -display localhost:1。这就是最简单的X server+ X client了，只不过把屏幕编号从默认的0改为了1，这里X server即是/usr/bin/X11/X 程序，X client即是/usr/bin/X11/xeyes 程序。<br />
总结下单机用startx启动过程吧：<br />
(1) startx置X client和X server的位置，处理参数并调用xinit<br />
(2) xinit根据传过来的参数启动X server，成功后呼叫X client<br />
(3) 根据xinitrc设置相关资源，启动窗口管理器,输入法和其他应用程序等X client程序。</span></div>
<div><span style="color: #000000;">但还未搞清楚gnome是怎么起来的！gnome当然属于X client了，看上面启动过程第(3)步。<br />
这里分两种情况看吧，第一种是用系统的xinitrc文件。看/etc/X11/xinit/xinitrc文件(我的sarge装x-window- system-core和gnome-core)，里面只包含了. /etc/X11/Xsession一句话。接着看/etc/X11/Xsession这个脚本，只看关键部分吧。最后面有：</p>
<pre class="brush: plain;">[/code]
SESSIONFILES=$(run_parts $SYSSESSIONDIR)
if [ -n "$SESSIONFILES" ]; then
for SESSIONFILE in $SESSIONFILES; do
. $SESSIONFILE
done
fi
exit 0
[code]</pre>
<p>接着看run_parts()，位于本文件中间:</span></div>
<div>
<span style="color: #000000;">代码:<br />
run_parts () {<br />
# until run-parts --noexec is implemented<br />
if [ -z "$1" ]; then<br />
internal_errormsg "run_parts() called without an argument."<br />
fi<br />
if [ ! -d "$1" ]; then<br />
internal_errormsg "run_parts() called, but \"$1\" does not exist or is" \<br />
"not a directory."<br />
fi<br />
for F in $(ls $1); do<br />
if expr "$F" : '[[:alnum:]_-]\+$' &gt; /dev/null 2&gt;&amp;1; then<br />
if [ -f "$1/$F" ]; then<br />
echo "$1/$F"<br />
fi<br />
fi<br />
done<br />
} 大 概意思就是run_parts () 把$SYSSESSIONDIR目录下的文件名取出来赋值给$SESSIONFILES，然后循环运行该目录下的文件。看看该目录，即 /etc/X11/Xsession.d目录，可以看到几个以数字开头的文件，实际上这些数值就表示了这几个文件被运行的优先级，数字小的优先级高，因为在上面的run_parts () 里是用ls命令显示该目录下的文件，所以前面数字小的被ls时显示在前面，所以被</span></div>
<div>
<span style="color: #000000;">代码:<br />
for SESSIONFILE in $SESSIONFILES; do<br />
. $SESSIONFILE<br />
done 这个for循环执行时也先被执行。看到/etc/X11/Xsession.d目录下有个55gnome-session_gnomerc文件，里面提到了STARTUP变量。然后运行：<br />
</span><a href="mailto:xdkui@Debian:/etc/X11/Xsession.d$"><span style="color: #000000;">xdkui@Debian:/etc/X11/Xsession.d$</span></a><span style="color: #000000;"> grep STARTUP *<br />
看到50xfree86-common_determine-startup文件。里面有</span></div>
<div>
<span style="color: #000000;">代码:<br />
if [ -z "$STARTUP" ]; then<br />
if [ -x /usr/bin/x-session-manager ]; then<br />
STARTUP=x-session-manager<br />
elif [ -x /usr/bin/x-window-manager ]; then<br />
STARTUP=x-window-manager<br />
elif [ -x /usr/bin/x-terminal-emulator ]; then<br />
STARTUP=x-terminal-emulator<br />
fi<br />
fi 即设置启动程序，实际上设置STARTUP变量，如果以上程序都没有找到，则会报错退出，即X环境没有被启动。再运行<br />
</span><a href="mailto:xdkui@Debian:/etc/X11/Xsession.d$"><span style="color: #000000;">xdkui@Debian:/etc/X11/Xsession.d$</span></a><span style="color: #000000;"> grep STARTUP *<br />
看到优先级最低也即最后被运行的99xfree86-common_start文件，里面只有一句话：<br />
exec $STARTUP<br />
好了，到这里就启动我们的X client了，终于完了^_^。总结下这第一种方式的启动过程，简单的说就是依次顺序查找/usr/bin/x-session-manager ，x-window-manager，/usr/bin/x-terminal-emulator 这三个文件。如果存在则启动之，也即X client。如果三个都不存在则报错退出了。看/usr/bin/x-session-manager文件可以看到是个符号连接，最终连接到 /usr/bin/gnome-session，也就是gnome 了。至于我们在gnome 启动时可能会设置启动输入法等程序，那就归gnome-session管了，也就不再分析了。可以试着把/usr/bin/x-session- manager 改为指向xfce4-session(如果安装了的话) ，再startx就会启动xfce4环境了。大概RedHat的switchdesk工具就是改这个连接实现的吧？。或者删掉/usr/bin/x- session-manager ，再startx，只启动了/usr/bin/x-window-manager 所指向的window manager了吧，我这里是blackbox。</span></div>
<div><span style="color: #000000;">下面看第二种情况，即用户目录的xinitrc文件$HOME/.xinitrc。对比hiweed-debian-desktop_0.55_i386，存在$HOME/.xinitrc文件，在里面有exec xfce4-session。故其X client可以说最主要的x-session-manger是从$HOME/.xinitrc启动的。也就不会经过上面第一种情况的执行过程了。</span></div>
<div><span style="color: #000000;">终于把gnome(或者说x-session-manger)的启动过程弄明白了，下面说点别的吧。xinit程序同时启动X server和X client，这在单机上还可。要是位于网络上的两台电脑分别是client和server，则xinit就无能为力了。这时就得靠纯“手工”来启动X 了。下面简单的“手工”启动X server和X client：在CUI模式下运行命令:<br />
</span><a href="mailto:xdkui@Debian:~$X"><span style="color: #000000;">xdkui@Debian:~$X</span></a><span style="color: #000000;"> :1&amp;<br />
看 到了一个灰色的全屏幕和一个鼠标指针，这就是X server了，其屏幕编号为1。下面构造X client，按Ctrl+Alt+F1回到刚才的CUI(Ctrl+Alt+F7对应本机的第一个启动的X server，Ctrl+Alt+F8对应第二个，有人说F7对应屏幕编号为0的X server实际上是不对的，如果第一个启动的屏幕编号为1，第二个启动的编号为0,则F7对应1屏幕，F8对应0屏幕)，运行命令: </span><a href="mailto:xdkui@Debian:~$xeyes"><span style="color: #000000;">xdkui@Debian:~$xeyes</span></a><span style="color: #000000;"> -display localhost:1&amp;<br />
然后按Ctrl+Alt+F7，看到我们的X client也就是xeyes了吧。再回到CUI，运行<br />
</span><a href="mailto:xdkui@Debian:~$X"><span style="color: #000000;">xdkui@Debian:~$X</span></a><span style="color: #000000;">&amp;<br />
开启一个屏幕编号0的X server，CUI下再运行<br />
</span><a href="mailto:xdkui@Debian:~$xterm"><span style="color: #000000;">xdkui@Debian:~$xterm</span></a><span style="color: #000000;">&amp;<br />
这时Ctrl+Alt+F7对应屏幕编号1；而F8对应屏幕编号0，且其X client为xterm。先退出上面的两个X server，下面复杂点手动启动我们的gnome吧，首先<br />
</span><a href="mailto:xdkui@Debian:~$X"><span style="color: #000000;">xdkui@Debian:~$X</span></a><span style="color: #000000;">&amp;<br />
然后<br />
</span><a href="mailto:xdkui@Debian:~$gnome-session"><span style="color: #000000;">xdkui@Debian:~$gnome-session</span></a><br />
<span style="color: #000000;">看 到的就和用startx 启动的X一样了，这时X server是X这个程序，X client是gnome-session及其启动的窗口管理器等程序。看到这里感觉xinit用处并不大(??不知是否正确)，简单的脚本就可以实现。本来想把xinit反汇编了分析下，可懒得搞了^_^这是位于本机的情况，对于X server和X client位于不同主机的情况见下面本文第三部分。<br />
个人感觉对于X Window System，搞清楚X server与X client关系很重要。一般X server很简单，就是/usr/bin/X11/X程序；X client则花样繁多，从高级的CDE,GNOME,KDE，到低级一点的只有twm,Window Maker，blackbox等窗口管理器，再到最简陋的只有xterm,rxvt,xeyes等单个x程序。正是由于X client的各种搭配，使得我们的X Window System看起来多样化。这可能也是X Window System最大的卖点之一吧 ^_^</span></div>
<div><span style="color: #000000;">三) 跨网络运行X Window System<br />
一般用来做服务器的系统(Linux,FreeBSD,Solaris等等)都不会装X server，甚至很多都没有显示器。这样可以在这些系统里安装简单的X client，以GUI的方式远程显示在管理员们所坐的X server里。我们实验室用FreeBSD做网关，提供WWW,FTP服务，一般在管理员的本地机器起个X server，然后ssh或telnet上网关运行X client程序显示在本地显示器上，当然，也可用XDMCP(X Display Manager Control Protocol)，man xsession里提到/etc/X11/Xsession一般被startx(我的/etc/X11/xinit/xinitrc里调用 Xsession脚本)或display manager调用，但有的display manager只调用Xsession而不是xinitrc，故为了startx和display manager两种方式下都可正常启动GUI，最好把X client启动的程序放在Xsession文件里。远程运行X client程序需要设置DISPLAY环境变量，设置为 主机名称：屏幕编号(如192.168.1.2:0，则表示X server是192.168.1.2这台机器上的0号屏幕)；或是给X client程序加个—display参数。由于条件限制，只测试了位于TCP/IP网络环境，X server为192.168.1.2，X client为192.168.1.1。<br />
1) Windows系统做X server<br />
a) 用ssh或telnet方式<br />
Windows下面的X server软件有很多种，我这里使用X-win32。在Windows里运行X-win32程序，则相当于本地机器是个X server。远程登录上Debian(我这里是用VMware仿真网络环境，直接进虚拟机即可^_^)，运行：<br />
</span><a href="mailto:xdkui@xclient:~$export"><span style="color: #000000;">xdkui@xclient:~$export</span></a><span style="color: #000000;"> DISPLAY=192.168.1.2:0<br />
</span><a href="mailto:xdkui@xclient:~$xterm"><span style="color: #000000;">xdkui@xclient:~$xterm</span></a><span style="color: #000000;">&amp;<br />
这时即在Windows里的X server里看到了xterm了，至于X client还运行什么程序就看你的需要了，文件管理器阿，资源查看器等。当然，这里X-win32要设置好授权，好像默认是禁止接入控制，即任何X client都可使用这个X server。<br />
b) XDMCP方式<br />
常见的Display Manager有xdm,gdm,kdm等。我这里使用的是gdm。需要修改gdm的配置文件/etc/X11/gdm/gdm.conf，修改[xdmcp]段的Enable＝true，使得可以远程登录，在X client运行gdm。<br />
在X-win32里建一个XDMCP的session，查询方式，填入IP为运行gdm的机器地址。</span></div>
<div><span style="color: #000000;">连接，即可看到登录界面，下面的就不用说了，享受吧<br />
2) Linux与Linux互联<br />
a) ssh或telnet方式<br />
在linux 本地起个X server，需要注意授权问题，建立文件/etc/X0.hosts，填入X client的IP192.168.1.1，其中X0.hosts表示本地第0个屏幕允许连接的X client地址，建立X1.hosts文件则是本地第1个屏幕允许连接的X client地址，以此类推，man xserver里有。运行<br />
</span><a href="mailto:xdkui@xserver:~$X"><span style="color: #000000;">xdkui@xserver:~$X</span></a><span style="color: #000000;">&amp;<br />
运行该程序时别加-nolisten参数，否则不会在网络上侦听。<br />
这个时候Ctrl+Alt+F7是X server，返回Ctrl+Alt+F1还可以ssh上X client机器上。<br />
然后登录上X client，运行<br />
</span><a href="mailto:xdkui@xclient:~$xterm"><span style="color: #000000;">xdkui@xclient:~$xterm</span></a><span style="color: #000000;"> –display 192.168.1.2:0<br />
即可在本地的X server里看到xterm了，如果有的话，还可把gnome-session也显示在本地来。同样可以在linux里的VMware里做这个测试，需要用点手腕了^_^见下<br />
b) XDMCP方式<br />
在我们的X client里运行gdm(别忘了修改gdm.conf)，然后在本地X server的CUI下面运行X -query 192.168.1.1(X client开gdm机器的地址)。可以看到登录界面了吧。<br />
我是在linux里的VMware里做的测试，说说所用的手腕吧。在Ctrl+Alt+F1的CUI下正常运行startx&amp;启动GUI，这时 Ctrl+Alt+F7即为我的X server，X client启动的gnome，然后在这里运行VMware打开Debian虚拟机，并运行gdm。然后回到Ctrl+Alt+F1，运行X :1 -query 192.168.1.1。看到登录界面了吧。这时Ctrl+Alt+F7为我的0号屏幕，里面运行了虚拟机。Ctrl+Alt+F8为1号屏幕，在远程 GUI登录X client。相当于我在本地起了两个X server。</span></div>
<div><a href="http://www.diybl.com/course/6_system/linux/Linuxjs/200871/129592.html"></a></div>
</div>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2010/10/pxe%e7%bd%91%e7%bb%9c%e5%ae%89%e8%a3%85linux/' rel='bookmark' title='Permanent Link: PXE网络安装LINUX'>PXE网络安装LINUX</a></li>
<li><a href='http://cq-cser.cn/2010/04/sliverlight%e6%b5%8b%e8%af%95-%e9%9a%8f%e7%ac%94/' rel='bookmark' title='Permanent Link: sliverlight测试-随笔'>sliverlight测试-随笔</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/10/x-window%e5%8e%9f%e7%90%86%e8%af%a6%e8%a7%a3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tcp_wrapper</title>
		<link>http://cq-cser.cn/2010/08/tcp_wrapper/</link>
		<comments>http://cq-cser.cn/2010/08/tcp_wrapper/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 17:35:54 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[sec]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1334</guid>
		<description><![CDATA[Tcp_wrapper的安装和使用 端口的限制可以通过限制服务来实现 请使用Tcp_wrapper，RedHat8.0默认是安装的了 －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ Tcp_wrapper的安装和使用 　Internet的开放互连性使得每一台连在网上的服务器都逃脱不了被攻击的可能性，事实上我国从接入互联网以来这类事从未中断过。对目前我国的绝大部分网络管理员而言，熟练的使用Unix操作系统尚是一个亟待解决的问题， 网络安全，很难顾及。然而 今天我们来介绍一个软件Tcp_wrapper，说起这个软件,可算得上是大名鼎鼎了,互联网上, 无论采用何种unix操作系统,安装了这个软件的主机恐怕都是不计其数的,事实上它已经成为一种安全的标准配置.本文就以solaris作为操作环境对这个软件做一说明，在其它的Unix操作系统平台上是相通的，读者根据自己的操作系统的种类稍加变化即可。 Tcp_wrapper是Wietse Venema开发的一个可用于各种Unix平台的免费软件，说起Tcp_wrapper的诞生，到有个小小的故事，大约在1990年，作者所在大学的服务器屡屡受到一个外来黑客侵入， 因为受害主机的硬盘数据屡次被rm –rf / 命令整个抹掉，所以找寻线索极为困难，直到有一天晚上Venema在工作的过程中无意中发现这个黑客在不断的finger 受害主机，偷窥受害者的工作，在那个时候一个想法诞生了：设计一个软件，使它可以截获发起finger请求的IP，用户名等资料，Venema 很快投入了工作,而Tcp_wrapper也由此出现!在这以后，Tcp_wrapper随着应用逐渐成为一种标准的Unix安全工具，成为unix守护程序inetd的一个插件.通过Tcp_wrapper,管理员可以设置对inetd提供的各种服务进行监控和过滤. 我们知道,unix中各种服务的实现是基于inetd这个守护进程的,每当有网络服务请求时,无论是ftp,telnet,rlogin等等,这种请求都被送到处于侦听状态的inetd守护进程,inetd再根据请求启动相应服务.inetd的设置是根据/etc目录下inetd.conf决定的.inetd.conf中标识了每种服务由什么进程来控制,我们抽取一行如下: telnet stream tcp nowait root /usr/sbin/in.telnted in.telned 从上面这一行我们可以看到,telnet这个服务,是由/usr/sbin目录下的in.telnetd来控制的,每当有telnet的连接请求时,inetd就指导in.telnetd来启动telnet服务.这是unix默认的连接方式,在这个过程中,没有管理员可以控制的部分,也没有连接纪录. 而在安装了Tcp_wrapper的主机上,管理员可以对上述服务加以控制,当Tcp_wrapper编译安装成功后,会生成一个tcpd程序,它可以在inetd.conf这个控制文件中取代in.telnetd的位置,这样,每当有telnet的连接请求时,tcpd即会截获,先读取管理员所设置的访问控制文件,合乎要求,则会把这次连接原封不动的转给真正的in.telnetd程序,由in.telnetd完成以后的工作.如果这次连接发起的ip不符合访问控制文件中的设置,则会中断连接请求,拒绝提供telnet服务.除in.telnetd以外,tcpd还可以替代其它各种tcp服务. Tcp_wrapper访问控制的实现是依靠两个文件:hosts.allow,hosts.deny来实现的.这两个文件的语法是比较简单的,基本语法就是:服务类型 :本服务有效ip范围 : 许可或拒绝.如hosts.allow中为: In.telnetd : secu.unix.org : allow In.ftpd : 10.68.32. : allow in.rshd : all　:　 /usr/local/sbin/safe_finger -l @%h &#124; usr/ucb/mail　yiming@371.net 而hosts.deny为:all : all.这两个文件的意思是对telnet来讲,只允许来自secu.unix.org的连接,对ftp而言,允许10.68.32这个c类地址的连接.in.rshd这一部分语法稍微复杂一些,它的意思是外界任何一个ip每次试图使用rsh连接本系统的时候系统会finger发起连接请求的远程用户，并立即将结果发mail到一个管理员的远程信箱yiming@371.net，我们知道,管理员之所以这么做,是因为一般试图进行rsh的连接, 都是有很大的潜在危险性的,这说明也许系统已经被人入侵,并安插了.rhosts文件了,这很危险! 所以对管理员来说,这种连接需要引起极大的注意. hosts.deny文件中的all [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2010/10/%e5%ae%89%e8%a3%85%e7%81%ab%e9%b8%9fbbs%e7%b3%bb%e7%bb%9f/' rel='bookmark' title='Permanent Link: 安装火鸟BBS系统'>安装火鸟BBS系统</a></li>
<li><a href='http://cq-cser.cn/2011/01/linux-passwd/' rel='bookmark' title='Permanent Link: LINUX本地密码遗忘'>LINUX本地密码遗忘</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<h2>Tcp_wrapper的安装和使用</h2>
<div>
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td id="postmessage_58449">端口的限制可以通过限制服务来实现<br />
请使用Tcp_wrapper，RedHat8.0默认是安装的了<span id="more-1334"></span></p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
Tcp_wrapper的安装和使用<br />
　Internet的开放互连性使得每一台连在网上的服务器都逃脱不了被攻击的可能性，事实上我国从接入互联网以来这类事从未中断过。对目前我国的绝大部分网络管理员而言，熟练的使用Unix操作系统尚是一个亟待解决的问题， 网络安全，很难顾及。然而</p>
<p>今天我们来介绍一个软件Tcp_wrapper，说起这个软件,可算得上是大名鼎鼎了,互联网上, 无论采用何种unix操作系统,安装了这个软件的主机恐怕都是不计其数的,事实上它已经成为一种安全的标准配置.本文就以solaris作为操作环境对这个软件做一说明，在其它的Unix操作系统平台上是相通的，读者根据自己的操作系统的种类稍加变化即可。 Tcp_wrapper是Wietse Venema开发的一个可用于各种Unix平台的免费软件，说起Tcp_wrapper的诞生，到有个小小的故事，大约在1990年，作者所在大学的服务器屡屡受到一个外来黑客侵入， 因为受害主机的硬盘数据屡次被rm –rf / 命令整个抹掉，所以找寻线索极为困难，直到有一天晚上Venema在工作的过程中无意中发现这个黑客在不断的finger 受害主机，偷窥受害者的工作，在那个时候一个想法诞生了：设计一个软件，使它可以截获发起finger请求的IP，用户名等资料，Venema 很快投入了工作,而Tcp_wrapper也由此出现!在这以后，Tcp_wrapper随着应用逐渐成为一种标准的Unix安全工具，成为unix守护程序inetd的一个插件.通过Tcp_wrapper,管理员可以设置对inetd提供的各种服务进行监控和过滤.</p>
<p>我们知道,unix中各种服务的实现是基于inetd这个守护进程的,每当有网络服务请求时,无论是ftp,telnet,rlogin等等,这种请求都被送到处于侦听状态的inetd守护进程,inetd再根据请求启动相应服务.inetd的设置是根据/etc目录下inetd.conf决定的.inetd.conf中标识了每种服务由什么进程来控制,我们抽取一行如下:</p>
<p>telnet stream tcp nowait root /usr/sbin/in.telnted in.telned</p>
<p>从上面这一行我们可以看到,telnet这个服务,是由/usr/sbin目录下的in.telnetd来控制的,每当有telnet的连接请求时,inetd就指导in.telnetd来启动telnet服务.这是unix默认的连接方式,在这个过程中,没有管理员可以控制的部分,也没有连接纪录.</p>
<p>而在安装了Tcp_wrapper的主机上,管理员可以对上述服务加以控制,当Tcp_wrapper编译安装成功后,会生成一个tcpd程序,它可以在inetd.conf这个控制文件中取代in.telnetd的位置,这样,每当有telnet的连接请求时,tcpd即会截获,先读取管理员所设置的访问控制文件,合乎要求,则会把这次连接原封不动的转给真正的in.telnetd程序,由in.telnetd完成以后的工作.如果这次连接发起的ip不符合访问控制文件中的设置,则会中断连接请求,拒绝提供telnet服务.除in.telnetd以外,tcpd还可以替代其它各种tcp服务.</p>
<p>Tcp_wrapper访问控制的实现是依靠两个文件:hosts.allow,hosts.deny来实现的.这两个文件的语法是比较简单的,基本语法就是:服务类型 :本服务有效ip范围 : 许可或拒绝.如hosts.allow中为:</p>
<p>In.telnetd : secu.unix.org : allow</p>
<p>In.ftpd : 10.68.32. : allow</p>
<p>in.rshd : all　:　 /usr/local/sbin/safe_finger -l @%h | usr/ucb/mail　yiming@371.net</p>
<p>而hosts.deny为:all : all.这两个文件的意思是对telnet来讲,只允许来自secu.unix.org的连接,对ftp而言,允许10.68.32这个c类地址的连接.in.rshd这一部分语法稍微复杂一些,它的意思是外界任何一个ip每次试图使用rsh连接本系统的时候系统会finger发起连接请求的远程用户，并立即将结果发mail到一个管理员的远程信箱yiming@371.net，我们知道,管理员之所以这么做,是因为一般试图进行rsh的连接, 都是有很大的潜在危险性的,这说明也许系统已经被人入侵,并安插了.rhosts文件了,这很危险! 所以对管理员来说,这种连接需要引起极大的注意. hosts.deny文件中的all : all表示除了这些以外,拒绝来自任何地方的任何服务.以上只是对访问控制文件的一个简单说明,管理员可以参看Tcp_wrapper的相应说明定制更为复杂的控制策略.同时需要说明的是,如果需要象上例中设置对rsh的这种finger,mail功能,是需要在Makefile中打开language extension的.</p>
<p>下面来讲讲Tcp_wrapper的安装</p>
<p>首先，我们从可信站点下载tcp_wrappers，如ftp://ftp.porcupine。org/pub/security/tcp_wrappers_7.6.tar.gz（目前最新的版本是7.6）</p>
<p>我们假设你的主机已有了各种所需的编译工具，cc（或gcc），make（或gmake），gzip等，如果使用solaris的读者主机上没有这些工具，可到sunfreeware.com下载它们，使用其它Unix系统亦可到相关站点下载。我们在得到Tcp_wrapper包后，用gzip和tar将压缩包解开，会生成Tcp_wrapper目录，进入目录，我们需要编辑Makefile文件，使它合乎我们的工作要求。编辑的基本工作可以分为3步。</p>
<p>1：在Makefile的头一部分我们可以看到REAL_DAEMON_DIR的描述，它表明了Unix系统中真正的守护程序所在位置，即上面提到的第六个分隔段的守护进程所在目录，solaris中这些守护程序的目录是/usr/sbin，所以我们将SysV.4 Solaris 2.x OSF AIX前的#注释号去掉，即下面的形式:</p>
<p># Ultrix 4.x SunOS 4.x ConvexOS 10.x Dynix/ptx</p>
<p>#REAL_DAEMON_DIR=/usr/etc</p>
<p>#</p>
<p># SysV.4 Solaris 2.x OSF AIX</p>
<p>REAL_DAEMON_DIR=/usr/sbin</p>
<p>#</p>
<p># BSD 4.4</p>
<p>#REAL_DAEMON_DIR=/usr/libexec</p>
<p>#</p>
<p># HP-UX SCO Unicos</p>
<p>#REAL_DAEMON_DIR=/etc</p>
<p>2：在Makefile 中查找FACILITY= LOG_MAIL这几个关键字，Tcp_wrapper的纪录功能就是由这里实现的，系统默认是使用solaris的MAIL精灵来做连接纪录的，但这样会造成Tcp_wrapper的连接纪录和系统的mail日志混杂在一起,不利于管理员分辨.所以建议还是选用一个solaris中未使用的local精灵.我们在这里使用LOCAL3，即FACILITY= LOG_ LOCAL3 ，SEVERITY级别保持INFO级别不变。在读者的机器上可视情况而定用何种精灵。修改后即下面的形式:</p>
<p># The LOG_XXX names below are taken from the /usr/include/syslog.h file.</p>
<p>FACILITY= LOG_LOCAL3 #LOG_MAIL is what most sendmail daemons use</p>
<p># The syslog priority at which successful connections are logged。</p>
<p>SEVERITY= LOG_INFO # LOG_INFO is normally not logged to the console</p>
<p>3：接着查找/etc/hosts.allow，/etc/hosts.deny，也就是上文提到的访问控制文件，建议将默认的/etc替换为其它路径。 由此Makefile编辑完成，退出vi，执行make sunos5（sunos5这个参数是由Makefile开始描述部分得到，采用其它操作系统的将sunos5替换为为相应参数即可）。我们可以看到系统在编译，成功后，在当前目录下会生成tcpd，tcpdmatch，safe_finger等5个可执行文件。建议选一个目录如/usr/local/sbin，将上述5个文件拷贝到这个目录中，至此Tcp_wrapper本身的编译工作就此结束。</p>
<p>下一步，编辑/etc/inetd.conf，将原</p>
<p>telnet stream tcp nowait root /usr/sbin/in.telnetd in.telnetd中的/usr/sbin/in.telnetd替换为tcpd及其所在路径，在此例中即</p>
<p>telnet stream tcp nowait root /usr/local/sbin/tcpd in.telnetd</p>
<p>其它ftp ， tftp ， rsh ， rlogin等同样操作即可，建议至少替换telnet，ftp，rsh，rlogin这几个守护程序。</p>
<p>编辑结束后，保存文件，ps –ef | grep inetd找出inetd的进程号，kill –HUP 重启inetd进程使改动生效。</p>
<p>接着我们编辑/etc/syslog.conf文件，加入日志纪录功能，在此例中即</p>
<p>#tcp wrapper log</p>
<p>local3.info /var/log/tcplog</p>
<p>编辑结束后，保存文件， 在/var/log下生成tcplog文件，注意这个文件的读写属性， 应该只对root有读写权限。然后ps –ef | grep syslogd，找出syslogd的进程号，kill –HUP 重启syslogd进程使改动生效。</p>
<p>最后一项工作是编辑hosts.deny和hosts.allow文件，按上面的语法编辑即可。至此所有工作完成，我们可以用上述两个文件的设置来试一试，假设主机refuse(IP 11.22.33.44)telnet本机，我们看一看，会有什么反应？</p>
<p>refuse#telnet www.yiming.com</p>
<p>Trying www.yiming.com &#8230;</p>
<p>Connected to www.yiming.com</p>
<p>Connection closed by foreign host.</p>
<p>我们再看看本机Tcp_wrapper的日志，多了一条：</p>
<p>Apr 2 13:56:20 yiming in.telnetd[1769]: refused connect from 11.22.33.44</p>
<p>实际上这种测试可用Tcp_wrapper自带的测试文件tcpdmatch，使用很简单，格式tcpdmatch 守护程序 假定IP 即可，这里也不介绍了。</td>
</tr>
</tbody>
</table>
</div>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2010/10/%e5%ae%89%e8%a3%85%e7%81%ab%e9%b8%9fbbs%e7%b3%bb%e7%bb%9f/' rel='bookmark' title='Permanent Link: 安装火鸟BBS系统'>安装火鸟BBS系统</a></li>
<li><a href='http://cq-cser.cn/2011/01/linux-passwd/' rel='bookmark' title='Permanent Link: LINUX本地密码遗忘'>LINUX本地密码遗忘</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/08/tcp_wrapper/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MonoDevelop-LINUX-C#</title>
		<link>http://cq-cser.cn/2010/07/monodevelop-linux-c/</link>
		<comments>http://cq-cser.cn/2010/07/monodevelop-linux-c/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 14:41:52 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[linux/unix]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1298</guid>
		<description><![CDATA[ 原文链接 先看看本篇文章最终效果：在 Ubuntu 里跑的开 发环境 MonoDevelop [图 片:MonoDevelop1.png] 如 果平时主要开发控制台类、组件、后端服务等程序，可以尝试在Linux类操作系统下搭建C#.Net开发环境，好处是在Linux环境里你不用担心朋友或 同事拿你的电脑来玩魔兽世界或者一不小心被装了一大堆流氓软件 ;-) 1、Linux发行版的选择 在Linuxux操作系统里只要安装Mono环 境就可以开发C#程序，Linux的众多发行版RedHat/CentOS/Fedora、OpenSuse、Debian、Ubuntu都可以安装 Mono。 鉴于 目前 Ubuntu 容易安装、界面漂亮而且比较多人用作桌面环境，所以这里推荐使用 Ubuntu 10.04 。官方网站是：http://www.ubuntu.com/ 在官方网站下载回来的是一个光盘映像文件 （ISO格式），这里需要注意的是 Ubuntu 共有4个不同版本的ISO文件：Desktop版、Alternative版、Netbook版、 Server版。一般下载Desktop就可以了。如果你想通过网络启动安装程序或者使用硬盘安装则需要下载Alternative版。 如果你的电脑硬件配置比较低（内存少于等于 512MB），还可以下载一个轻量级的衍生版：Xubuntu（http://www.xubuntu.org/），如果你的电脑只有256MB内存，那还可以 下载另一个衍生版Lubuntu（http://lubuntu.net/），这个更加轻量级，平时系统启动后只占用 70～100MB内存。 2、安装Ubuntu 安装Ubuntu 的方法非常简单，跟装 WinXP差不多，只需点5，6次“下一步”过10来分钟就可以完成。因为关于安装Ubuntu的过程已经有大量的文章介绍，这里就不再赘述了，下面主要 列举一下安装方式，大家可以根据自己的具体情况选择合适的： （1）虚拟机安装 如果你的电脑速度飞快，内存比较大，用这种方式安装最快，虚拟机软件推荐使用免费 的 VirtualBox。先装好虚拟机软件，然后创建一个新的虚拟机，把下载回来的 ISO文件挂靠到虚拟机，启动之后就可以安装了。 （2）尝试性安装 如果你仅仅想尝试一下在Linux环境开发C# 的感觉，并不打算长期使用，则可以使用这种安装模式。这种安装模式不需要调整硬盘分区（因为整个Linux将安装到一个“虚拟硬盘”文件里头）、不会弄坏 你的现有的系统和软件，只是性能会稍微减低一些。 首先你的系统必须是WinXP/Vista/Win7，然后把ISO文件和一个 Wubi Installer (http://wubi-installer.org/) 的软件放在同一个目录，运行 Wubi installer，选择Ubuntu的安装位置，然后就开始复制文件了，重启计算机会多出一项启动项“Ubuntu install”，选择 它就开始真正的安装过程了。 下 面的安装方式需要先在硬盘腾出一块空白的空间（最好准备至少10GB），主分区以外的自由空间或者扩展分区的自由空间都可以，你可以用PQMagic软件慢慢 调整自己硬盘的分区大小。在安装过程中程序会询问你将Ubuntu安装在何处，选择使用“最大连续空间”即可。 （3）光盘安装 这种安装方式最简单，将下载回来的ISO文件刻 录成光盘，设置从光盘启动并重启计算机。 （4） 硬盘安装 要下载Alternative版的ISO文件， 放到C盘根目录，然后下载“UNetbootin ”（http://unetbootin.sourceforge.net/）软件，也放在C盘根目录，运 行 UNetbootin，在发行版类型项选择Ubuntu和MediaHD即开始复制文件，重启电脑开始安装。 （5）用U盘安装/安装到U盘 先使用安装光盘启动计算机，选择“试用”进入 LiveCD模式的Ubuntu，然后在“系统”-&#62;“系统管理”点击“制作启动盘”，准备一个1GB以上的U盘，启动盘制作程序会把Ubuntu 的所有文件复制到U盘，然后就可以使用这个U盘启动其他电脑并安装系统了。也可以直接从这个U盘启动进入系统。 （6）通过网络安装 如果你的电脑没有光驱也不支持U盘启动，而带有 从网卡启动（PXE）功能。或者有一批电脑需要批量安装，则可以使用这种安装模式，具体的请见：http://kalashnicov.javaeye.com/blog/663337 [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2010/01/6564/' rel='bookmark' title='Permanent Link: 让.NET Windows Forms程序脱离官方.NET框架运行之最简Mono方案(3mb)'>让.NET Windows Forms程序脱离官方.NET框架运行之最简Mono方案(3mb)</a></li>
<li><a href='http://cq-cser.cn/2009/11/linux-ssh%e5%91%bd%e4%bb%a4%e5%a4%a7%e5%85%a8/' rel='bookmark' title='Permanent Link: Linux SSH命令大全'>Linux SSH命令大全</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p> <a href="http://www.cnblogs.com/domslab/archive/2010/07/08/1774005.html" target="_blank">原文链接</a></p>
<p>先看看本篇文章最终效果：在 Ubuntu 里跑的开 发环境 MonoDevelop</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/domslab/ubuntu/MonoDevelop1.png" border="0" alt="" width="500" height="374" /><br />
[图 片:MonoDevelop1.png]<br />
<span id="more-1298"></span><br />
如 果平时主要开发控制台类、组件、后端服务等程序，可以尝试在Linux类操作系统下搭建C#.Net开发环境，好处是在Linux环境里你不用担心朋友或 同事拿你的电脑来玩魔兽世界或者一不小心被装了一大堆流氓软件 ;-)</p>
<p>1、Linux发行版的选择</p>
<p>在Linuxux操作系统里只要安装Mono环 境就可以开发C#程序，Linux的众多发行版RedHat/CentOS/Fedora、OpenSuse、Debian、Ubuntu都可以安装 Mono。<br />
鉴于 目前 Ubuntu 容易安装、界面漂亮而且比较多人用作桌面环境，所以这里推荐使用 Ubuntu 10.04 。官方网站是：<a href="http://www.ubuntu.com/" target="_blank">http://www.ubuntu.com/</a><br />
在官方网站下载回来的是一个光盘映像文件 （ISO格式），这里需要注意的是 Ubuntu 共有4个不同版本的ISO文件：Desktop版、Alternative版、Netbook版、 Server版。一般下载Desktop就可以了。如果你想通过网络启动安装程序或者使用硬盘安装则需要下载Alternative版。<br />
如果你的电脑硬件配置比较低（内存少于等于 512MB），还可以下载一个轻量级的衍生版：Xubuntu（<a href="http://www.xubuntu.org/" target="_blank">http://www.xubuntu.org/</a>），如果你的电脑只有256MB内存，那还可以 下载另一个衍生版Lubuntu（<a href="http://lubuntu.net/" target="_blank">http://lubuntu.net/</a>），这个更加轻量级，平时系统启动后只占用 70～100MB内存。</p>
<p>2、安装Ubuntu</p>
<p>安装Ubuntu 的方法非常简单，跟装 WinXP差不多，只需点5，6次“下一步”过10来分钟就可以完成。因为关于安装Ubuntu的过程已经有大量的文章介绍，这里就不再赘述了，下面主要 列举一下安装方式，大家可以根据自己的具体情况选择合适的：</p>
<p>（1）虚拟机安装<br />
如果你的电脑速度飞快，内存比较大，用这种方式安装最快，虚拟机软件推荐使用免费 的 VirtualBox。先装好虚拟机软件，然后创建一个新的虚拟机，把下载回来的 ISO文件挂靠到虚拟机，启动之后就可以安装了。</p>
<p>（2）尝试性安装<br />
如果你仅仅想尝试一下在Linux环境开发C# 的感觉，并不打算长期使用，则可以使用这种安装模式。这种安装模式不需要调整硬盘分区（因为整个Linux将安装到一个“虚拟硬盘”文件里头）、不会弄坏 你的现有的系统和软件，只是性能会稍微减低一些。<br />
首先你的系统必须是WinXP/Vista/Win7，然后把ISO文件和一个 Wubi Installer (<a href="http://wubi-installer.org/" target="_blank">http://wubi-installer.org/</a>) 的软件放在同一个目录，运行 Wubi installer，选择Ubuntu的安装位置，然后就开始复制文件了，重启计算机会多出一项启动项“Ubuntu install”，选择 它就开始真正的安装过程了。</p>
<p><strong>下 面的安装方式需要先在硬盘腾出一块空白的空间（最好准备至少10GB），</strong>主分区以外的自由空间或者扩展分区的自由空间都可以，你可以用PQMagic软件慢慢 调整自己硬盘的分区大小。在安装过程中程序会询问你将Ubuntu安装在何处，选择使用“最大连续空间”即可。</p>
<p>（3）光盘安装<br />
这种安装方式最简单，将下载回来的ISO文件刻 录成光盘，设置从光盘启动并重启计算机。</p>
<p>（4） 硬盘安装<br />
要下载Alternative版的ISO文件， 放到C盘根目录，然后下载“UNetbootin<br />
”（<a href="http://unetbootin.sourceforge.net/" target="_blank">http://unetbootin.sourceforge.net/</a>）软件，也放在C盘根目录，运 行 UNetbootin，在发行版类型项选择Ubuntu和MediaHD即开始复制文件，重启电脑开始安装。</p>
<p>（5）用U盘安装/安装到U盘<br />
先使用安装光盘启动计算机，选择“试用”进入 LiveCD模式的Ubuntu，然后在“系统”-&gt;“系统管理”点击“制作启动盘”，准备一个1GB以上的U盘，启动盘制作程序会把Ubuntu 的所有文件复制到U盘，然后就可以使用这个U盘启动其他电脑并安装系统了。也可以直接从这个U盘启动进入系统。</p>
<p>（6）通过网络安装<br />
如果你的电脑没有光驱也不支持U盘启动，而带有 从网卡启动（PXE）功能。或者有一批电脑需要批量安装，则可以使用这种安装模式，具体的请见：<a href="http://kalashnicov.javaeye.com/blog/663337" target="_blank">http://kalashnicov.javaeye.com/blog/663337</a></p>
<p>3、安装开发环境 MonoDevelop</p>
<p>安装好Ubuntu 10.04之后会发现系统已经自带Mono运行和编译环境，而且还有部分Ubuntu系统自带的软件是C#写的，比如tomboy便利帖、IQ测试游戏gbrainy、照片查看和管理程序F-Spot</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/domslab/ubuntu/f-spot.png" border="0" alt="" width="500" height="375" /> </p>
<p>[图片：F-spot.png]</p>
<p>如果你已经习惯了Win7的任务栏，推荐另外一 个任务栏软件“Docky”，它也是C#写的</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/domslab/ubuntu/Docky.png" border="0" alt="" width="502" height="376" /> </p>
<p>[图片：Docky.png]</p>
<p>MacOS的同学请淡定。<br />
记住在Ubuntu里安装软件是不需要去什么软 件下载网站的，所有需要的软件都可以在“Ubuntu软件中心”找到、安装、卸载。</p>
<p>运行“Ubuntu软件中心”，输入需要安装的软件名称，比如 “MonoDevelop”，然后点击“安装”，程序会自动上网下载并安装。</p>
<p>好了，现在就已经搭建好C#开发环境了，试试写一个HelloWorld吧（效果图 片见文章开头处）</p>
<p>4、其他</p>
<p>MonoDevelop除了能写C#程序之外， 还能写C，C++，Java等程序，只要安装相应的插件和编译器即可，</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/domslab/ubuntu/MonoDevelop2.png" border="0" alt="" width="500" height="375" /> </p>
<p>[图片：MonoDevelop2.png]</p>
<p>附录：</p>
<p>mono项目主页： <a href="http://mono-project.com/" target="_blank">http://mono-project.com</a></p>
<p>控制台、窗口、Web的HelloWorld演示程序：<a href="http://mono-project.com/Mono_Basics" target="_blank">http://mono-project.com/Mono_Basics</a></p>
<p> mono 与 ms.net 的兼容性列表： <a href="http://mono-project.com/Compatibility" target="_blank">http://mono-project.com/Compatibility</a></p>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2010/01/6564/' rel='bookmark' title='Permanent Link: 让.NET Windows Forms程序脱离官方.NET框架运行之最简Mono方案(3mb)'>让.NET Windows Forms程序脱离官方.NET框架运行之最简Mono方案(3mb)</a></li>
<li><a href='http://cq-cser.cn/2009/11/linux-ssh%e5%91%bd%e4%bb%a4%e5%a4%a7%e5%85%a8/' rel='bookmark' title='Permanent Link: Linux SSH命令大全'>Linux SSH命令大全</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/07/monodevelop-linux-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cygwin的使用方法</title>
		<link>http://cq-cser.cn/2010/07/cygwin%e7%9a%84%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95/</link>
		<comments>http://cq-cser.cn/2010/07/cygwin%e7%9a%84%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 04:31:22 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1296</guid>
		<description><![CDATA[原文如下： By EnterBD[BCT] QQ:4791821 E-Mail:Taynni@Gmail.com 欢迎转载和指出错误,但请保留以上信息,谢谢. 0:简介 1:下载和安装 2:使用 简介 Cygwin是一个运行于Windows下的免费的UNIX的子系统,使用一个Dll(动态链接库)来 实现,这样,我们可以开发出Cygwin下的UNIX工具,使用这个DLL运行在Windows下,大家可以想 一下,你在运行Windows的同时,也可以使用VI,BASH,TAR,SED等UNIX下的工具,不是很好吗?这个VM 虚拟机有很相同的原理,但是VM是虚拟多个,而Cygwin是同时使用Windows和UNIX,很爽吧,这样 对于那些在Windows和Unix下移植的程序来说是比较简单的事情了. 一:下载和安装 其下载安装程序在Http://www.cygwin.com,下载安装程序以后,运行,然后会要你选择是通过什么方 式进行下载安装所需要的文件,有三种方式,Http.Ftp.本地,我建议你首先通过Http和Ftp把安装所需要的 文件全部下回来以后选择本地安装比较好,在线安装比较慢,会是一个很长的等待,虽然所需要的文件 不大,但是全部安装的话会是4G大小,还是有选择性的安装吧,在安装界面,有Prev(老版本),Curr(当前版本) Exp(最新版本测试版本),苹果这里建议你选择Curr,然后你单击View按钮,这样你可以在可以使用的安装 文件之间进行选择性的安装,如果你真的想全部安装的话,那么左键点击一下最上面的All,然后看到 INSTALL,这样选择了全部,进行全部安装便可以了,安装完以后,会在桌面产生一个图标,双击这个图标, 呵呵,你便可以使用Cygwin了.关于安装的具体参数方法,网络上有比较详细的介绍,我就不罗嗦了. PS:下载方面我建议如下:你可以下载以下几个版本的Cygwin: 您现在可以使用Cygwin.cn的镜像，详情请参考[安装] 原始站: http://sources.redhat.com/cygwin/; 印地安那大学的免安砚光盘cygwin, 叫做 XLiveCD:http://xlivecd.indiana.edu/ , USA, Indiana ftp://ftp.ussg.indiana.edu/pub/xlivecd/xlivecd-20041201.iso Mirrors: Belgium, Geel ftp://sin.khk.be/mirror/xlivecd/xlivecd-20041201.iso Germany, Bochum ftp://linux.rz.ruhr-uni-bochum.de/xlivecd/xlivecd-20041201.iso Germany, Bochum http://linux.rz.ruhr-uni-bochum.de/download/xlivecd/xlivecd-20041201.iso Sweden, Ume? http://ftp.acc.umu.se/mirror/xlivecd/xlivecd-20041201.iso USA, Wisconsin ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso USA, Georgia ftp://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso USA, [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<div id="fontzoom">
<p><span style="color: #ff0000;"><strong>原文如下：</strong></span></p>
<p>By EnterBD[BCT]<br />
QQ:4791821<br />
E-Mail:Taynni@Gmail.com<br />
欢迎转载和指出错误,但请保留以上信息,谢谢.</p>
<p>0:简介<br />
1:下载和安装<br />
2:使用<br />
<span id="more-1296"></span><br />
简介<br />
Cygwin是一个运行于Windows下的免费的UNIX的子系统,使用一个Dll(动态链接库)来</p>
<p>实现,这样,我们可以开发出Cygwin下的UNIX工具,使用这个DLL运行在Windows下,大家可以想</p>
<p>一下,你在运行Windows的同时,也可以使用VI,BASH,TAR,SED等UNIX下的工具,不是很好吗?这个VM</p>
<p>虚拟机有很相同的原理,但是VM是虚拟多个,而Cygwin是同时使用Windows和UNIX,很爽吧,这样</p>
<p>对于那些在Windows和Unix下移植的程序来说是比较简单的事情了.</p>
<p>一:下载和安装</p>
<p>其下载安装程序在<a title="Http://www.cygwin.com,下载安装程序以后,运行,然后会要你选择是通过什么方" href="http://www.cygwin.com,下载安装程序以后,运行,然后会要你选择是通过什么方/" target="_blank"><span style="text-decoration: underline;">Http://www.cygwin.com,下载安装程序以后,运行,然后会要你选择是通过什么方</span></a></p>
<p>式进行下载安装所需要的文件,有三种方式,Http.Ftp.本地,我建议你首先通过Http和Ftp把安装所需要的</p>
<p>文件全部下回来以后选择本地安装比较好,在线安装比较慢,会是一个很长的等待,虽然所需要的文件</p>
<p>不大,但是全部安装的话会是4G大小,还是有选择性的安装吧,在安装界面,有Prev(老版本),Curr(当前版本)<br />
Exp(最新版本测试版本),苹果这里建议你选择Curr,然后你单击View按钮,这样你可以在可以使用的安装</p>
<p>文件之间进行选择性的安装,如果你真的想全部安装的话,那么左键点击一下最上面的All,然后看到</p>
<p>INSTALL,这样选择了全部,进行全部安装便可以了,安装完以后,会在桌面产生一个图标,双击这个图标,</p>
<p>呵呵,你便可以使用Cygwin了.关于安装的具体参数方法,网络上有比较详细的介绍,我就不罗嗦了.</p>
<p>PS:下载方面我建议如下:你可以下载以下几个版本的Cygwin:</p>
<p>您现在可以使用Cygwin.cn的镜像，详情请参考[安装]</p>
<p>原始站: <a title="http://sources.redhat.com/cygwin/;" href="http://sources.redhat.com/cygwin/;" target="_blank"><span style="text-decoration: underline;">http://sources.redhat.com/cygwin/;</span></a><br />
印地安那大学的免安砚光盘cygwin, 叫做 XLiveCD:<a title="http://xlivecd.indiana.edu/" href="http://xlivecd.indiana.edu/" target="_blank"><span style="text-decoration: underline;">http://xlivecd.indiana.edu/</span></a> ,<br />
USA, Indiana <a title="ftp://ftp.ussg.indiana.edu/pub/xlivecd/xlivecd-20041201.iso" href="ftp://ftp.ussg.indiana.edu/pub/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://ftp.ussg.indiana.edu/pub/xlivecd/xlivecd-20041201.iso</span></a><br />
Mirrors:<br />
Belgium, Geel <a title="ftp://sin.khk.be/mirror/xlivecd/xlivecd-20041201.iso" href="ftp://sin.khk.be/mirror/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://sin.khk.be/mirror/xlivecd/xlivecd-20041201.iso</span></a><br />
Germany, Bochum <a title="ftp://linux.rz.ruhr-uni-bochum.de/xlivecd/xlivecd-20041201.iso" href="ftp://linux.rz.ruhr-uni-bochum.de/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://linux.rz.ruhr-uni-bochum.de/xlivecd/xlivecd-20041201.iso</span></a><br />
Germany, Bochum <a title="http://linux.rz.ruhr-uni-bochum.de/download/xlivecd/xlivecd-20041201.iso" href="http://linux.rz.ruhr-uni-bochum.de/download/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">http://linux.rz.ruhr-uni-bochum.de/download/xlivecd/xlivecd-20041201.iso</span></a><br />
Sweden, Ume? <a title="http://ftp.acc.umu.se/mirror/xlivecd/xlivecd-20041201.iso" href="http://ftp.acc.umu.se/mirror/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">http://ftp.acc.umu.se/mirror/xlivecd/xlivecd-20041201.iso</span></a><br />
USA, Wisconsin <a title="ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso" href="ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso</span></a><br />
USA, Georgia <a title="ftp://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso" href="ftp://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso</span></a><br />
USA, Georgia <a title="http://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso" href="http://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">http://ftp.gtlib.cc.gatech.edu/pub/XLiveCD/xlivecd-20041201.iso</span></a><br />
苹果提示:USA, Wisconsin <a title="ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso" href="ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso" target="_blank"><span style="text-decoration: underline;">ftp://xlivecd.mirrors.tds.net/pub/xlivecd/xlivecd-20041201.iso</span></a><br />
这个下载速度快<br />
Shelley Yen 的cygnuwin : <a title="ftp://ftp.tceb.edu.tw/pub/free_software/cygnuwin/" href="ftp://ftp.tceb.edu.tw/pub/free_software/cygnuwin/" target="_blank"><span style="text-decoration: underline;">ftp://ftp.tceb.edu.tw/pub/free_software/cygnuwin/</span></a><br />
<a title="ftp://ftp.tcc.edu.tw/iso/cygwin/cyg+gnu.iso" href="ftp://ftp.tcc.edu.tw/iso/cygwin/cyg+gnu.iso" target="_blank"><span style="text-decoration: underline;">ftp://ftp.tcc.edu.tw/iso/cygwin/cyg+gnu.iso</span></a>(cygwin 与 gnuwin 的合成版本)<br />
老古开发网:<a title="ftp://ic.laogu.com/down/cygwin.rar" href="ftp://ic.laogu.com/down/cygwin.rar" target="_blank"><span style="text-decoration: underline;">ftp://ic.laogu.com/down/cygwin.rar</span></a><br />
<a title="http://soft.laogu.com/down/cygwin.rar" href="http://soft.laogu.com/down/cygwin.rar" target="_blank"><span style="text-decoration: underline;">http://soft.laogu.com/down/cygwin.rar</span></a> (均为05年3月版本)</p>
<p>苹果提示:这个站点是高人站点,比较NB,呵呵,喜欢单片机的朋友有福气,超级多 的下载资料等着你,包含*NIX下的东西&#8230;</p>
<p>其他的镜像站点:<a title="http://cygwin.com/mirrors.html" href="http://cygwin.com/mirrors.html" target="_blank"><span style="text-decoration: underline;">http://cygwin.com/mirrors.html</span></a></p>
<p>苹果自己也下载了最新版本的Cygwin，但是偶没有空间，真的需要的话，请哪位好心人提供空间</p>
<p>偶可以上传上去，联系请加偶的QQ:4791821，或者给偶发邮件:Taynni@gmail.com注明一下就可以了.</p>
<p>二:使用</p>
<p>使用上的方便性很是不错，启动Cygwin以后，会在Windows下得到一个Bash Shell，由于Cygwin是以</p>
<p>Windows下的服务运行的，所以很多情况下和在Linux下有很大的不同，这点上，苹果建议你多理解下这个</p>
<p>工作环境。我们开始使用Cygwin吧，比如PS，相当于Windows下的TM(任务管理器)，呵呵，直接Ps的话</p>
<p>那么得到的会是Cygwin下的Shell的进程如下<br />
Taynni-417@ENTERBD-417 ~<br />
$ ps<br />
PID PPID PGID WINPID TTY UID STIME COMMAND<br />
2212 1 2212 2212 con 1003 01:54:29 /usr/bin/bas<br />
3384 2212 3384 3232 con 1003 01:59:24 /usr/bin/ps</p>
<p>如果这个时候你需要在Cygwin下显示Windows下的进程你可以在PS后面加上参数-aW，</p>
<p>PS的相关用法:</p>
<div>Quote<br />
Usage ps [-aefl] [-u uid]<br />
-f = show process uids, ppids<br />
-l = show process uids, ppids, pgids, winpids<br />
-u uid = list processes owned by uid<br />
-a, -e = show processes of all users<br />
-s = show process summary<br />
-W = show windows as well as cygwin processes</div>
<p>很容易看懂吧，呵呵</p>
<p>有点不一样的地方，我想大家一定想知道在Cygwin下怎么访问Windows下的内容了，</p>
<p>呵呵，首先使用DF命令直接查看下本地驱动器，呵呵，很容易了吧，显示的内容</p>
<p>如下:</p>
<div>Quote<br />
Taynni-417@ENTERBD-417 ~<br />
$ df<br />
Filesystem 1k-blocks Used Available Use% Mounted on<br />
e:\cygwin\bin 10231384 4844432 5386952 48% /usr/bin<br />
e:\cygwin\lib 10231384 4844432 5386952 48% /usr/lib<br />
e:\cygwin 10231384 4844432 5386952 48% /<br />
c: 5106676 1240312 3866364 25% /cygdrive/c<br />
d: 10239408 6560328 3679080 65% /cygdrive/d<br />
e: 10231384 4844432 5386952 48% /cygdrive/e<br />
f: 6333252 4065564 2267688 65% /cygdrive/f<br />
g: 7150972 4672724 2478248 66% /cygdrive/g</div>
<p>如上便是我的硬盘的全部了，在后面的/cygdrive/c便是C盘了，然后/cygdrive/d便是D盘了</p>
<p>这样的话，想进D盘便可以这样进，呵呵</p>
<div>Quote<br />
Taynni-417@ENTERBD-417 ~<br />
$ cd /cygdrive/d</p>
<p>Taynni-417@ENTERBD-417 /cygdrive/d<br />
$ ls -l<br />
ls: pagefile.sys: Permission denied<br />
total 0<br />
drwxr-xr-x 9 Taynni-4 None 0 Aug 31 20:56 Book<br />
drwxr-xr-x 2 Taynni-4 None 0 Aug 23 05:24 Ftproot<br />
drwxr-xr-x 30 Taynni-4 None 0 May 10 23:38 HACKER<br />
drwxr-xr-x 11 Taynni-4 None 0 Feb 1 2005 JIAOXUE<br />
drwxr-xr-x 8 Taynni-4 None 0 Jan 3 2005 Local Settings<br />
dr-xr-xr-x 24 Taynni-4 None 0 Oct 16 2004 My Documents<br />
drwxr-xr-x 12 Taynni-4 None 0 May 14 16:48 Mywww<br />
drwxr-xr-x 2 Taynni-4 None 0 Jun 29 2004 Recycled<br />
drwxr-xr-x 3 Taynni-4 None 0 Aug 22 04:44 SECBOOK<br />
drwxr-xr-x 6 Taynni-4 None 0 Feb 28 2005 TaynniCHX<br />
drwxr-xr-x 15 Taynni-4 None 0 Mar 30 01:04 TaynniGZ<br />
drwxr-xr-x 12 Taynni-4 None 0 May 11 01:30 TaynniH<br />
drwxr-xr-x 15 Taynni-4 None 0 Mar 12 04:27 TaynniYM<br />
drwxr-xr-x 6 Taynni-4 None 0 Dec 13 2004 Taynniwww<br />
drwxr-xr-x 8 Taynni-4 None 0 Aug 31 20:55 Word</p>
<p>Taynni-417@ENTERBD-417 /cygdrive/d<br />
$</p>
<p>在Cygwin下还可以运行Windows下的程序，如下:<br />
Taynni-417@ENTERBD-417 ~<br />
$ cmd.exe<br />
Microsoft Windows XP [Version 5.1.2600]<br />
(C) Copyright 1985-2001 Microsoft Corp.</p>
<p>e:\cygwin\home\Taynni-417&gt;d:</p>
<p>D:\&gt;cd hacker</p>
<p>D:\HACKER&gt;cd tools</p>
<p>D:\HACKER\Tools&gt;cd pstools</p>
<p>D:\HACKER\Tools\Pstools&gt;ls<br />
pdh.dll pskill.exe pspasswd.exe<br />
Psinfo.exe psexec.exe pslist.exe psservice.exe<br />
Pstools.chm psfile.exe psloggedon.exe psshutdown.exe<br />
README.TXT psgetsid.exe psloglist.exe pssuspend.exe</p>
<p>D:\HACKER\Tools\Pstools&gt;exit</p>
<p>Taynni-417@ENTERBD-417 ~<br />
$</p></div>
<p>很明显的，直接输入CMD.EXE便可以得到一个本机CMDSHELL，这样你想运行什么程序都可以了</p>
<p>退出到Cygwin的Bash shell需要使用exit命令，很方便吧，呵呵</p>
<p>在Cygwin下还可以进行编译程序，比如C和perl，当然，你也可以借助ActivePy，这个东西也很不错</p>
<p>也是一个仿真器，在Windows下模拟perl的解释器.</p>
<p>对于一个系统而言，没有相应的系统工具是不可能的，在Cygwin下拥有的UNIX工具基本上够你使用</p>
<p>了。当然，这需要你安装完整的Cygwin包，我的机子上就安装了完整的，比较大，如果硬盘允许，苹果建</p>
<p>议你完整安装!像grep，cut，sed，strings，strace，md5sum，diff，patch，ssh，xxd，等等工具</p>
<p>你都可以进行安装和使用，如果你真的不知道应该怎么用这些工具，其实苹果很多也不会，只要去接触</p>
<p>你就会了！！！没有不会使用的东西，只有你愿意不愿意去使用而已！说笑了,言归正传，请使用</p>
<p>所要使用的命令 &#8211;help获取帮助，如下所示:比如我不知道md5sum做什么用的</p>
<p>（这个命令是用于效验文件md5值的，主要是为了文件的完整性和安全性）</p>
<div>Quote<br />
Taynni-417@ENTERBD-417 ~<br />
$ md5sum &#8211;help<br />
Usage: md5sum [OPTION] [FILE]&#8230;<br />
or: md5sum [OPTION] &#8211;check [FILE]<br />
Print or check MD5 (128-bit) checksums.<br />
With no FILE, or when FILE is -, read standard input.</p>
<p>-b, &#8211;binary read files in binary mode (default on DOS/Windows)<br />
-c, &#8211;check check MD5 sums against given list<br />
-t, &#8211;text read files in text mode (default)</p>
<p>The following two options are useful only when verifying checksums:<br />
&#8211;status don&#8217;t output anything, status code shows success<br />
-w, &#8211;warn warn about improperly formated checksum lines</p>
<p>&#8211;help display this help and exit<br />
&#8211;version output version information and exit</p>
<p>The sums are computed as described in RFC 1321. When checking, the input<br />
should be a former output of this program. The default mode is to print<br />
a line with checksum, a character indicating type (`*&#8217; for binary, ` &#8216; for<br />
text), and name for each FILE.</p>
<p>Taynni-417@ENTERBD-417 ~<br />
$</p></div>
<p>基本使用上应该没有多大的问题了，文章因为我偷懒，也是不知道该怎么写才可以帮助大家</p>
<p>我很苦恼的是，并没有人给我意见，所以先写这么点吧，如果你有问题的话，请加我的qq或者</p>
<p>给我邮件，大家可以讨论，不是么？</p>
<p>下面给出一些关于Cygwin的资料:<br />
1:<a title="http://www.isi.edu/nsnam/ns/ns-cygwin.html" href="http://www.isi.edu/nsnam/ns/ns-cygwin.html" target="_blank"><span style="text-decoration: underline;">http://www.isi.edu/nsnam/ns/ns-cygwin.html</span></a><br />
2:<a title="http://pigtail.net/LRP/printsrv/cygwin-sshd.html" href="http://pigtail.net/LRP/printsrv/cygwin-sshd.html" target="_blank"><span style="text-decoration: underline;">http://pigtail.net/LRP/printsrv/cygwin-sshd.html</span></a><br />
3:<a title="http://kde-cygwin.sourceforge.net/" href="http://kde-cygwin.sourceforge.net/" target="_blank"><span style="text-decoration: underline;">http://kde-cygwin.sourceforge.net/</span></a><br />
4:<a title="http://x.cygwin.com/" href="http://x.cygwin.com/" target="_blank"><span style="text-decoration: underline;">http://x.cygwin.com/</span></a><br />
5:<a title="http://chinyi.ncit.edu.tw/~peterju/cygwin.html" href="http://chinyi.ncit.edu.tw/~peterju/cygwin.html" target="_blank"><span style="text-decoration: underline;">http://chinyi.ncit.edu.tw/~peterju/cygwin.html</span></a><br />
6:<a title="http://cygnome.sourceforge.net/" href="http://cygnome.sourceforge.net/" target="_blank"><span style="text-decoration: underline;">http://cygnome.sourceforge.net/</span></a><br />
<a title="http://xlivecd.indiana.edu/" href="http://xlivecd.indiana.edu/" target="_blank"><span style="text-decoration: underline;">http://xlivecd.indiana.edu/</span></a></p>
</div>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/07/cygwin%e7%9a%84%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Control.Invoke和BeginInvoke的区别</title>
		<link>http://cq-cser.cn/2010/06/control-invoke-begininvoke/</link>
		<comments>http://cq-cser.cn/2010/06/control-invoke-begininvoke/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 18:59:47 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[invoke]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1253</guid>
		<description><![CDATA[Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。 Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。 以下为实际应用中碰到的问题，在主线程中启动一个线程，然后在这个线程中启动serviceForm,然而在线程启动后，往serviceForm发送指令，serviceForm.IsHandleCreated老是报serviceForm = null,无法执行指令，采用延时的办法可以解决此问题，但不是高效的办法，后来在serviceForm.Load += new EventHandler(serviceForm_Load);serviceForm_Load事件中添加指令，发送成功。主要原因还是多线程所致。 SatirServiceForm serviceForm; Thread serviceFormThread; protected void Init() { serviceFormThread = new Thread(MainFormMessageThread); serviceFormThread.Name = &#8220;ServiceThread&#8221;; serviceFormThread.Start(); } protected void MainFormMessageThread() { if (serviceForm == null) { serviceForm = new SatirServiceForm(); serviceForm.Load += new EventHandler(serviceForm_Load); //serviceForm.RecvedCmd += new EventHandler(OnServiceRecvedCmd); } Application.Run(serviceForm); } [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2010/03/%e5%90%af%e5%8a%a8%e6%8e%a7%e5%88%b6%e9%9d%a2%e6%9d%bf%e5%90%84%e9%80%89%e9%a1%b9c/' rel='bookmark' title='Permanent Link: 启动控制面板各选项:c#'>启动控制面板各选项:c#</a></li>
<li><a href='http://cq-cser.cn/2010/04/crossthreaddemo%e8%b7%a8%e7%ba%bf%e7%a8%8b%e5%ae%89%e5%85%a8%e7%bc%96%e7%a8%8borz/' rel='bookmark' title='Permanent Link: CrossThreadDemo跨线程安全编程/ORZ'>CrossThreadDemo跨线程安全编程/ORZ</a></li>
<li><a href='http://cq-cser.cn/2009/12/asp-net%e7%9a%84%e5%87%a0%e7%a7%8d%e9%a1%b5%e9%9d%a2%e4%bc%a0%e5%80%bc%e6%96%b9%e6%b3%95/' rel='bookmark' title='Permanent Link: asp.net的几种页面传值方法'>asp.net的几种页面传值方法</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;">Control.Invoke 方法 (Delegate) <strong>:</strong>在<strong>拥有</strong>此控件的基础窗口句柄的线程上<strong>执行</strong>指定的委托。</span></p>
<p><span style="color: #000000;">Control.BeginInvoke 方法 (Delegate) :在<strong>创建</strong>控件的基础句柄所在线程上<strong>异步执行</strong>指定委托。<span id="more-1253"></span></span></p>
<p><span style="color: #000000;">以下为实际应用中碰到的问题，在主线程中启动一个线程，然后在这个线程中启动serviceForm,然而在线程启动后，往serviceForm发送指令，serviceForm.IsHandleCreated老是报serviceForm = null,无法执行指令，采用延时的办法可以解决此问题，但不是高效的办法，后来在serviceForm.Load += new EventHandler(serviceForm_Load);serviceForm_Load事件中添加指令，发送成功。主要原因还是多线程所致。</span></p>
<p><span style="color: #000000;">SatirServiceForm serviceForm;<br />
Thread serviceFormThread;</span></p>
<p><span style="color: #000000;">protected void Init()<br />
{<br />
serviceFormThread = new Thread(MainFormMessageThread);<br />
serviceFormThread.Name = &#8220;ServiceThread&#8221;;<br />
serviceFormThread.Start();<br />
}</span></p>
<p><span style="color: #000000;">protected void MainFormMessageThread()<br />
{<br />
if (serviceForm == null)<br />
{<br />
serviceForm = new SatirServiceForm();<br />
serviceForm.Load += new EventHandler(serviceForm_Load);<br />
//serviceForm.RecvedCmd += new EventHandler(OnServiceRecvedCmd);</span></p>
<p><span style="color: #000000;">}<br />
Application.Run(serviceForm);<br />
}</span></p>
<p><span style="color: #000000;">void serviceForm_Load(object sender, EventArgs e)<br />
{<br />
SendCommand(InfraOnlineCmd.Start, 0);<br />
SendCommand(InfraOnlineCmd.AutoAjust, 0);<br />
}</span></p>
<p><span style="color: #000000;">protected override void SendCommand(InfraOnlineCmd cmd, object param)<br />
{<br />
if (param != null &amp;&amp; param is int)<br />
this.param = (int)param;</span></p>
<p><span style="color: #000000;">if (serviceForm.IsHandleCreated)<br />
{<br />
serviceForm.BeginInvoke(new DCmdHandler(ExecuteCmd), cmd);<br />
}<br />
}</span></p>
<p><span style="color: #000000;">以下ZT From:<a href="http://blog.163.com/kjpt126@126/blog/static/48940426200824103658846/" target="_blank"><span style="color: #3c910d;">http://blog.163.com/kjpt126@126/blog/static/48940426200824103658846/</span></a></span></p>
<p><span style="color: #000000;">Control的Invoke和BeginInvoke</span></p>
<p>近日，被Control的Invoke和BeginInvoke搞的头大，就查了些相关的资料，整理如下。感谢这篇文章对我的理解<span style="color: #000000;">Invoke和BeginInvoke的真正含义 。</span></p>
<p>(一）Control的Invoke和BeginInvoke</p>
<p>我们要基于以下认识：</p>
<p>（1）Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的。</p>
<p>（2）Control的Invoke和BeginInvoke的参数为delegate，委托的方法是在Control的线程上执行的，也就是我们平时所说的UI线程。</p>
<p>我们以代码(一)来看(Control的Invoke)</p>
<p>private delegate void InvokeDelegate();</p>
<p>private void InvokeMethod(){</p>
<p>//C代码段</p>
<p>}</p>
<p>private void butInvoke_Click(object sender, EventArgs e) {</p>
<p>//A代码段&#8230;&#8230;.</p>
<p>this.Invoke(new InvokeDelegate(InvokeMethod));</p>
<p>//B代码段&#8230;&#8230;</p>
<p>}</p>
<p>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p>A&#8212;&#8212;&gt;C&#8212;&#8212;&#8212;&#8212;&#8212;-&gt;B</p>
<p>解释：(1)A在UI线程上执行完后，开始Invoke，Invoke是同步</p>
<p>(2)代码段B并不执行，而是立即在UI线程上执行InvokeMethod方法，即代码段C。</p>
<p>(3)InvokeMethod方法执行完后，代码段C才在UI线程上继续执行。</p>
<p>看看代码(二)，Control的BeginInvoke</p>
<p>private delegate void BeginInvokeDelegate();</p>
<p>private void BeginInvokeMethod(){</p>
<p>//C代码段</p>
<p>}</p>
<p>private void butBeginInvoke_Click(object sender, EventArgs e) {</p>
<p>//A代码段&#8230;&#8230;.</p>
<p>this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));</p>
<p>//B代码段&#8230;&#8230;</p>
<p>}</p>
<p>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p>A&#8212;&#8212;&#8212;&#8211;&gt;B&#8212;&#8212;&#8212;&#8212;&#8212;&gt;C慎重，这个只做参考。。。。。，我也不肯定执行顺序，如果有哪位达人知道的话请告知。</p>
<p>解释：：(1)A在UI线程上执行完后，开始BeginInvoke，BeginInvoke是异步</p>
<p>(2)InvokeMethod方法，即代码段C不会执行，而是立即在UI线程上执行代码段B。</p>
<p>(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后)，InvokeMethod方法，即代码段C才在UI线程上继续执行。</p>
<p>由此，我们知道：</p>
<p>Control的Invoke和BeginInvoke的委托方法是在主线程，即UI线程上执行的。也就是说如果你的委托方法用来取花费时间长的数据，然后更新界面什么的，千万别在UI线程上调用Control.Invoke和Control.BeginInvoke，因为这些是依然阻塞UI线程的，造成界面的假死。</p>
<p>那么，这个异步到底是什么意思呢?</p>
<p>异步是指相对于调用BeginInvoke的线程异步，而不是相对于UI线程异步，你在UI线程上调用BeginInvoke ，当然不行了。－－－－摘自&#8221;Invoke和BeginInvoke的真正涵义&#8221;一文中的评论。</p>
<p>BeginInvoke的原理是将调用的方法Marshal成消息，然后调用Win32 API中的RegisterWindowMessage()向UI窗口发送消息。－－－－摘自&#8221;Invoke和BeginInvoke的真正涵义&#8221;一文中的评论。</p>
<p>(二)我们用Thread来调用BeginInvoke和Invoke</p>
<p>我们开一个线程，让线程执行一些耗费时间的操作，然后再用Control.Invoke和Control.BeginInvoke回到用户UI线程，执行界面更新。</p>
<p>代码(三) Thread调用Control的Invoke</p>
<p>private Thread invokeThread;</p>
<p>private delegate void invokeDelegate();</p>
<p>private void StartMethod(){</p>
<p>//C代码段&#8230;&#8230;</p>
<p>Control.Invoke(new invokeDelegate(invokeMethod));</p>
<p>//D代码段&#8230;&#8230;</p>
<p>}</p>
<p>private void invokeMethod(){</p>
<p>//E代码段</p>
<p>}</p>
<p>private void butInvoke_Click(object sender, EventArgs e) {</p>
<p>//A代码段&#8230;&#8230;.</p>
<p>invokeThread = new Thread(new ThreadStart(StartMethod));</p>
<p>invokeThread.Start();</p>
<p>//B代码段&#8230;&#8230;</p>
<p>}</p>
<p>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p>A&#8212;&#8212;&gt;(Start一开始B和StartMethod的C就同时执行)&#8212;-&gt;(C执行完了，不管B有没有执行完，invokeThread把消息封送(invoke)给UI线程，然后自己等待)&#8212;-&gt;UI线程处理完butInvoke_Click消息后，处理invokeThread封送过来的消息，执行invokeMethod方法，即代码段E，处理往后UI线程切换到invokeThread线程。</p>
<p>这个Control.Invoke是相对于invokeThread线程同步的，阻止了其运行。</p>
<p><img title="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" src="http://www.cnblogs.com/images/cnblogs_com/whssunboy/invoke.JPG" border="0" alt="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" /></p>
<p>解释：</p>
<p>1。UI执行A</p>
<p>2。UI开线程InvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程invokeThread上。</p>
<p>3。invokeThread封送消息给UI，然后自己等待，UI处理完消息后，处理invokeThread封送的消息，即代码段E</p>
<p>4。UI执行完E后，转到线程invokeThread上，invokeThread线程执行代码段D</p>
<p>代码(四) Thread调用Control的BeginInvoke</p>
<p>private Thread beginInvokeThread;</p>
<p>private delegate void beginInvokeDelegate();</p>
<p>private void StartMethod(){</p>
<p>//C代码段&#8230;&#8230;</p>
<p>Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod));</p>
<p>//D代码段&#8230;&#8230;</p>
<p>}</p>
<p>private void beginInvokeMethod(){</p>
<p>//E代码段</p>
<p>}</p>
<p>private void butBeginInvoke_Click(object sender, EventArgs e) {</p>
<p>//A代码段&#8230;&#8230;.</p>
<p>beginInvokeThread = new Thread(new ThreadStart(StartMethod));</p>
<p>beginInvokeThread .Start();</p>
<p>//B代码段&#8230;&#8230;</p>
<p>}</p>
<p>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p>A在UI线程上执行&#8212;&#8211;&gt;beginInvokeThread线程开始执行，UI继续执行代码段B，并发地invokeThread执行代码段C&#8212;&#8212;&#8212;&#8212;&#8211;&gt;不管UI有没有执行完代码段B，这时beginInvokeThread线程把消息封送给UI，单自己并不等待，继续向下执行&#8212;&#8212;&#8211;&gt;UI处理完butBeginInvoke_Click消息后，处理beginInvokeThread线程封送过来的消息。</p>
<p><img title="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" src="http://www.cnblogs.com/images/cnblogs_com/whssunboy/beginInvoke.JPG" border="0" alt="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" /></p>
<p>解释：</p>
<p>1。UI执行A</p>
<p>2。UI开线程beginInvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程beginInvokeThread上。</p>
<p>3。beginInvokeThread封送消息给UI，然后自己继续执行代码D，UI处理完消息后，处理invokeThread封送的消息，即代码段E</p>
<p>有点疑问：如果UI先执行完毕，是不是有可能过了段时间beginInvokeThread才把消息封送给UI，然后UI才继续执行封送的消息E。如图浅绿的部分。</p>
<p>Control的BeginInvoke是相对于调用它的线程，即beginInvokeThread相对是异步的。</p>
<p>因此，我们可以想到。如果要异步取耗费长时间的数据，比如从数据库中读大量数据，我们应该这么做。</p>
<p>(1)如果你想阻止调用线程，那么调用代码(三)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。</p>
<p>(2)如果你不想阻止调用线程，那么调用代码(四)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。</p>
<p><span class="Apple-style-span" style="line-height: 20px; font-family: Georgia; font-size: 12px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;"><span style="line-height: normal;"> </span></span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;"><span style="line-height: normal;"> </span></span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;"><span style="line-height: normal;">Control.Invoke 方法 (Delegate)</span> <strong style="line-height: normal;">:</strong>在<strong style="line-height: normal;">拥有</strong>此控件的基础窗口句柄的线程上<strong style="line-height: normal;">执行</strong>指定的委托。</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;"><span style="line-height: normal;">Control.BeginInvoke 方法 (Delegate)</span> :在<strong style="line-height: normal;">创建</strong>控件的基础句柄所在线程上<strong style="line-height: normal;">异步执行</strong>指定委托。</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">以下为实际应用中碰到的问题，在主线程中启动一个线程，然后在这个线程中启动serviceForm,然而在线程启动后，往serviceForm发送指令，serviceForm.IsHandleCreated老是报serviceForm = null,无法执行指令，采用延时的办法可以解决此问题，但不是高效的办法，后来在serviceForm.Load += new EventHandler(serviceForm_Load);serviceForm_Load事件中添加指令，发送成功。主要原因还是多线程所致。</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">SatirServiceForm serviceForm;<br style="line-height: normal;" />Thread serviceFormThread;</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">protected void Init()<br style="line-height: normal;" />{<br style="line-height: normal;" />serviceFormThread = new Thread(MainFormMessageThread);<br style="line-height: normal;" />serviceFormThread.Name = &#8220;ServiceThread&#8221;;<br style="line-height: normal;" />serviceFormThread.Start();<br style="line-height: normal;" />}</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">protected void MainFormMessageThread()<br style="line-height: normal;" />{<br style="line-height: normal;" />if (serviceForm == null)<br style="line-height: normal;" />{<br style="line-height: normal;" />serviceForm = new SatirServiceForm();<br style="line-height: normal;" />serviceForm.Load += new EventHandler(serviceForm_Load);<br style="line-height: normal;" />//serviceForm.RecvedCmd += new EventHandler(OnServiceRecvedCmd);</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">}<br style="line-height: normal;" />Application.Run(serviceForm);<br style="line-height: normal;" />}</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">void serviceForm_Load(object sender, EventArgs e)<br style="line-height: normal;" />{<br style="line-height: normal;" />SendCommand(InfraOnlineCmd.Start, 0);<br style="line-height: normal;" />SendCommand(InfraOnlineCmd.AutoAjust, 0);<br style="line-height: normal;" />}</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">protected override void SendCommand(InfraOnlineCmd cmd, object param)<br style="line-height: normal;" />{<br style="line-height: normal;" />if (param != null &amp;&amp; param is int)<br style="line-height: normal;" />this.param = (int)param;</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">if (serviceForm.IsHandleCreated)<br style="line-height: normal;" />{<br style="line-height: normal;" />serviceForm.BeginInvoke(new DCmdHandler(ExecuteCmd), cmd);<br style="line-height: normal;" />}<br style="line-height: normal;" />}</span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">以下ZT From:<a style="line-height: 20px; font-family: Georgia; color: #be0d5d; font-size: 12px; text-decoration: none;" href="http://blog.163.com/kjpt126@126/blog/static/48940426200824103658846/" target="_blank"><span style="line-height: normal; color: #3c910d;">http://blog.163.com/kjpt126@126/blog/static/48940426200824103658846/</span></a></span></p>
<p style="line-height: normal; text-indent: 2em;"><span style="line-height: normal; color: #000000;">Control的Invoke和BeginInvoke</span></p>
<p style="line-height: normal; text-indent: 2em;">近日，被Control的Invoke和BeginInvoke搞的头大，就查了些相关的资料，整理如下。感谢这篇文章对我的理解<span style="line-height: normal; background-color: #ffffff; color: #000000;">Invoke和BeginInvoke的真正含义 。</span></p>
<p style="line-height: normal; text-indent: 2em;">(一）Control的Invoke和BeginInvoke</p>
<p style="line-height: normal; text-indent: 2em;">我们要基于以下认识：</p>
<p style="line-height: normal; text-indent: 2em;">（1）Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的。</p>
<p style="line-height: normal; text-indent: 2em;">（2）Control的Invoke和BeginInvoke的参数为delegate，委托的方法是在Control的线程上执行的，也就是我们平时所说的UI线程。</p>
<p style="line-height: normal; text-indent: 2em;">我们以代码(一)来看(Control的Invoke)</p>
<p style="line-height: normal; text-indent: 2em;">private delegate void InvokeDelegate();</p>
<p style="line-height: normal; text-indent: 2em;">private void InvokeMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//C代码段</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void butInvoke_Click(object sender, EventArgs e) {</p>
<p style="line-height: normal; text-indent: 2em;">//A代码段&#8230;&#8230;.</p>
<p style="line-height: normal; text-indent: 2em;">this.Invoke(new InvokeDelegate(InvokeMethod));</p>
<p style="line-height: normal; text-indent: 2em;">//B代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p style="line-height: normal; text-indent: 2em;">A&#8212;&#8212;&gt;C&#8212;&#8212;&#8212;&#8212;&#8212;-&gt;B</p>
<p style="line-height: normal; text-indent: 2em;">解释：(1)A在UI线程上执行完后，开始Invoke，Invoke是同步</p>
<p style="line-height: normal; text-indent: 2em;">(2)代码段B并不执行，而是立即在UI线程上执行InvokeMethod方法，即代码段C。</p>
<p style="line-height: normal; text-indent: 2em;">(3)InvokeMethod方法执行完后，代码段C才在UI线程上继续执行。</p>
<p style="line-height: normal; text-indent: 2em;">看看代码(二)，Control的BeginInvoke</p>
<p style="line-height: normal; text-indent: 2em;">private delegate void BeginInvokeDelegate();</p>
<p style="line-height: normal; text-indent: 2em;">private void BeginInvokeMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//C代码段</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void butBeginInvoke_Click(object sender, EventArgs e) {</p>
<p style="line-height: normal; text-indent: 2em;">//A代码段&#8230;&#8230;.</p>
<p style="line-height: normal; text-indent: 2em;">this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));</p>
<p style="line-height: normal; text-indent: 2em;">//B代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p style="line-height: normal; text-indent: 2em;">A&#8212;&#8212;&#8212;&#8211;&gt;B&#8212;&#8212;&#8212;&#8212;&#8212;&gt;C慎重，这个只做参考。。。。。，我也不肯定执行顺序，如果有哪位达人知道的话请告知。</p>
<p style="line-height: normal; text-indent: 2em;">解释：：(1)A在UI线程上执行完后，开始BeginInvoke，BeginInvoke是异步</p>
<p style="line-height: normal; text-indent: 2em;">(2)InvokeMethod方法，即代码段C不会执行，而是立即在UI线程上执行代码段B。</p>
<p style="line-height: normal; text-indent: 2em;">(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后)，InvokeMethod方法，即代码段C才在UI线程上继续执行。</p>
<p style="line-height: normal; text-indent: 2em;">由此，我们知道：</p>
<p style="line-height: normal; text-indent: 2em;">Control的Invoke和BeginInvoke的委托方法是在主线程，即UI线程上执行的。也就是说如果你的委托方法用来取花费时间长的数据，然后更新界面什么的，千万别在UI线程上调用Control.Invoke和Control.BeginInvoke，因为这些是依然阻塞UI线程的，造成界面的假死。</p>
<p style="line-height: normal; text-indent: 2em;">那么，这个异步到底是什么意思呢?</p>
<p style="line-height: normal; text-indent: 2em;">异步是指相对于调用BeginInvoke的线程异步，而不是相对于UI线程异步，你在UI线程上调用BeginInvoke ，当然不行了。－－－－摘自&#8221;Invoke和BeginInvoke的真正涵义&#8221;一文中的评论。</p>
<p style="line-height: normal; text-indent: 2em;">BeginInvoke的原理是将调用的方法Marshal成消息，然后调用Win32 API中的RegisterWindowMessage()向UI窗口发送消息。－－－－摘自&#8221;Invoke和BeginInvoke的真正涵义&#8221;一文中的评论。</p>
<p style="line-height: normal; text-indent: 2em;">(二)我们用Thread来调用BeginInvoke和Invoke</p>
<p style="line-height: normal; text-indent: 2em;">我们开一个线程，让线程执行一些耗费时间的操作，然后再用Control.Invoke和Control.BeginInvoke回到用户UI线程，执行界面更新。</p>
<p style="line-height: normal; text-indent: 2em;">代码(三) Thread调用Control的Invoke</p>
<p style="line-height: normal; text-indent: 2em;">private Thread invokeThread;</p>
<p style="line-height: normal; text-indent: 2em;">private delegate void invokeDelegate();</p>
<p style="line-height: normal; text-indent: 2em;">private void StartMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//C代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">Control.Invoke(new invokeDelegate(invokeMethod));</p>
<p style="line-height: normal; text-indent: 2em;">//D代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void invokeMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//E代码段</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void butInvoke_Click(object sender, EventArgs e) {</p>
<p style="line-height: normal; text-indent: 2em;">//A代码段&#8230;&#8230;.</p>
<p style="line-height: normal; text-indent: 2em;">invokeThread = new Thread(new ThreadStart(StartMethod));</p>
<p style="line-height: normal; text-indent: 2em;">invokeThread.Start();</p>
<p style="line-height: normal; text-indent: 2em;">//B代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p style="line-height: normal; text-indent: 2em;">A&#8212;&#8212;&gt;(Start一开始B和StartMethod的C就同时执行)&#8212;-&gt;(C执行完了，不管B有没有执行完，invokeThread把消息封送(invoke)给UI线程，然后自己等待)&#8212;-&gt;UI线程处理完butInvoke_Click消息后，处理invokeThread封送过来的消息，执行invokeMethod方法，即代码段E，处理往后UI线程切换到invokeThread线程。</p>
<p style="line-height: normal; text-indent: 2em;">这个Control.Invoke是相对于invokeThread线程同步的，阻止了其运行。</p>
<p style="line-height: normal; text-indent: 2em;"><img style="line-height: normal;" title="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" src="http://www.cnblogs.com/images/cnblogs_com/whssunboy/invoke.JPG" border="0" alt="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" /></p>
<p style="line-height: normal; text-indent: 2em;">解释：</p>
<p style="line-height: normal; text-indent: 2em;">1。UI执行A</p>
<p style="line-height: normal; text-indent: 2em;">2。UI开线程InvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程invokeThread上。</p>
<p style="line-height: normal; text-indent: 2em;">3。invokeThread封送消息给UI，然后自己等待，UI处理完消息后，处理invokeThread封送的消息，即代码段E</p>
<p style="line-height: normal; text-indent: 2em;">4。UI执行完E后，转到线程invokeThread上，invokeThread线程执行代码段D</p>
<p style="line-height: normal; text-indent: 2em;">代码(四) Thread调用Control的BeginInvoke</p>
<p style="line-height: normal; text-indent: 2em;">private Thread beginInvokeThread;</p>
<p style="line-height: normal; text-indent: 2em;">private delegate void beginInvokeDelegate();</p>
<p style="line-height: normal; text-indent: 2em;">private void StartMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//C代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod));</p>
<p style="line-height: normal; text-indent: 2em;">//D代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void beginInvokeMethod(){</p>
<p style="line-height: normal; text-indent: 2em;">//E代码段</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">private void butBeginInvoke_Click(object sender, EventArgs e) {</p>
<p style="line-height: normal; text-indent: 2em;">//A代码段&#8230;&#8230;.</p>
<p style="line-height: normal; text-indent: 2em;">beginInvokeThread = new Thread(new ThreadStart(StartMethod));</p>
<p style="line-height: normal; text-indent: 2em;">beginInvokeThread .Start();</p>
<p style="line-height: normal; text-indent: 2em;">//B代码段&#8230;&#8230;</p>
<p style="line-height: normal; text-indent: 2em;">}</p>
<p style="line-height: normal; text-indent: 2em;">你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上</p>
<p style="line-height: normal; text-indent: 2em;">A在UI线程上执行&#8212;&#8211;&gt;beginInvokeThread线程开始执行，UI继续执行代码段B，并发地invokeThread执行代码段C&#8212;&#8212;&#8212;&#8212;&#8211;&gt;不管UI有没有执行完代码段B，这时beginInvokeThread线程把消息封送给UI，单自己并不等待，继续向下执行&#8212;&#8212;&#8211;&gt;UI处理完butBeginInvoke_Click消息后，处理beginInvokeThread线程封送过来的消息。</p>
<p style="line-height: normal; text-indent: 2em;"><img style="line-height: normal;" title="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" src="http://www.cnblogs.com/images/cnblogs_com/whssunboy/beginInvoke.JPG" border="0" alt="c Invoke和BeginInvoke 区别 - Dragon - everyday happy" /></p>
<p style="line-height: normal; text-indent: 2em;">解释：</p>
<p style="line-height: normal; text-indent: 2em;">1。UI执行A</p>
<p style="line-height: normal; text-indent: 2em;">2。UI开线程beginInvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程beginInvokeThread上。</p>
<p style="line-height: normal; text-indent: 2em;">3。beginInvokeThread封送消息给UI，然后自己继续执行代码D，UI处理完消息后，处理invokeThread封送的消息，即代码段E</p>
<p style="line-height: normal; text-indent: 2em;">有点疑问：如果UI先执行完毕，是不是有可能过了段时间beginInvokeThread才把消息封送给UI，然后UI才继续执行封送的消息E。如图浅绿的部分。</p>
<p style="line-height: normal; text-indent: 2em;">Control的BeginInvoke是相对于调用它的线程，即beginInvokeThread相对是异步的。</p>
<p style="line-height: normal; text-indent: 2em;">因此，我们可以想到。如果要异步取耗费长时间的数据，比如从数据库中读大量数据，我们应该这么做。</p>
<p style="line-height: normal; text-indent: 2em;">(1)如果你想阻止调用线程，那么调用代码(三)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。</p>
<p style="line-height: normal; text-indent: 2em;">(2)如果你不想阻止调用线程，那么调用代码(四)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。</p>
<p style="line-height: normal; text-indent: 2em;"> </p>
<p></span></p>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2010/03/%e5%90%af%e5%8a%a8%e6%8e%a7%e5%88%b6%e9%9d%a2%e6%9d%bf%e5%90%84%e9%80%89%e9%a1%b9c/' rel='bookmark' title='Permanent Link: 启动控制面板各选项:c#'>启动控制面板各选项:c#</a></li>
<li><a href='http://cq-cser.cn/2010/04/crossthreaddemo%e8%b7%a8%e7%ba%bf%e7%a8%8b%e5%ae%89%e5%85%a8%e7%bc%96%e7%a8%8borz/' rel='bookmark' title='Permanent Link: CrossThreadDemo跨线程安全编程/ORZ'>CrossThreadDemo跨线程安全编程/ORZ</a></li>
<li><a href='http://cq-cser.cn/2009/12/asp-net%e7%9a%84%e5%87%a0%e7%a7%8d%e9%a1%b5%e9%9d%a2%e4%bc%a0%e5%80%bc%e6%96%b9%e6%b3%95/' rel='bookmark' title='Permanent Link: asp.net的几种页面传值方法'>asp.net的几种页面传值方法</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/06/control-invoke-begininvoke/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>dev c++下连接MYSQL</title>
		<link>http://cq-cser.cn/2010/06/dev-c%e4%b8%8b%e8%bf%9e%e6%8e%a5mysql/</link>
		<comments>http://cq-cser.cn/2010/06/dev-c%e4%b8%8b%e8%bf%9e%e6%8e%a5mysql/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 04:25:14 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[MYSQL]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1243</guid>
		<description><![CDATA[挂机锁(最终版) 绿色纯净免安装单文件版 2C++封装类+1C例子，DEV下编译通过，记得装DEV.PACKcmysql.rar(自己重命名，RAR格式)http://16hot.blog.isyi.com/post/1/144 在网上搜索到一些资料，按照上面提示的方法。 已经解决了问题。 因为我使用的是Dev-C++开发工具。他使用的是gcc编译器。 而MySQL提供的Windows For C连接库不支持gcc 、 CygWin 、MinGW等。 因此在编译连接的时候，就会出现错误提示。 解决方法： 1 、安装好MySQL （如果不愿意安装，那找个libmySQL.dll文件也可以） 2、下载Pexports工具 3、转换操作： pexports libmySQL.dll &#62; libmySQL.def 4、使用Cygwin的 dlltool转换成为libmysql.a文件。dlltool &#8211;input-def libmySQL.def &#8211;dllname libmySQL.dll &#8211;output-lib libmysql.a -k 5、尝试是否成功： gcc -o mysqldemo mysqldemo.o &#60;path to libmysql.a&#62; 如果再出现象mysql_connect@xx （xx是数字）的错误提示。就执行第6步。 6、修改libmysql.def文件，给mysql_connect加上@xx，即： mysql_connect@xx 7、重做第4步 8、然后尝试第5步，如果还是出现错误提示。就作第6步。一直到没有错误为止。 //&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; 第一步：指定mysql.h等包含文件的路径 在Dev-C++里，打开项目，Alt+P 打开项目属性。 在“文件/目录” -&#62; “包含文件目录”添加你存放mysql头文件的路径。 第二步：生成libmySQL.a文件 参考我上面的文章，必须将libmySQL.dll转换成为libmySQL.a [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><a href="http://cq-cser.cn/wp-content/uploads/2010/06/挂机锁最终版-绿色纯净免安装单文件版.exe">挂机锁(最终版) 绿色纯净免安装单文件版</a><br />
2C++封装类+1C例子，DEV下编译通过，记得装DEV.PACK<a href="http://cq-cser.cn/wp-content/uploads/2010/06/cmysql.rar_.exe">cmysql.rar</a>(自己重命名，RAR格式)<a href="http://16hot.blog.isyi.com/post/1/144"><span id="more-1243"></span>http://16hot.blog.isyi.com/post/1/144</a></p>
<p>在网上搜索到一些资料，按照上面提示的方法。</p>
<p>已经解决了问题。</p>
<p>因为我使用的是Dev-C++开发工具。他使用的是gcc编译器。</p>
<p>而MySQL提供的Windows For C连接库不支持gcc 、 CygWin 、MinGW等。</p>
<p>因此在编译连接的时候，就会出现错误提示。</p>
<p>解决方法：</p>
<p>1 、安装好MySQL （如果不愿意安装，那找个libmySQL.dll文件也可以）</p>
<p>2、下载Pexports工具</p>
<p>3、转换操作： pexports libmySQL.dll &gt; libmySQL.def</p>
<p>4、使用Cygwin的 dlltool转换成为libmysql.a文件。dlltool &#8211;input-def libmySQL.def &#8211;dllname libmySQL.dll &#8211;output-lib libmysql.a -k</p>
<p>5、尝试是否成功： gcc -o mysqldemo mysqldemo.o &lt;path to libmysql.a&gt;</p>
<p>如果再出现象<a href="mailto:mysql_connect@xx">mysql_connect@xx</a> （xx是数字）的错误提示。就执行第6步。</p>
<p>6、修改libmysql.def文件，给mysql_connect加上@xx，即： <a href="mailto:mysql_connect@xx">mysql_connect@xx</a></p>
<p>7、重做第4步</p>
<p>8、然后尝试第5步，如果还是出现错误提示。就作第6步。一直到没有错误为止。</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>第一步：指定mysql.h等包含文件的路径<br />
在Dev-C++里，打开项目，Alt+P 打开项目属性。<br />
在“文件/目录” -&gt; “包含文件目录”添加你存放mysql头文件的路径。</p>
<p>第二步：生成libmySQL.a文件<br />
参考我上面的文章，必须将libmySQL.dll转换成为libmySQL.a ，编译器才能认。<br />
因为mysql自带的libmySQL.dll是给微软的VC++使用的。:(<br />
我也因为这个问题，搞了N久。</p>
<p>第三步：指定libmySQL.a的路径<br />
同样是在项目属性里。在“参数”页，有个“连接器”框。在下面有“加入库或者对象”，点击打开，到你存放libmySQL.a文件的目录，选择它。<br />
然后“确定”退出属性窗口，再编译。</p>
<p>这时候会出现一些函数提示如mysql_query@8 不存在等。需要参考上面文章，一步一步改，生成新的libmySQL.a文件。<br />
直到成功为止。</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/06/dev-c%e4%b8%8b%e8%bf%9e%e6%8e%a5mysql/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>a star algorithm/A* algorithm</title>
		<link>http://cq-cser.cn/2010/06/a-star-algorithma-algorithm/</link>
		<comments>http://cq-cser.cn/2010/06/a-star-algorithma-algorithm/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 07:20:44 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[a star]]></category>
		<category><![CDATA[A*]]></category>
		<category><![CDATA[algorithm]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1219</guid>
		<description><![CDATA[A star算法在静态路网中的应用 AStar  #include &#60;string.h&#62; #include&#60;stdio.h &#62; #define MAPW 21 #define MAPH 21 //a star path finding take 2 //create a list struct for the path struct list_s {  int x;  int y;  int f; } path[10000]; struct NODE {  int walkable;  int onopen;  int onclosed;  int g;  int h;  int f;  int parentx;  int [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2010/03/%e5%a4%9a%e5%8f%89%e6%a0%91-jsonc/' rel='bookmark' title='Permanent Link: 多叉树 JSON:C#'>多叉树 JSON:C#</a></li>
<li><a href='http://cq-cser.cn/2010/02/%e5%be%ae%e8%bd%af%e7%9a%8422%e9%81%93%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e7%ae%97%e6%b3%95%e9%9d%a2%e8%af%95%e9%a2%98/' rel='bookmark' title='Permanent Link: 微软的22道数据结构算法面试题'>微软的22道数据结构算法面试题</a></li>
<li><a href='http://cq-cser.cn/2010/01/%e7%94%a8htmlparser%e5%88%86%e6%9e%90%e5%b9%b6%e6%8a%bd%e5%8f%96%e6%ad%a3%e6%96%87zz/' rel='bookmark' title='Permanent Link: 用htmlparser分析并抽取正文[zz]'>用htmlparser分析并抽取正文[zz]</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://baike.baidu.com/image/b6045da9af0672c51e17a2ff" target="_blank"></a><a href="http://cq-cser.cn/wp-content/uploads/2010/06/b6045da9af0672c51e17a2ff.jpg"><img class="alignnone size-full wp-image-1241" title="b6045da9af0672c51e17a2ff" src="http://cq-cser.cn/wp-content/uploads/2010/06/b6045da9af0672c51e17a2ff.jpg" alt="" width="200" height="182" /></a><span id="more-1219"></span></p>
<h3>A star算法在静态路网中的应用</h3>
<p><a href="http://cq-cser.cn/wp-content/uploads/2010/06/AStar.zip">AStar</a> </p>
<p>#include &lt;string.h&gt;<br />
#include&lt;stdio.h &gt;<br />
#define MAPW 21<br />
#define MAPH 21<br />
//a star path finding take 2</p>
<p>//create a list struct for the path<br />
struct list_s<br />
{<br />
 int x;<br />
 int y;<br />
 int f;<br />
} path[10000];</p>
<p>struct NODE<br />
{<br />
 int walkable;</p>
<p> int onopen;<br />
 int onclosed;</p>
<p> int g;<br />
 int h;<br />
 int f;</p>
<p> int parentx;<br />
 int parenty;<br />
} node[MAPW][MAPH];</p>
<p>void initnodes()<br />
{<br />
 int x,y;</p>
<p> for(x=0;x&lt;MAPW;x++)<br />
 {<br />
  for(y=0;y&lt;MAPH;y++)<br />
  {<br />
   node[x][y].walkable = getpixel(map,x,y);<br />
   node[x][y].onopen = FALSE;<br />
   node[x][y].onclosed = FALSE;<br />
   node[x][y].g = 0;<br />
   node[x][y].h = 0;<br />
   node[x][y].f = 0;<br />
   node[x][y].parentx = NULL;<br />
   node[x][y].parenty = NULL;<br />
  }<br />
 }<br />
}</p>
<p>int *findpath(int startx, int starty, int endx, int endy)<br />
{<br />
 int x=0,y=0; // for running through the nodes<br />
 int dx,dy; // for the 8 squares adjacent to each node<br />
 int currentx=startx, currenty=starty;<br />
 int lowestf=10000; // start with the lowest being the highest</p>
<p> // add starting node to open list<br />
 node[startx][starty].onopen = TRUE;</p>
<p> while (!node[currentx][currenty].onclosed) //stop when the current node is on the closed list<br />
 {<br />
  //look for lowest F cost node on open list &#8211; this becomes the current node<br />
  for(x=0;x&lt;MAPW;x++)<br />
  {<br />
   for(y=0;y&lt;MAPY;y++)<br />
   {<br />
    node[x][y].f = node[x][y].g + node[x][y].h;<br />
    if(node[x][y].onopen)<br />
    if(node[x][y].f&lt;lowestf) { currentx = x; currenty = y; lowestf = node[x][y].f;}<br />
   }<br />
  }<br />
  // we found it, so now put that node on the closed list<br />
  node[currentx][currenty].onopen = FALSE;<br />
  node[currentx][currenty].onclosed = TRUE;</p>
<p>  // for each of the 8 adjacent node<br />
  for(dx=-1;dx&lt;=1;dx++)<br />
  {<br />
   for(dy=-1;dy&lt;=1;dy++)<br />
   {<br />
    // if its walkable and not on the closed list<br />
    if(node[currentx+dx][currenty+dy].walkable || !node[currentx+dx][currenty+dy].onclosed)<br />
    {<br />
     //if its not on open list<br />
     if(!node[currentx+dx][currenty+dy].onopen)<br />
     {<br />
      //add it to open list<br />
      node[currentx+dx][currenty+dy].onopen = TRUE; node[currentx+dx][currenty+dy].onclosed = FALSE;<br />
      //make the current node its parent<br />
      node[currentx+dx][currenty+dy].parentx = currentx;<br />
      node[currentx+dx][currenty+dy].parenty = currenty;<br />
      //work out G<br />
      if(dx!=0 &amp;&amp; dy!=0) node[currentx+dx][currenty+dy].g = 14; // diagonals cost 14<br />
      else node[currentx+dx][currenty+dy].g = 10; // straights cost 10<br />
      //work out H<br />
      //MANHATTAN METHOD<br />
      node[currentx+dx][currenty+dy].h = abs(endx-currentx+dy + endy-currenty+dy) * 10;<br />
     }<br />
     //otherwise it is on the open list<br />
     else<br />
     {<br />
      if(dx==0 || dy==0) // if its not a diagonal<br />
       if(node[currentx+dx][currenty+dy].g!=10) //and it was previously<br />
       {<br />
        node[currentx+dx][currenty+dy].g = 10; // straight score 10<br />
        //change its parent because its a shorter distance<br />
        node[currentx+dx][currenty+dy].parentx = currentx;<br />
        node[currentx+dx][currenty+dy].parenty = currenty;<br />
        //recalc H<br />
        node[currentx+dx][currenty+dy].h = abs(endx-currentx+dy + endy-currenty+dy) * 10;<br />
        //recalc F<br />
        node[currentx+dx][currenty+dy].f = node[currentx+dx][currenty+dy].g + node[currentx+dx][currenty+dy].h;<br />
       }<br />
     <br />
     }//end else<br />
    }// end if walkable and not on closed list<br />
   }<br />
  }//end for each 8 adjacent node<br />
 }//end while</p>
<p> //put the parent nodes into a list ordered from highest to lowest f value<br />
 //first count how many there are<br />
 int count=0;<br />
 for(x=0;x&lt;MAPW;x++)<br />
 {<br />
  for(y=0;y&lt;MAPY;y++)<br />
  {<br />
   if(node[x][y].onclosed) { path[count].x = x; path[count].y = y; path[count].f = node[x][y].f; count++; }<br />
  }<br />
 }<br />
 //sort them<br />
 qsort (path, count, sizeof(struct list_s), compare);</p>
<p> return &amp;path; //we&#8217;re done, return a pointer to the final path;<br />
}//end function<br />
//sorting stuff<br />
int compare (const struct list_s * a, const struct list_s * b)<br />
{<br />
  return ( a-&gt;f &#8211; b-&gt;f );<br />
}</p>
<p>主要搜索过程： 　　创建两个表，OPEN表保存所有已生成而未考察的节点，CLOSED表中记录已访问过的节点。 　　遍历当前节点的各个节点，将n节点放入CLOSE中，取n节点的子节点X,-&gt;算X的估价值-&gt; 　　While(OPEN!=NULL) 　　{ 　　从OPEN表中取估价值f最小的节点n; 　　if(n节点==目标节点) break; 　　else 　　{ 　　if(X in OPEN) 比较两个X的估价值f //注意是同一个节点的两个不同路径的估价值 　　if( X的估价值小于OPEN表的估价值 ) 　　更新OPEN表中的估价值; //取最小路径的估价值 　　if(X in CLOSE) 比较两个X的估价值 //注意是同一个节点的两个不同路径的估价值 　　if( X的估价值小于CLOSE表的估价值 ) 　　更新CLOSE表中的估价值; 把X节点放入OPEN //取最小路径的估价值 　　if(X not in both) 　　求X的估价值; 　　并将X插入OPEN表中; //还没有排序 　　} 　　将n节点插入CLOSE表中; 　　按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小，从最小路径的节点向下进行。</p>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2010/03/%e5%a4%9a%e5%8f%89%e6%a0%91-jsonc/' rel='bookmark' title='Permanent Link: 多叉树 JSON:C#'>多叉树 JSON:C#</a></li>
<li><a href='http://cq-cser.cn/2010/02/%e5%be%ae%e8%bd%af%e7%9a%8422%e9%81%93%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84%e7%ae%97%e6%b3%95%e9%9d%a2%e8%af%95%e9%a2%98/' rel='bookmark' title='Permanent Link: 微软的22道数据结构算法面试题'>微软的22道数据结构算法面试题</a></li>
<li><a href='http://cq-cser.cn/2010/01/%e7%94%a8htmlparser%e5%88%86%e6%9e%90%e5%b9%b6%e6%8a%bd%e5%8f%96%e6%ad%a3%e6%96%87zz/' rel='bookmark' title='Permanent Link: 用htmlparser分析并抽取正文[zz]'>用htmlparser分析并抽取正文[zz]</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/06/a-star-algorithma-algorithm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>基于索引的SQL语句优化</title>
		<link>http://cq-cser.cn/2010/05/%e5%9f%ba%e4%ba%8e%e7%b4%a2%e5%bc%95%e7%9a%84sql%e8%af%ad%e5%8f%a5%e4%bc%98%e5%8c%96/</link>
		<comments>http://cq-cser.cn/2010/05/%e5%9f%ba%e4%ba%8e%e7%b4%a2%e5%bc%95%e7%9a%84sql%e8%af%ad%e5%8f%a5%e4%bc%98%e5%8c%96/#comments</comments>
		<pubDate>Mon, 24 May 2010 14:25:08 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[索引]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1202</guid>
		<description><![CDATA[老文了 1 前言 2 2 总纲 2 3 降龙十八掌 3 第一掌避免对列的操作 3 第二掌避免不必要的类型转换 4 第三掌增加查询的范围限制 4 第四掌尽量去掉&#8221;IN&#8221;、&#8221;OR&#8221; 4 第五掌尽量去掉 &#8220;&#8221; 5 第六掌去掉Where子句中的IS NULL和IS NOT NULL 5 第七掌索引提高数据分布不均匀时查询效率 5 第八掌利用HINT强制指定索引 6 第九掌屏蔽无用索引 6 第十掌分解复杂查询，用常量代替变量 7 第十一掌 like子句尽量前端匹配 7 第十二掌用Case语句合并多重扫描 7 第十三掌使用nls_date_format 8 第十四掌使用基于函数的索引 8 第十五掌基于函数的索引要求等式匹配 9 第十六掌使用分区索引 9 第十七掌使用位图索引 9 第十八掌决定使用全表扫描还是使用索引 9 4 总结 10 1 [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2011/02/how-to-use-svmap/' rel='bookmark' title='Permanent Link: How to use svmap.'>How to use svmap.</a></li>
<li><a href='http://cq-cser.cn/2009/12/seo%e6%89%93%e6%89%8b/' rel='bookmark' title='Permanent Link: SEO打手'>SEO打手</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>老文了<br />
<span id="more-1202"></span><br />
1        前言        2<br />
2        总纲        2<br />
3        降龙十八掌        3<br />
第一掌避免对列的操作        3<br />
第二掌避免不必要的类型转换        4<br />
第三掌增加查询的范围限制        4<br />
第四掌尽量去掉&#8221;IN&#8221;、&#8221;OR&#8221;        4<br />
第五掌尽量去掉 &#8220;<>&#8221;        5<br />
第六掌去掉Where子句中的IS NULL和IS NOT NULL        5<br />
第七掌索引提高数据分布不均匀时查询效率        5<br />
第八掌利用HINT强制指定索引        6<br />
第九掌屏蔽无用索引        6<br />
第十掌分解复杂查询，用常量代替变量        7<br />
第十一掌 like子句尽量前端匹配        7<br />
第十二掌用Case语句合并多重扫描        7<br />
第十三掌使用nls_date_format        8<br />
第十四掌使用基于函数的索引        8<br />
第十五掌基于函数的索引要求等式匹配        9<br />
第十六掌使用分区索引        9<br />
第十七掌使用位图索引        9<br />
第十八掌决定使用全表扫描还是使用索引        9<br />
4        总结        10</p>
<p>1        前言<br />
客服业务受到SQL语句的影响非常大，在规模比较大的局点，往往因为一个小的SQL语句不够优化，导致数据库性能急剧下降，小型机idle所剩无几，应用服务器断连、超时，严重影响业务的正常运行。因此，称低效的SQL语句为客服业务的‘恶龙’并不过分。数据库的优化方法有很多种，在应用层来说，主要是基于索引的优化。本次秘笈根据实际的工作经验，在研发原来已有的方法的基础上，进行了一些扩充，总结了基于索引的SQL语句优化的降龙十八掌，希望有一天你能用其中一掌来驯服客服业务中横行的‘恶龙’。<br />
2        总纲<br />
l        建立必要的索引<br />
这次传授的降龙十八掌，总纲只有一句话：建立必要的索引，这就是后面降龙十八掌的内功基础。这一点看似容易实际却很难。难就难在如何判断哪些索引是必要的，哪些又是不必要的。判断的最终标准是看这些索引是否对我们的数据库性能有所帮助。具体到方法上，就必须熟悉数据库应用程序中的所有SQL语句，从中统计出常用的可能对性能有影响的部分SQL，分析、归纳出作为Where条件子句的字段及其组合方式；在这一基础上可以初步判断出哪些表的哪些字段应该建立索引。其次，必须熟悉应用程序。必须了解哪些表是数据操作频繁的表；哪些表经常与其他表进行连接；哪些表中的数据量可能很大；对于数据量大的表，其中各个字段的数据分布情况如何；等等。对于满足以上条件的这些表，必须重点关注，因为在这些表上的索引，将对SQL语句的性能产生举足轻重的影响。不过下面还是总结了一下降龙十八掌内功的入门基础，建立索引常用的规则如下：<br />
1、表的主键、外键必须有索引；<br />
2、数据量超过300的表应该有索引；<br />
3、经常与其他表进行连接的表，在连接字段上应该建立索引；<br />
4、经常出现在Where子句中的字段，特别是大表的字段，应该建立索引；<br />
5、索引应该建在选择性高的字段上；<br />
6、索引应该建在小字段上，对于大的文本字段甚至超长字段，不要建索引；<br />
7、复合索引的建立需要进行仔细分析；尽量考虑用单字段索引代替：<br />
   A、正确选择复合索引中的主列字段，一般是选择性较好的字段；<br />
   B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中？单字段查询是否极少甚至没有？如果是，则可以建立复合索引；否则考虑单字段索引；<br />
   C、如果复合索引中包含的字段经常单独出现在Where子句中，则分解为多个单字段索引；<br />
   D、如果复合索引所包含的字段超过3个，那么仔细考虑其必要性，考虑减少复合的字段；<br />
   E、如果既有单字段索引，又有这几个字段上的复合索引，一般可以删除复合索引；<br />
8、频繁进行数据操作的表，不要建立太多的索引；<br />
9、删除无用的索引，避免对执行计划造成负面影响；<br />
以上是一些普遍的建立索引时的判断依据。一言以蔽之，索引的建立必须慎重，对每个索引的必要性都应该经过仔细分析，要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处：在表上建立的每个索引都会增加存储开销，索引对于插入、删除、更新操作也会增加处理上的开销。另外，过多的复合索引，在有单字段索引的情况下，一般都是没有存在价值的；相反，还会降低数据增加删除时的性能，特别是对频繁更新的表来说，负面影响更大。<br />
3        降龙十八掌</p>
<p>第一掌避免对列的操作<br />
任何对列的操作都可能导致全表扫描，这里所谓的操作包括数据库函数、计算表达式等等，查询时要尽可能将操作移至等式的右边，甚至去掉函数。<br />
例1：下列SQL条件语句中的列都建有恰当的索引，但30万行数据情况下执行速度却非常慢：<br />
select * from record where  substrb(CardNo,1,4)=&#8217;5378&#8242;(13秒)<br />
select * from record where  amount/30< 1000（11秒）<br />
select * from record where  to_char(ActionTime,'yyyymmdd')='19991201'（10秒）<br />
由于where子句中对列的任何操作结果都是在SQL运行时逐行计算得到的，因此它不得不进行表扫描，而没有使用该列上面的索引；如果这些结果在查询编译时就能得到，那么就可以被SQL优化器优化，使用索引，避免表扫描，因此将SQL重写如下：<br />
select * from record where CardNo like  '5378%'（< 1秒）<br />
select * from record where amount  < 1000*30（< 1秒）<br />
select * from record where ActionTime= to_date ('19991201' ,'yyyymmdd')（< 1秒）<br />
差别是很明显的！</p>
<p>第二掌避免不必要的类型转换<br />
需要注意的是，尽量避免潜在的数据类型转换。如将字符型数据与数值型数据比较，ORACLE会自动将字符型用to_number()函数进行转换，从而导致全表扫描。<br />
例2：表tab1中的列col1是字符型（char)，则以下语句存在类型转换：<br />
select col1,col2 from tab1 where col1>10，<br />
应该写为： select col1,col2 from tab1 where col1>&#8217;10&#8242;。</p>
<p>第三掌增加查询的范围限制<br />
增加查询的范围限制，避免全范围的搜索。<br />
例3：以下查询表record 中时间ActionTime小于2001年3月1日的数据：<br />
        select * from record where ActionTime < to_date ('20010301' ,'yyyymm')<br />
查询计划表明，上面的查询对表进行全表扫描，如果我们知道表中的最早的数据为2001年1月1日，那么，可以增加一个最小时间，使查询在一个完整的范围之内。修改如下： select * from record where<br />
ActionTime < to_date ('20010301' ,'yyyymm')<br />
and   ActionTime > to_date (&#8217;20010101&#8242; ,&#8217;yyyymm&#8217;)<br />
后一种SQL语句将利用上ActionTime字段上的索引，从而提高查询效率。把&#8217;20010301&#8242;换成一个变量，根据取值的机率，可以有一半以上的机会提高效率。同理，对于大于某个值的查询，如果知道当前可能的最大值，也可以在Where子句中加上 “AND 列名< MAX(最大值)”。</p>
<p>第四掌尽量去掉"IN"、"OR"<br />
含有"IN"、"OR"的Where子句常会使用工作表，使索引失效；如果不产生大量重复值，可以考虑把子句拆开；拆开的子句中应该包含索引。<br />
例4：        select count(*) from stuff where id_no in('0','1')（23秒）<br />
可以考虑将or子句分开：<br />
select count(*) from stuff where id_no='0'<br />
select count(*) from stuff where id_no='1'<br />
然后再做一个简单的加法，与原来的SQL语句相比，查询速度更快。</p>
<p>第五掌尽量去掉 "<>&#8221;<br />
尽量去掉 &#8220;<>&#8220;，避免全表扫描，如果数据是枚举值，且取值范围固定，则修改为&#8221;OR&#8221;方式。<br />
例5：<br />
        UPDATE SERVICEINFO SET STATE=0 WHERE STATE<>0;<br />
以上语句由于其中包含了&#8221;<>&#8220;，执行计划中用了全表扫描（TABLE ACCESS FULL），没有用到state字段上的索引。实际应用中，由于业务逻辑的限制，字段state为枚举值，只能等于0，1或2，而且，值等于=1，2的很少，因此可以去掉&#8221;<>&#8220;，利用索引来提高效率。<br />
修改为：UPDATE SERVICEINFO SET STATE=0  WHERE STATE = 1 OR STATE = 2 。进一步的修改可以参考第4种方法。<br />
第六掌去掉Where子句中的IS NULL和IS NOT NULL<br />
Where字句中的IS NULL和IS NOT NULL将不会使用索引而是进行全表搜索，因此需要通过改变查询方式，分情况讨论等方法，去掉Where子句中的IS NULL和IS NOT NULL。</p>
<p>第七掌索引提高数据分布不均匀时查询效率<br />
索引的选择性低，但数据的值分布差异很大时，仍然可以利用索引提高效率。A、数据分布不均匀的特殊情况下，选择性不高的索引也要创建。<br />
表ServiceInfo中数据量很大，假设有一百万行，其中有一个字段DisposalCourseFlag，取值范围为枚举值：[0，1，2，3，4，5，6，7]。按照前面说的索引建立的规则，“选择性不高的字段不应该建立索引，该字段只有8种取值，索引值的重复率很高，索引选择性明显很低，因此不建索引。然而，由于该字段上数据值的分布情况非常特殊，具体如下表：<br />
取值范围                  1~5        6          7<br />
占总数据量的百分比        1%        98%        1%<br />
而且，常用的查询中，查询DisposalCourseFlag<6 的情况既多又频繁，毫无疑问，如果能够建立索引，并且被应用，那么将大大提高这种情况的查询效率。因此，我们需要在该字段上建立索引。</p>
<p>第八掌利用HINT强制指定索引<br />
在ORACLE优化器无法用上合理索引的情况下，利用HINT强制指定索引。<br />
继续上面7的例子，ORACLE缺省认定，表中列的值是在所有数据行中均匀分布的，也就是说，在一百万数据量下，每种DisposalCourseFlag值各有12.5万数据行与之对应。假设SQL搜索条件DisposalCourseFlag=2，利用DisposalCourseFlag列上的索引进行数据搜索效率，往往不比全表扫描的高，ORACLE因此对索引“视而不见”，从而在查询路径的选择中，用其他字段上的索引甚至全表扫描。根据我们上面的分析，数据值的分布很特殊，严重的不均匀。为了利用索引提高效率，此时，一方面可以单独对该字段或该表用analyze语句进行分析，对该列搜集足够的统计数据，使ORACLE在查询选择性较高的值时能用上索引；另一方面，可以利用HINT提示，在SELECT关键字后面，加上“/*+ INDEX(表名称，索引名称）*/”的方式，强制ORACLE优化器用上该索引。<br />
比如： select * from  serviceinfo where DisposalCourseFlag=1 ;<br />
上面的语句，实际执行中ORACLE用了全表扫描，加上蓝色提示部分后，用到索引查询。如下：<br />
select /*+  INDEX(SERVICEINFO,IX_S_DISPOSALCOURSEFLAG)  */  *<br />
from  serviceinfo where DisposalCourseFlag=1;<br />
请注意，这种方法会加大代码维护的难度，而且该字段上索引的名称被改变之后，必须要同步所有指定索引的HINT代码，否则HINT提示将被ORACLE忽略掉。</p>
<p>第九掌屏蔽无用索引<br />
继续上面8的例子，由于实际查询中，还有涉及到DisposalCourseFlag=6的查询，而此时如果用上该字段上的索引，将是非常不明智的，效率也极低。因此这种情况下，我们需要用特殊的方法屏蔽该索引，以便ORACLE选择其他字段上的索引。比如，如果字段为数值型的就在表达式的字段名后，添加“+ 0”，为字符型的就并上空串：“||""”<br />
如： select * from  serviceinfo where DisposalCourseFlag+ 0 = 6 and workNo =  '36' 。<br />
不过，不要把该用的索引屏蔽掉了，否则同样会产生低效率的全表扫描。</p>
<p>第十掌分解复杂查询，用常量代替变量<br />
对于复杂的Where条件组合，Where中含有多个带索引的字段，考虑用IF语句分情况进行讨论；同时，去掉不必要的外来参数条件，减低复杂度，以便在不同情况下用不同字段上的索引。<br />
继续上面9的例子，对于包含<br />
Where (DisposalCourseFlag < v_DisPosalCourseFlag) or (v_DisPosalCourseFlag is null) and ....的查询，(这里v_DisPosalCourseFlag为一个输入变量，取值范围可能为[NULL，0，1，2，3，4，5，6，7])，可以考虑分情况用IF语句进行讨论，类似：<br />
IF v_DisPosalCourseFlag =1 THEN<br />
Where DisposalCourseFlag = 1 and ....<br />
ELSIF v_DisPosalCourseFlag =2 THEN<br />
Where DisposalCourseFlag = 2 and ....<br />
。。。。。。 </p>
<p>第十一掌 like子句尽量前端匹配<br />
因为like参数使用的非常频繁，因此如果能够对like子句使用索引，将很高的提高查询的效率。<br />
例6：select * from city where name like ‘%S%’<br />
以上查询的执行计划用了全表扫描（TABLE ACCESS FULL），如果能够修改为：<br />
select * from city where name like ‘S%’<br />
那么查询的执行计划将会变成（INDEX RANGE SCAN），成功的利用了name字段的索引。这意味着Oracle SQL优化器会识别出用于索引的like子句，只要该查询的匹配端是具体值。因此我们在做like查询时，应该尽量使查询的匹配端是具体值，即使用like ‘S%’。</p>
<p>第十二掌用Case语句合并多重扫描<br />
我们常常必须基于多组数据表计算不同的聚集。例如下例通过三个独立查询：<br />
例8：1）select count(*) from emp where sal<1000;<br />
     2）select count(*) from emp where sal between 1000 and 5000;<br />
     3）select count(*) from emp where sal>5000;<br />
这样我们需要进行三次全表查询，但是如果我们使用case语句：<br />
select<br />
count (sale when sal <1000<br />
then 1 else null end)                count_poor,<br />
count (sale when between 1000 and 5000<br />
then 1 else null end)                count_blue_collar,<br />
count (sale when sal >5000<br />
then 1 else null end)                count_poor<br />
from emp;<br />
这样查询的结果一样，但是执行计划只进行了一次全表查询。</p>
<p>第十三掌使用nls_date_format<br />
例9：<br />
select * from record where  to_char(ActionTime,&#8217;mm&#8217;)=&#8217;12&#8242;<br />
这个查询的执行计划将是全表查询，如果我们改变nls_date_format，<br />
SQL>alert session set nls_date_formate=’MM’;<br />
现在重新修改上面的查询：<br />
select * from record where  ActionTime=&#8217;12&#8242;<br />
这样就能使用actiontime上的索引了，它的执行计划将是（INDEX RANGE SCAN）。</p>
<p>第十四掌使用基于函数的索引<br />
前面谈到任何对列的操作都可能导致全表扫描，例如：<br />
select * from emp where substr(ename,1,2)=’SM’;<br />
但是这种查询在客服系统又经常使用，我们可以创建一个带有substr函数的基于函数的索引，<br />
create index emp_ename_substr on eemp ( substr(ename,1,2) );</p>
<p>这样在执行上面的查询语句时，这个基于函数的索引将排上用场，执行计划将是（INDEX RANGE SCAN）。</p>
<p>第十五掌基于函数的索引要求等式匹配<br />
上面的例子中，我们创建了基于函数的索引，但是如果执行下面的查询：<br />
select * from emp where substr(ename,1,1)=’S’<br />
得到的执行计划将还是（TABLE ACCESS FULL），因为只有当数据列能够等式匹配时，基于函数的索引才能生效，这样对于这种索引的计划和维护的要求都很高。请注意，向表中添加索引是非常危险的操作，因为这将导致许多查询执行计划的变更。然而，如果我们使用基于函数的索引就不会产生这样的问题，因为Oracle只有在查询使用了匹配的内置函数时才会使用这种类型的索引。</p>
<p>第十六掌使用分区索引<br />
在用分析命令对分区索引进行分析时，每一个分区的数据值的范围信息会放入Oracle的数据字典中。Oracle可以利用这个信息来提取出那些只与SQL查询相关的数据分区。<br />
例如，假设你已经定义了一个分区索引，并且某个SQL语句需要在一个索引分区中进行一次索引扫描。Oracle会仅仅访问这个索引分区，而且会在这个分区上调用一个此索引范围的快速全扫描。因为不需要访问整个索引，所以提高了查询的速度。</p>
<p>第十七掌使用位图索引<br />
位图索引可以从本质上提高使用了小于1000个唯一数据值的数据列的查询速度，因为在位图索引中进行的检索是在RAM中完成的，而且也总是比传统的B树索引的速度要快。对于那些少于1000个唯一数据值的数据列建立位图索引，可以使执行效率更快。</p>
<p>第十八掌决定使用全表扫描还是使用索引<br />
和所有的秘笈一样，最后一招都会又回到起点，最后我们来讨论一下是否需要建立索引，也许进行全表扫描更快。在大多数情况下，全表扫描可能会导致更多的物理磁盘输入输出，但是全表扫描有时又可能会因为高度并行化的存在而执行的更快。如果查询的表完全没有顺序，那么一个要返回记录数小于10％的查询可能会读取表中大部分的数据块，这样使用索引会使查询效率提高很多。但是如果表非常有顺序，那么如果查询的记录数大于40％时，可能使用全表扫描更快。因此，有一个索引范围扫描的总体原则是：<br />
1）对于原始排序的表  仅读取少于表记录数40％的查询应该使用索引范围扫描。反之，读取记录数目多于表记录数的40％的查询应该使用全表扫描。<br />
2）对于未排序的表    仅读取少于表记录数7％的查询应该使用索引范围扫描。反之，读取记录数目多于表记录数的7％的查询应该使用全表扫描。</p>
<p>4        总结<br />
以上的招式，是完全可以相互结合同时运用的。而且各种方法之间相互影响，紧密联系。这种联系既存在一致性，也可能带来冲突，当冲突发生时，需要根据实际情况进行选择，没有固定的模式。最后决定SQL优化功力的因素就是对ORACLE内功的掌握程度了。<br />
另外，值得注意的是：随着时间的推移和数据的累计与变化，ORACLE对SQL语句的执行计划也会改变，比如：基于代价的优化方法，随着数据量的增大，优化器可能错误的不选择索引而采用全表扫描。这种情况可能是因为统计信息已经过时，在数据量变化很大后没有及时分析表；但如果对表进行分析之后，仍然没有用上合理的索引，那么就有必要对SQL语句用HINT提示，强制用合理的索引。但这种HINT提示也不能滥用，因为这种方法过于复杂，缺乏通用性和应变能力，同时也增加了维护上的代价；相对来说，基于函数右移、去掉“IN ，OR ，<> ，IS NOT NULL ”、分解复杂的SQL语句等等方法，却是“放之四海皆准”的，可以放心大胆的使用。<br />
同时，优化也不是“一劳永逸”的，必须随着情况的改变进行相应的调整。当数据库设计发生变化，包括更改表结构：字段和索引的增加、删除或改名等；业务逻辑发生变化：如查询方式、取值范围发生改变等等。在这种情况下，也必须对原有的优化进行调整，以适应效率上的需求 </p>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2011/02/how-to-use-svmap/' rel='bookmark' title='Permanent Link: How to use svmap.'>How to use svmap.</a></li>
<li><a href='http://cq-cser.cn/2009/12/seo%e6%89%93%e6%89%8b/' rel='bookmark' title='Permanent Link: SEO打手'>SEO打手</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/05/%e5%9f%ba%e4%ba%8e%e7%b4%a2%e5%bc%95%e7%9a%84sql%e8%af%ad%e5%8f%a5%e4%bc%98%e5%8c%96/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Mac OS X中运行Apache ＋ PHP ＋ MySQL</title>
		<link>http://cq-cser.cn/2010/05/%e5%9c%a8mac-os-x%e4%b8%ad%e8%bf%90%e8%a1%8capache-%ef%bc%8b-php-%ef%bc%8b-mysql/</link>
		<comments>http://cq-cser.cn/2010/05/%e5%9c%a8mac-os-x%e4%b8%ad%e8%bf%90%e8%a1%8capache-%ef%bc%8b-php-%ef%bc%8b-mysql/#comments</comments>
		<pubDate>Mon, 10 May 2010 05:04:48 +0000</pubDate>
		<dc:creator>cq</dc:creator>
				<category><![CDATA[OS]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://cq-cser.cn/?p=1184</guid>
		<description><![CDATA[在Mac OS X中运行Apache ＋ PHP ＋ MySQL   作者：秦歌 Mac OS X 内置了Apache 和 PHP，这样使用起来非常方便。本文以Mac OS X 10.6.3为例。主要内容包括： 启动Apache 运行PHP 安装MySQL 使用phpMyAdmin 配置PHP的MCrypt扩展库 设置虚拟主机 启动Apache 有两种方法： 打开“系统设置偏好（System Preferences）” -&#62; “共享（Sharing）” -&#62; “Web共享（Web Sharing）” 打开“终端（terminal）”，然后 运行“sudo apachectl start”，再输入帐号密码，这样Apache就运行了。 运行“sudo apachectl －v”，你会看到Mac OS X 10.6.3中的Apache版本号： Server version: Apache/2.2.14 (Unix) Server built: Feb 11 2010 14:40:31 这样在浏览器中输入“http://localhost”，就可以看到出现一个内容为“It works!”的页面，它位于“/Library（资源库）/WebServer/Documents/”下，这是Apache的默认根目录。   [...]


Related posts:<ol><li><a href='http://cq-cser.cn/2011/01/xampp-mysql-1067/' rel='bookmark' title='Permanent Link: xampp-mysql-1067'>xampp-mysql-1067</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
<li><a href='http://cq-cser.cn/2010/03/mysql-net/' rel='bookmark' title='Permanent Link: MYSQL+.NET'>MYSQL+.NET</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>在Mac OS X中运行Apache ＋ PHP ＋ MySQL <span id="more-1184"></span></p>
<p> 作者：秦歌</p>
<div>
<div>
<p>Mac OS X 内置了Apache 和 PHP，这样使用起来非常方便。本文以Mac OS X 10.6.3为例。主要内容包括：</p>
<ol>
<li><a href="http://dancewithnet.com/#apache" target="_blank">启动Apache</a></li>
<li><a href="http://dancewithnet.com/#php" target="_blank">运行PHP</a></li>
<li><a href="http://dancewithnet.com/#mysql" target="_blank">安装MySQL</a></li>
<li><a href="http://dancewithnet.com/" target="_blank">使用phpMyAdmin</a></li>
<li><a href="http://dancewithnet.com/" target="_blank">配置PHP的MCrypt扩展库</a></li>
<li><a href="http://dancewithnet.com/" target="_blank">设置虚拟主机</a></li>
</ol>
<h3>启动Apache</h3>
<p>有两种方法：</p>
<ol>
<li>打开“系统设置偏好（System Preferences）” -&gt; “共享（Sharing）” -&gt; “Web共享（Web Sharing）”</li>
<li>打开“终端（terminal）”，然后
<ol>
<li>运行“<code>sudo apachectl start</code>”，再输入帐号密码，这样Apache就运行了。</li>
<li>运行“<code>sudo apachectl －v</code>”，你会看到Mac OS X 10.6.3中的Apache版本号：
<pre><code>Server version: Apache/2.2.14 (Unix)
Server built:   Feb 11 2010 14:40:31
</code></pre>
</li>
</ol>
</li>
</ol>
<p>这样在浏览器中输入“http://localhost”，就可以看到出现一个内容为“It works!”的页面，它位于“/Library（资源库）/WebServer/Documents/”下，这是Apache的默认根目录。</p>
<p><span> </span></p>
<p>注意：开启了Apache就是开启了“Web共享”，这时联网的用户就会通过“http://[本地IP]/”来访问“/Library（资源库）/WebServer/Documents/”目录，通过“http://[本地IP]/~[用户名]”来访问“/Users/[用户名]/Sites/”目录，可以通过设置“系统偏好设置”的“安全（Security）”中的“防火墙（Firewall）”来禁止这种访问。</p>
<h3>运行PHP</h3>
<ol>
<li>在终端中运行“<code>sudo vi /etc/httpd.conf</code>”，打开Apache的配置文件。（如果不习惯操作终端和vi的可以设置<a href="http://apple.tgbus.com/tutorial/soft/200811/20081125100105.shtml" target="_blank">在Finder中显示所有的系统隐藏文件</a>，记得需要<a href="http://www.macdocks.com/2009/07/14/mac-tips-%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95%E9%87%8D%E5%90%AFmac-os-x-finder/" target="_blank">重启Finder</a>，这样就可以找到对应文件，随心所欲编辑了，但需要注意的是某些文件的修改需要<a href="http://support.apple.com/kb/HT1528?viewlocale=zh_CN" target="_blank">开启root帐号</a>，但整体上还是在终端上使用sudo来临时获取root权限比较安全。）</li>
<li>找到“<code>#LoadModule php5_module libexec/apache2/libphp5.so</code>”，把前面的#号去掉，保存并退出vi。</li>
<li>运行“<code>sudo cp /etc/php.ini.default /ect/php.ini</code>”，这样就可以通过php.ini来配置各种PHP功能了。比如：
<pre><code><span>;通过下面两项来调整PHP提交文件的最大值，比如phpMyAdmin中导入数据的最大值</span>
upload_max_filesize = 2M
post_max_size = 8M
<span>;比如通过display_errors来控制是否显示PHP程序的报错</span>
display_errors = Off
</code></pre>
</li>
<li>运行“<code>sudo apachectl restart</code>”，重启Apache，这样PHP就可以用了。</li>
<li>运行“<code>cp /Library/WebServer/Documents/index.html.en /Library/WebServer/Documents/info.php</code>”，即在Apache的根目录下复制index.html.en文件并重命名为info.php</li>
<li>在终端中运行“<code>vi /Library/WebServer/Document/info.php</code>”，这样就可以在vi中编辑info.php文件了。在“It’s works!”后面加上“”，然后保存之。这样就可以在http://localhost/info.php中看到有关PHP的信息，比如版本号是5.3.1。</li>
</ol>
<h3>安装MySQL</h3>
<p>由于Mac OS X中并没有预装MySQL，所以需要自己手动安装，目前MySQL的最稳定版本是5.1。<a href="http://dev.mysql.com/doc/refman/5.1/en/mac-os-x-installation.html" target="_blank">MySQL提供了Mac OS X下的安装说明</a>。</p>
<ol>
<li><a href="http://dev.mysql.com/downloads/mysql/5.1.html" target="_blank">下载MySQL 5.1</a>。选择合适的版本，比如这里选择的是mysql-5.1.46-osx10.6-x86_64.dmg。</li>
<li>运行dmg，会发现里面有4个文件。首先点击安装mysql-5.1.46-osx10.6-x86_64.pkg，这是MySQL的主安装包。一般情况下，安装文件会自动把MySQL安装到/usr/local下的同名文件夹下。比如点击运行“mysql-5.1.46-osx10.6-x86_64.dmg”会把MySQ安装到“<code>/usr/local/mysql-5.1.46-osx10.6-x86_64</code>”中。一路默认安装完毕即可。</li>
<li>点击安装第2个文件MySQLStartupItem.pkg，这样MySQL就会自动在开机时自动启动了。</li>
<li>点击安装第3个文件MySQL.prefPane，这样就会在“系统设置偏好”中看到名为“MySQL”的ICON，通过它就可以设置MySQL开始还是停止，以及是否开机时自动运行。到这里MySQL就基本安装完毕了。</li>
<li>通过运行“<code>sudo vi /etc/bashrc</code>”，在bash的配置文件中加入<code>mysql</code>和<code>mysqladmin</code>的别名
<pre><code>#mysql
alias mysql='/usr/local/mysql/bin/mysql'
alias mysqladmin='/usr/local/mysql/bin/mysqladmin'
</code></pre>
<p>这样就可以在终端中比较简单地通过命令进行相应的操作，比如安装完毕之后MySQL的<code>root</code>默认密码为空，如果要设置密码可以在终端运行“<code>mysqladmin -u root password "mysqlpassword"</code>”来设置，其中mysqlpassword即root的密码。更多相关内容可以参考<a href="http://dev.mysql.com/doc/refman/5.1/en/resetting-permissions.html" target="_blank">B.5.4.1. How to Reset the Root Password</a>。</li>
</ol>
<h3>使用phpMyAdmin</h3>
<p><a href="http://www.phpmyadmin.net/" target="_blank">phpMyAdmin</a>是用PHP开发的管理MySQL的程序，非常的流行和实用。能够实用phpMyAdmin管理MySQL是检验前面几步成果的非常有效方式。</p>
<ol>
<li><a href="http://www.phpmyadmin.net/home_page/downloads.php" target="_blank">下载phpMyAdmin</a>。选择合适的版本，比如我选择的是phpMyAdmin-3.3.2-all-languages.tar.bz2这个版本。</li>
<li>把“下载（downloads）”中的phpMyAdmin-3.32-all-languages文件夹复制到“<code>/Users/[用户名]/Site</code>s”中，名改名为phpmyadmin。</li>
<li>复制“<code>/Users/[用户名]/Sites/phpmyadmin/</code>”中的config.sample.inc.php，并命名为config.inc.php</li>
<li>打开config.inc.php,做如下修改：
<pre><code><span>用于Cookie加密，随意的长字符串</span>
$cfg['blowfish_secret'] = ''; 

<span>当phpMyAdmin中出现“#2002 无法登录 MySQL 服务器”时，
<a href="http://achan.me/2010/04/mysql-error-2002.html" target="_blank">请把localhost改成127.0.0.1就ok了</a>，
这是因为MySQL守护程序做了IP绑定（bind-address =127.0.0.1）造成的</span>
$cfg['Servers'][$i]['host'] = 'localhost';

<span>把false改成true，这样就可以访问无密码的MySQL了，
即使MySQL设置了密码也可以这样设置，然后在登录phpMyAdmin时输入密码</span>
$cfg['Servers'][$i]['AllowNoPassword'] = false;
</code></pre>
</li>
<li>这样就可以通过<code>http://localhost/~[用户名]/phpmyadmin</code>访问phpMyAdmin了。这个时候就看到一个提示“无法加载 mcrypt 扩展，请检查您的 PHP 配置。”，这就涉及到下一节安装MCrypt扩展了。</li>
</ol>
<h3>配置PHP的MCrypt扩展</h3>
<p><a href="http://mcrypt.sourceforge.net/" target="_blank">MCrypt</a>是一个功能强大的加密算法扩展库，它包括有22种算法，phpMyAdmin依赖这个PHP扩展库。但是它在Mac OS X下的安装却不那么友善，具体如下：</p>
<ol>
<li>下载并解压<a href="http://sourceforge.net/projects/mcrypt/files/Libmcrypt/" target="_blank">libmcrypt-2.5.8.tar.bz2</a>。</li>
<li>在终端执行如下命令：
<pre><code>cd ~/Downloads/libmcrypt-2.5.8/
./configure --disable-posix-threads --enable-static
make
sudo make install</code></pre>
</li>
<li>下载并解压<a href="http://us2.php.net/get/php-5.3.1.tar.bz2/from/a/mirror" target="_blank">PHP源码文件php-5.3.1.tar.bz2</a>。Mac OS X 10.6.3中预装的PHP版本是5.3.1，而现在<a href="http://us2.php.net/downloads.php" target="_blank">最新的PHP版本是5.3.2</a>，你需要依据自己的实际情况选择对应的版本。</li>
<li>在终端执行如下命令：
<pre><code>cd ~/Downloads/php-5.3.1/ext/mcrypt
phpize
./configure
make
cd modules
sudo cp mcrypt.so /usr/lib/php/extensions/no-debug-non-zts-20090626/</code></pre>
</li>
<li>打开php.ini
<pre><code>sudo vi /etc/php.ini</code></pre>
<p>在php.ini中加入如下代码，并保存后退出，然后重启Apache</p>
<pre><code>extension=/usr/lib/php/extensions/no-debug-non-zts-20090626/mcrypt.so</code></pre>
</li>
</ol>
<p>当你再访问<code>http://localhost/~[用户名]/phpmyadmin</code>时，你会发现“无法加载 mcrypt 扩展，请检查您的 PHP 配置。”的提示没有了，这就表示MCrypt扩展库安装成功了。</p>
<h3>设置虚拟主机</h3>
<ol>
<li>在终端运行“<code>sudo vi /etc/apache2/httpd.conf</code>”，打开Apche的配置文件</li>
<li>在httpd.conf中找到“<code>#Include /private/etc/apache2/extra/httpd-vhosts.conf</code>”，去掉前面的“＃”，保存并退出。</li>
<li>运行“sudo apachectl restart”，重启Apache后就开启了它的虚拟主机配置功能。</li>
<li>运行“sudo vi /etc/apache2/extra/httpd-vhosts.conf”，这样就打开了配置虚拟主机的文件httpd-vhost.conf，配置你需要的虚拟主机了。需要注意的是该文件默认开启了两个作为例子的虚拟主机：
<pre><code>&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "/usr/docs/dummy-host.example.com"
    ServerName dummy-host.example.com
    ErrorLog "/private/var/log/apache2/dummy-host.example.com-error_log"
    CustomLog "/private/var/log/apache2/dummy-host.example.com-access_log" common
&lt;/VirtualHost&gt;
&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "/usr/docs/dummy-host2.example.com"
    ServerName dummy-host2.example.com
    ErrorLog "/private/var/log/apache2/dummy-host2.example.com-error_log"
    CustomLog "/private/var/log/apache2/dummy-host2.example.com-access_log" common
&lt;/VirtualHost&gt; </code></pre>
<p>而实际上，这两个虚拟主机是不存在的，在没有配置任何其他虚拟主机时，可能会导致访问localhost时出现如下提示：</p>
<pre><code>Forbidden
You don't have permission to access /index.php on this server</code></pre>
<p>最简单的办法就是在它们每行前面加上#，注释掉就好了，这样既能参考又不导致其他问题。</li>
<li>增加如下配置
<pre><code>&lt;VirtualHost *:80&gt;
    DocumentRoot "/Users/[用户名]/Sites"
    ServerName sites
    ErrorLog "/private/var/log/apache2/sites-error_log"
    CustomLog "/private/var/log/apache2/sites-access_log" common
&lt;/VirtualHost&gt; </code></pre>
<p>保存退出，并重启Apache。</li>
<li>运行“<code>sudo vi /etc/hosts</code>”，打开hosts配置文件，加入”<code>127.0.0.1 sites</code>“，这样就可以配置完成sites虚拟主机了，这样就可以用“http://sites”访问了，其内容和“http://localhost/~[用户名]”完全一致。</li>
</ol>
<p>这是利用Mac OS X 10.6.3中原生支持的方式来实现的配置，也可以参考“<a href="http://blog.csdn.net/afatgoat/archive/2008/12/26/3615026.aspx" target="_blank">Mac OS X Leopard: 配置Apache, PHP, SQLite, MySQL, and phpMyAdmin(一) </a>”和“<a href="http://blog.csdn.net/afatgoat/archive/2008/12/28/3628710.aspx" target="_blank">Mac OS X Leopard: 配置Apache, PHP, SQLite, MySQL, and phpMyAdmin(二) </a>”。实际上，你还可以使用<a href="http://www.apachefriends.org/en/xampp-macosx.html" target="_blank">XAMPP</a>或<a href="http://www.macports.org/" target="_blank">MacPorts</a>这种第三方提供的集成方案来实现简单的安装和使用。</p>
</div>
</div>


<p>Related posts:<ol><li><a href='http://cq-cser.cn/2011/01/xampp-mysql-1067/' rel='bookmark' title='Permanent Link: xampp-mysql-1067'>xampp-mysql-1067</a></li>
<li><a href='http://cq-cser.cn/2009/11/vps-%e5%bf%ab%e9%80%9f%e5%ae%89%e8%a3%85-linuxnginxmysqlphp-%e7%8e%af%e5%a2%83%e3%80%90%e8%bd%ac%e3%80%91/' rel='bookmark' title='Permanent Link: VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】'>VPS 快速安装 Linux+Nginx+MySQL+PHP 环境【转】</a></li>
<li><a href='http://cq-cser.cn/2010/03/mysql-net/' rel='bookmark' title='Permanent Link: MYSQL+.NET'>MYSQL+.NET</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cq-cser.cn/2010/05/%e5%9c%a8mac-os-x%e4%b8%ad%e8%bf%90%e8%a1%8capache-%ef%bc%8b-php-%ef%bc%8b-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

