﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-GCC/GNU/Linux Delphi/Window Java/Anywhere</title><link>http://www.cppblog.com/Khan/</link><description>路漫漫，长修远，我们不能没有钱</description><language>zh-cn</language><lastBuildDate>Thu, 08 Jan 2009 17:28:47 GMT</lastBuildDate><pubDate>Thu, 08 Jan 2009 17:28:47 GMT</pubDate><ttl>60</ttl><item><title>Linux 进程互斥锁</title><link>http://www.cppblog.com/Khan/archive/2008/12/24/70218.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Wed, 24 Dec 2008 02:45:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/12/24/70218.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/70218.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/12/24/70218.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/70218.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/70218.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 最开始打算用semaphore实现, <br><br>sem_t waitNonEmpty;<br>int empty=0;&nbsp; <br>sem_init(&amp;waitNonEmpty, 1, empty); /*初始化信号量*/<br><br>sem_wait(&amp;waitNonEmpty);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*是否有"非空资源"*/<br>sem_post(&amp;waitNonEmpty);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*生成一个"非满资源"*/<br>sem_destroy(&amp;waitNonEmpty);<br><br>后来在fc3 redhat7.3下man了sem_init, 第二个参数int pshared <br>The pshared<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; argument indicates whether the semaphore is local to the&nbsp; current&nbsp; pro-<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cess&nbsp; ( pshared is zero) or is to be shared between several processes (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pshared is not zero). LinuxThreads currently does not support&nbsp; process-<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shared&nbsp; semaphores,&nbsp; thus&nbsp; sem_init always returns with error ENOSYS if<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pshared is not zero.<br><br>最邪恶的现状出来了, 这俩系统没有实现sem的进程间通信, 如果设置not zero, 会返回ENOSYS的错误...<br>后来找了个redhat Enterprise 4 看了下文档, 貌似又支持了....<br><br>做个记号. 一会儿看看flock<br>fcntl 是唯一符合posix的文件锁<br>
<p><span style="color: #0000ff;">结构体flock的指针</span>
<span style="color: #000000;">：</span>
</p>
<p>struct flcok { <br>&nbsp; short int l_type; /* 锁定的状态*/</p>
<p>&nbsp; //这三个参数用于分段对文件加锁，若对整个文件加锁，则：l_whence=SEEK_SET,l_start=0,l_len=0;<br>&nbsp; short int l_whence;/*决定l_start位置*/ <br>&nbsp; off_t l_start; /*锁定区域的开头位置*/ <br>&nbsp; off_t l_len; /*锁定区域的大小*/<br><br>&nbsp; pid_t l_pid; /*锁定动作的进程*/ <br>
};</p>
<p><br>
l_type 有三种状态: <br>
F_RDLCK 建立一个供读取用的锁定 <br>
F_WRLCK 建立一个供写入用的锁定 <br>
F_UNLCK 删除之前建立的锁定</p>
<br>int fcntl(int fd, int cmd, struct flock *lock);<br>int cmd<br>&nbsp; //F_SETLKW对加锁操作进行阻塞，<br>&nbsp; //F_SETLK不对加锁操作进行阻塞，立即返回<br><br>&nbsp;&nbsp;&nbsp; 当使用F_SETLK宏，不进行阻塞加锁操作时。两个进程有对文件加锁失败的情况出现。<br>&nbsp;&nbsp;&nbsp; 当使用F_SETLKW宏，进行阻塞加锁操作时。两个进程没有文件加锁失败的情况。但是根据进程的输出日志，可以明显看出A进程对文件操作时，B进程停止对文件操作。<br>&nbsp;&nbsp;&nbsp; 测试过程中打开文件使用O_RDWR | O_CREAT | O_APPEND模式，并对文件加写锁。锁对打开文件没有影响，但是对另一进程加锁和写操作有影响。<br>&nbsp; 加锁对同一进程中的多线程无效。同一进程中的多线程对同一文件加锁，后加锁的线程会覆盖前一个线程加的文件锁。<br>&nbsp; fcntl文档中写到，一个进程对一个文件的区域只能加一个类型的锁<br><br><br><br>实现代码如下:<br>//filelock.h<br>#ifndef __FILE_LOCK_HPP__
<br>#define __FILE_LOCK_HPP__<br><br>&nbsp;<br>#ifdef __cplusplus<br>extern "C" {<br>#endif<br><br>&nbsp;<br>int file_lock(int fd);
<br>int file_unlock(int fd);<br>&nbsp;<br>#ifdef __cplusplus<br>}<br>#endif<br>&nbsp;<br>#endif //__FILE_LOCK_HPP__
<br>&nbsp;<br><br>------------------------华丽分割线-----------------------------<br>//filelock.cpp<br>&nbsp;<br>#include &lt;fcntl.h&gt;
<br>#include &lt;unistd.h&gt;
<br>&nbsp;<br>#include "filelock.h";
<br>&nbsp;<br>int file_lock(int fd){
<br>&nbsp; struct flock s_flock;
<br>&nbsp; s_flock.l_type = F_WRLCK;
<br>&nbsp;<br>&nbsp; s_flock.l_whence = SEEK_SET;
<br>&nbsp; s_flock.l_start = 0;
<br>&nbsp; s_flock.l_len = 0;
<br>&nbsp; s_flock.l_pid = getpid();
<br>&nbsp;&nbsp;
<br>&nbsp; //F_SETLKW对加锁操作进行阻塞，
<br>&nbsp; //F_SETLK不对加锁操作进行阻塞，立即返回
<br>&nbsp; return fcntl(fd, F_SETLKW, &amp;s_flock);
<br>}
<br>&nbsp;<br>&nbsp;<br>int file_unlock(int fd){
<br>&nbsp; return fcntl(fd, F_SETLKW, F_UNLCK);
<br>}
<br>&nbsp;<br><br>---------------------------------华丽的分割线--------------------------<br>test.cpp<br>&nbsp;<br>#include "filelock.h"
<br><br>#include &lt;sys/types.h&gt;<br>#include &lt;sys/stat.h&gt;<br>#include &lt;fcntl.h&gt;<br><br>#include &lt;unistd.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;sys/wait.h&gt;<br>#include &lt;errno.h&gt;<br>&nbsp;<br>&nbsp;<br>int main(int argc,char *argv[]) {<br>&nbsp; int pid = -1;<br>&nbsp;<br>&nbsp; int i = 5;<br>&nbsp; while(i--){<br>&nbsp;&nbsp;&nbsp; if ((pid = fork()) &lt; 0) { //fork出错<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; puts("fork1 error");<br>&nbsp;&nbsp;&nbsp; } else if (pid &gt; 0) {//父进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep(5);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (waitpid(pid, NULL, 0) &lt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; puts("waitpid error");<br><br>&nbsp;&nbsp;&nbsp; } else {//子进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep(1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int li_file = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int li_lck_st = -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li_file = open("tt.txt", O_WRONLY|O_CREAT, 0777);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( li_file &lt; 0 ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("file open error\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("li_file=[%d] pid=[%d]\n", li_file , getpid() );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; li_lck_st = file_lock(li_file);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep(5);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("li_lck_st=%d pid =%d\n", li_lck_st, getpid() );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file_unlock(li_file);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(li_file);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("close file pid=%d unlock\n", getpid());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return 0;
<br>}
<br>&nbsp;<br><br>------------------------------华丽分割线---------------------------<br>//makefile<br><br>#########################################################
<br>#Project: test
<br>#By: Khan.Lau
<br>#Description: test
<br>#########################################################
<br>&nbsp;<br>CC = gcc
<br>CXX = g++
<br>STRIP = strip
<br>AR = ar
<br><br>PROJ = $(shell pwd)<br>DLLPATH = $(shell find $(PROJ) -name *.so*)<br><br>LIBPATH = /usr<br>&nbsp;<br>INCS = -I$(LIBPATH)/include \<br>&nbsp;&nbsp;&nbsp; -I$(PROJ)/src/inc \<br>&nbsp;&nbsp;&nbsp; -I$(PROJ)/src<br><br><br>CXXINCS = -I$(LIBPATH)/include \<br>&nbsp;&nbsp;&nbsp; -I$(LIBPATH)/include/c++/4.3 \<br>&nbsp;&nbsp;&nbsp; -I$(LIBPATH)/include/c++/4.3/backward \<br>&nbsp;&nbsp;&nbsp; -I$(PROJ)/src/inc \<br>&nbsp;&nbsp;&nbsp; -I$(PROJ)/src<br><br>&nbsp;<br>CFLAGS = -g -Wall $(CXXINCS)&nbsp;
<br>#
<br>CONFIGURATION = release<br>#<br>BIN = test.exe<br>#LIB = lib/HuaWeiBsc.a<br>&nbsp;<br>#包路径<br>LIBS = -L$(PROJ)/lib&nbsp; \<br>&nbsp;&nbsp;&nbsp; -L$(LIBPATH)/lib -lz
<br>&nbsp;<br>SRCS = $(wildcard \<br>&nbsp;&nbsp;&nbsp; src/lib/*.cpp \<br>&nbsp;&nbsp;&nbsp; src/kernel/*.cpp)<br><br>&nbsp;<br>OBJBINS = $(SRCS:.cpp=.o)
<br>&nbsp;<br>&nbsp;<br>.c.o:
<br>&nbsp;&nbsp;&nbsp; $(CC) -o $@ -c $&lt; $(CFLAGS) <br>&nbsp;<br>.cpp.o:
<br>&nbsp;&nbsp;&nbsp; $(CXX) -o $@ -c $&lt; $(CFLAGS)&nbsp;
<br>&nbsp;<br>&nbsp;<br>COLORH=echo -en "\033[1;32;40m"
<br>COLORN=echo -en "\033[m"
<br>&nbsp;<br>&nbsp;<br>all : $(BIN)
<br><br>$(BIN) : $(OBJBINS)<br>&nbsp;&nbsp;&nbsp; $(CXX) -o $(CONFIGURATION)/$(BIN) $(OBJBINS) $(LIBS)
<br>&nbsp;&nbsp;&nbsp; @$(COLORN)
&nbsp;&nbsp;&nbsp; $(shell echo "$(BIN) build complete.")
<br>&nbsp;<br>#$(LIB) : $(OBJBINS)<br>#&nbsp;&nbsp;&nbsp; ar rc $(LIB) $(OBJBINS)<br><br>&nbsp;<br>clean :
<br>&nbsp;&nbsp;&nbsp; rm -f $(OBJBINS)
<br>&nbsp;&nbsp;&nbsp; rm -f $(BIN)
<br><br><br>-----------------------------华丽分割线--------------------------<br>测试环境 ubuntu 8.10,&nbsp; redhat 7.3, redhat fc3&nbsp; redhat enterprise 4.6<br>结果: <br>khan@khan-laptop:~/project/filelock/release$ ./test.exe <br>li_file=[3] pid=[10959]<br>li_lck_st=0 pid =10959<br>close file pid=10959 unlock<br>li_file=[3] pid=[10961]<br>li_lck_st=0 pid =10961<br>close file pid=10961 unlock<br>li_file=[3] pid=[10964]<br>li_lck_st=0 pid =10964<br>close file pid=10964 unlock<br>li_file=[3] pid=[10966]<br>li_lck_st=0 pid =10966<br>close file pid=10966 unlock<br>li_file=[3] pid=[10969]<br>li_lck_st=0 pid =10969<br>close file pid=10969 unlock<br><br>  <img src ="http://www.cppblog.com/Khan/aggbug/70218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-12-24 10:45 <a href="http://www.cppblog.com/Khan/archive/2008/12/24/70218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux /proc/文件系统.</title><link>http://www.cppblog.com/Khan/archive/2008/10/24/64933.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Fri, 24 Oct 2008 06:16:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/10/24/64933.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/64933.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/10/24/64933.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/64933.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/64933.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 最近要做一个jni给java来采集系统信息. 支持linux和windows<br>&nbsp;&nbsp;&nbsp; 采集的内容包括. 系统所有进程名, cpu占用率, 内存占用率, 系统内存大小, 已用内存大小, 可用内存大小, 分区大小, 已用分区磁盘空间, 可用分区磁盘空间. 系统信息. cpu核心总数..<br>&nbsp;&nbsp;&nbsp; 在windows下已经使用系统提供的api一一完成并经过调试. linux为了保证代码的统一. 也用了jni的方式<br><br>&nbsp;&nbsp;&nbsp; linux下我老以为会有类似的api提供. 翻了半天google, 最终决定还是从/proc文件系统开始来.<br>不过/proc方式的好处就是不论哪种语言. 只要他有操作文件的能力. 都可以获得这些信息. 而不局限于c或者c++<br><br>&nbsp;&nbsp;&nbsp; 要点1. /proc不是物理文件系统. 他是对内存数据的映射, 是驱动留给开发者和使用者的接口, 所以不管你什么时候用ls指令也好, 用stat来读 st_size也好. 他的大小都是0字节. <br>&nbsp;&nbsp;&nbsp; 要点2. 由于是vfs, 不要试图往/proc中扔文件或者目录<br><br>&nbsp;&nbsp;&nbsp; /proc目录中. 有不少信息. 我这次项目涉及到如下<br><br>&nbsp;&nbsp;&nbsp; /proc/stat&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实时的系统信息, 我感兴趣的主要是cpu负载数据<br>&nbsp;&nbsp;&nbsp; /proc/loadavg&nbsp;&nbsp; //一段时间内 cpu负载的平均数 以及最近一次的pid<br>&nbsp;&nbsp;&nbsp; /proc/cpuinfo&nbsp;&nbsp; //cpu信息 频率 核心 支持特性<br>&nbsp;&nbsp;&nbsp; /proc/version&nbsp;&nbsp; //系统内核版本&nbsp; 系统发行版本 gcc版本<br><br>&nbsp;&nbsp;&nbsp; /proc目录下每个以数字命名的子目录都代表一个进程, 目录名则是他的pid<br>&nbsp;&nbsp;&nbsp; /proc/(pid)/cmdline&nbsp; 该进程启动时的命令,&nbsp; 系统核心进程应该是空的<br>&nbsp;&nbsp;&nbsp; /proc/(pid)/stat&nbsp;&nbsp;&nbsp;&nbsp; 里面记录着pid, 进程名(short_cmd)等等<br>&nbsp;&nbsp;&nbsp; /proc/(pid)/environ&nbsp; 记录着系统执行的环境变量<br><br>其他的改天碰到再看吧.<br><br> <img src ="http://www.cppblog.com/Khan/aggbug/64933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-10-24 14:16 <a href="http://www.cppblog.com/Khan/archive/2008/10/24/64933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c语言（a ＜ b ＜ c ）的陷阱</title><link>http://www.cppblog.com/Khan/archive/2008/10/23/64835.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Thu, 23 Oct 2008 08:35:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/10/23/64835.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/64835.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/10/23/64835.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/64835.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/64835.html</trackback:ping><description><![CDATA[很久没有碰c/c++了, 近两年都是java为主, 偶尔用一下c/c++<br><br>(a&lt;b&lt;c) 这种写法我以前从来没有用过. 今天突然有网友提起来, 我习惯性的在脑海中把其翻译成<br>(a&lt;b &amp;&amp; b&lt;c) 酿成了一些小错误. 我悔过了.<br><br>网友给我扔来了c99的标准<br>&#167;6.5.9 第86页 89) The expression a&lt;b&lt;c is not interpreted as in ordinary mathematics. As the syntax indicates, it<br>means (a&lt;b)&lt;c; in other words, &#8216;&#8216;if a is less than b, compare 1 to c; otherwise, compare 0 to c&#8217;&#8217;.<br><br>意思也就是说. (a&lt;b&lt;c) 按照从左到右的方式开始运算<br>1.( (a&lt;b) &lt; c )<br>2.a&lt;b ?&nbsp; TRUE : FALSE; <br>3.所以, 最终表达式运算的是 (1&lt;c) 或者 (0&lt;c)<br><br>C语言中. 虽然任何不等于0的数为真. 但是实际在宏定义中 TRUE == 1&nbsp; FALSE == 0;<img src ="http://www.cppblog.com/Khan/aggbug/64835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-10-23 16:35 <a href="http://www.cppblog.com/Khan/archive/2008/10/23/64835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sourceforge又被封了...你们想让我说什么呢....</title><link>http://www.cppblog.com/Khan/archive/2008/07/07/55576.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Mon, 07 Jul 2008 15:28:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/07/07/55576.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/55576.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/07/07/55576.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/55576.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/55576.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 此贴是原创, 又不算技术, 关乎开源, 但是又无关软件...矛盾啊....<br>&nbsp;&nbsp; 半夜想down个mingw32... 去sourceforge.发现又上不去了. 凭直觉, 网站出问题的机会几乎没有. 开了个jondo, 果然能上去.<br>&nbsp;&nbsp; 上面的人又封sourceforge了.从06年LUPA事件到现在, 又开始了.<br>&nbsp;&nbsp;&nbsp; 开jondo down东西. 速度不足2k. tor速度更慢, 大家有没有什么好的工具.&nbsp; 这个时势没办法. 不能忍受就要学会享受.<br>&nbsp;&nbsp;&nbsp; 世道真是越来越乱了......<br><br><img src ="http://www.cppblog.com/Khan/aggbug/55576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-07-07 23:28 <a href="http://www.cppblog.com/Khan/archive/2008/07/07/55576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC6 与GCC-avr交叉环境配置</title><link>http://www.cppblog.com/Khan/archive/2008/06/24/54457.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Tue, 24 Jun 2008 04:05:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/06/24/54457.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/54457.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/06/24/54457.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/54457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/54457.html</trackback:ping><description><![CDATA[01、在C:或其他盘下安装VC6.0<br>02、在C:或其他盘下新建ECC文件夹<br>03、在C:\ECC目录下安装WinAVR-20040720版<br>04、在C:\ECC目录下新建common文件夹<br>05、把lib和inc文件夹copy到C:\ECC\common目录下<br>06、把cl.exe; lhex.exe; link.exe; lview.exe; nmake.exe; rc.exe; sp.exe; ecc.reg; 这8个文件COPY到C:\ECC目录下<br>07、把EccAddin.pdb和EccAddin.dll 文件copy到VC目录下的\common\msdev98\addins 目录下<br>08、把GccWizard.awx 文件copy到 VC目录下的\common\msdev98\template 目录下<br>09、在任何目录下安装port95nt.exe<br>10、把avr5.x 文件copy到C:\ECC\Winavr\avr\lib\ldscripts 目录下<br>11、把usertype&nbsp; 文件copy到 VC目录下的\common\msdev98\bin 目录下<br>12、用记事本打开ecc.reg修改路径并保存，双击此文件添加到注册表中<br>13、打开VC++6.0; 在tools菜单-&gt;options-&gt;directories中将 C:\ECC\common\inc和C:\ECC\winavr\include 两个目录添加到include file选项中。同时将C:\ECC目录添加到executable files 选项中；并将之移到顶部。<br><br>SP.exe 烧录的配置自己google吧<br><br>备注:<br>07 把EccAddin.pdb和EccAddin.dll 文件copy到VC目录下的\common\msdev98\addins 目录下<br>这俩文件是自己写d<br><br> <img src ="http://www.cppblog.com/Khan/aggbug/54457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-06-24 12:05 <a href="http://www.cppblog.com/Khan/archive/2008/06/24/54457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GCC Mingw编译JNI dll要点</title><link>http://www.cppblog.com/Khan/archive/2008/06/23/54364.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Mon, 23 Jun 2008 04:57:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/06/23/54364.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/54364.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/06/23/54364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/54364.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/54364.html</trackback:ping><description><![CDATA[本来想做一个win32平台下, 由于vc没有psapi.dll的库. 所以选择了mingw包和gcc编译器.<br><br>java部分<br>这里主要是申明接口. javah工具会根据你声明的接口自动生成对于的.h头文件<br><br>//SystemInfo.java<br>package com.khan.system;<br><br>public abstract class SystemInfo<br>{<br>&nbsp;&nbsp;&nbsp; // public: ................................................................<br>&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * A simple class to represent data snapshots taken by {@link #makeCPUUsageSnapshot}.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static final class CPUUsageSnapshot {<br>&nbsp;&nbsp;&nbsp; public final long m_time, m_CPUTime;<br>&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // constructor is private to ensure that makeCPUUsageSnapshot()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // is used as the factory method for this class:<br>&nbsp;&nbsp;&nbsp; private CPUUsageSnapshot (final long time, final long CPUTime) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_time = time;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_CPUTime = CPUTime;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; &nbsp;<br>&nbsp; } // end of nested class<br><br><br><br>&nbsp;&nbsp;&nbsp; // Custom exception class for throwing<br>&nbsp; public static final class NegativeCPUTime extends Exception {}<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Minimum time difference [in milliseconds] enforced for the inputs into<br>&nbsp;&nbsp;&nbsp; * {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.<br>&nbsp;&nbsp;&nbsp; * The motivation for this restriction is the fact that &lt;CODE&gt;System.currentTimeMillis()&lt;/CODE&gt;<br>&nbsp;&nbsp;&nbsp; * on some systems has a low resolution (e.g., 10ms on win32). The current value<br>&nbsp;&nbsp;&nbsp; * is 100 ms.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static final int MIN_ELAPSED_TIME = 100;<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Creates a CPU usage data snapshot by associating CPU time used with system<br>&nbsp;&nbsp;&nbsp; * time. The resulting data can be fed into<br>&nbsp;&nbsp;&nbsp; * {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static CPUUsageSnapshot makeCPUUsageSnapshot() throws SystemInfo.NegativeCPUTime {<br>&nbsp;&nbsp;&nbsp; long prCPUTime = getProcessCPUTime ();<br>&nbsp;&nbsp;&nbsp; if (prCPUTime&lt;0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new NegativeCPUTime();<br>&nbsp;&nbsp;&nbsp; return new CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ());<br>&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Computes CPU usage (fraction of 1.0) between &lt;CODE&gt;start.m_CPUTime&lt;/CODE&gt; and<br>&nbsp;&nbsp;&nbsp; * &lt;CODE&gt;end.m_CPUTime&lt;/CODE&gt; time points [1.0 corresponds to 100% utilization of<br>&nbsp;&nbsp;&nbsp; * all processors].<br>&nbsp;&nbsp;&nbsp; *<br>&nbsp;&nbsp;&nbsp; * @throws IllegalArgumentException if start and end time points are less than<br>&nbsp;&nbsp;&nbsp; * {@link #MIN_ELAPSED_TIME} ms apart.<br>&nbsp;&nbsp;&nbsp; * @throws IllegalArgumentException if either argument is null;<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static double getProcessCPUUsage (final CPUUsageSnapshot start, final CPUUsageSnapshot end) {<br>&nbsp;&nbsp;&nbsp; if (start == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalArgumentException ("null input: start");<br>&nbsp;&nbsp;&nbsp; if (end == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalArgumentException ("null input: end");<br>&nbsp;&nbsp;&nbsp; if (end.m_time &lt; start.m_time + MIN_ELAPSED_TIME)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalArgumentException ("end time must be at least " + MIN_ELAPSED_TIME + " ms later than start time");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; return ((double)(end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time);<br>&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns the PID of the current process. The result is useful when you need<br>&nbsp;&nbsp;&nbsp; * to integrate a Java app with external tools.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native int getProcessID ();<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns the number of processors on machine<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native int getCPUs ();<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns CPU (kernel + user) time used by the current process [in milliseconds].<br>&nbsp;&nbsp;&nbsp; * The returned value is adjusted for the number of processors in the system.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native long getProcessCPUTime ();<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns CPU (kernel + user) time used by the current process [in perecents].<br>&nbsp;&nbsp;&nbsp; * The returned value is either CPU percentage, or zero if this is not supported by OS.<br>&nbsp;&nbsp;&nbsp; * Currently it is supported by Solaris8, and not supported by Windows XP<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native double getProcessCPUPercentage();<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns maximum memory available in the system.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native long getMaxMem ();<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns current free memory in the system.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native long getFreeMem ();<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns system name info like "uname" command output<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native String getSysInfo ();<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns CPU usage (fraction of 1.0) so far by the current process. This is a total<br>&nbsp;&nbsp;&nbsp; * for all processors since the process creation time.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native double getProcessCPUUsage ();<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns current space allocated for the process, in Kbytes. Those pages may or may not be in memory.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native long getMemoryUsage();<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Returns current process space being resident in memory, in Kbytes.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native long getMemoryResident();<br><br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Sets the system native process PID for which all measurements will be done.<br>&nbsp;&nbsp;&nbsp; * If this method is not called then the current JVM pid will act as a default.<br>&nbsp;&nbsp;&nbsp; * Returns the native-dependent error code, or 0 in case of success.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native int setPid(int pid);<br><br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp; * Closes native-dependent process handle, if necessary.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; public static native int detachProcess();<br><br>&nbsp;&nbsp;&nbsp; // protected: .............................................................<br><br>&nbsp;&nbsp;&nbsp; // package: ...............................................................<br><br>&nbsp;&nbsp;&nbsp; // private: ...............................................................<br><br><br>&nbsp; private SystemInfo() {} // prevent subclassing<br><br>&nbsp; private static final String SILIB = "SystemInfo";<br><br>&nbsp; static {<br>&nbsp;&nbsp;&nbsp; // loading a native lib in a static initializer ensures that it is<br>&nbsp;&nbsp;&nbsp; // available done before any method in this class is called:<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.loadLibrary (SILIB);<br>&nbsp;&nbsp;&nbsp; }catch (UnsatisfiedLinkError e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("native lib '" + SILIB<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "' not found in 'java.library.path': "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + System.getProperty ("java.library.path"));<br>&nbsp;&nbsp;&nbsp; }catch (Exception e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br><br>} // end of class<br><br><br>//AppMain.java 测试文件<br>package com.khan.system;<br><br>public class AppMain {<br>&nbsp;&nbsp;&nbsp; /**<br>&nbsp;&nbsp;&nbsp;&nbsp; * Default constructor<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; public AppMain() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO: Add constructor code here<br>&nbsp;&nbsp;&nbsp; }<br><br><br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(1000);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("getMaxMem:" + SystemInfo.getMaxMem());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("getCPUs:" + SystemInfo.getCPUs());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("getSysInfo:" + SystemInfo.getSysInfo());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (Exception e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.getMessage());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>}<br><br>java部分工程文件. 等同与makefile<br>ant build.xml<br><br>&lt;project name="IpNet" default="build" basedir="."&gt;<br>&nbsp; &lt;description&gt;<br>&nbsp;&nbsp;&nbsp; simple example build file<br>&nbsp; &lt;/description&gt;<br>&nbsp; &lt;!-- set global properties for this build --&gt;<br>&nbsp; &lt;property name="name" value="IpNet"/&gt;<br>&nbsp; &lt;property name="src" location="src"/&gt;<br>&nbsp; &lt;property name="build" location="build"/&gt;<br>&nbsp; &lt;property name="dist"&nbsp; location="dist"/&gt;<br>&nbsp; &lt;property name="web"&nbsp; location="web/WEB-INF/lib"/&gt;<br><br>&nbsp; &lt;path id="master-classpath"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;fileset dir="./lib"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="*.jar"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;<br>&nbsp; &lt;/path&gt;<br><br>&nbsp; &lt;target name="init"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;tstamp/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;mkdir dir="${build}"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;mkdir dir="${dist}"/&gt;<br>&nbsp; &lt;/target&gt;<br><br>&nbsp; &lt;target name="build" depends="init" description="compile the source " &gt;<br>&nbsp;&nbsp;&nbsp; &lt;javac srcdir="${src}" destdir="${build}"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;compilerarg value="-Xlint:unchecked"/&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;compilerarg value="-deprecation"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpath refid="master-classpath"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/javac&gt;<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;copy todir="${build}" preservelastmodified="true"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir="${src}"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="*.class"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/copy&gt;<br>&nbsp;&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; &lt;jar jarfile="${dist}/${name}.jar" compress="true"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir="${build}"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="**"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/jar&gt;<br><br>&nbsp;&nbsp;&nbsp; &lt;copy todir="${web}" &gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir="${dist}"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="${name}.jar"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/copy&gt;<br>&nbsp; &lt;/target&gt;<br>&nbsp;<br>&nbsp; &lt;target name="clean" description="clean up" &gt;<br>&nbsp;&nbsp;&nbsp; &lt;delete dir="${build}"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;delete dir="${dist}"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;delete file="${web}/${name}.jar"/&gt;<br>&nbsp; &lt;/target&gt;<br>&lt;/project&gt;<br><br>在工程目录下ant 编译工程<br>build目录为本工程目标二进制文件目录. 编译后的class在此目录下<br>然后到build目录下<br>javah javah -jni com.khan.system.SystemInfo //注意, 一定要使用包全路径. 如果不是default包的话.<br>会在此目录下生成3个.h文件<br>com_khan_system_SystemInfo.h<br>com_khan_system_SystemInfo_CPUUsageSnapshot.h<br>com_khan_system_SystemInfo_NegativeCPUTime.h<br><br><br>java这边的准备工作完成<br><br>接下来处理c部分<br>新建一个c工程. 我用gcc的. 所以这些部分我手工完成的<br>将刚刚的.h文件实现<br><br>/* ------------------------------------------------------------------------- */<br>/*<br>&nbsp;* An implementation of JNI methods in com.vladium.utils.SystemInformation<br>&nbsp;* class. The author compiled it using Microsoft Visual C++ and GCC for Win32 but the code<br>&nbsp;* should be easy to use with any compiler for win32 platform.<br>&nbsp;*<br>&nbsp;* For simplicity, this implementaion assumes JNI 1.2+ and omits error handling.<br>&nbsp;*<br>&nbsp;* Enhanced by Peter V. Mikhalenko (C) 2004, Deutsche Bank [peter@mikhalenko.com]<br>&nbsp;* Original source (C) 2002, Vladimir Roubtsov [vlad@trilogy.com]<br>&nbsp;*/<br>/* ------------------------------------------------------------------------- */<br><br><br>#include &lt;windows.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;process.h&gt;<br>#include &lt;winbase.h&gt;<br>#include &lt;psapi.h&gt;<br>#include &lt;string.h&gt;<br><br><br>#include "include/com_khan_system_SystemInfo.h"<br><br><br><br>static jint s_PID;<br>static HANDLE s_currentProcess;<br>static int alreadyDetached;<br>static int s_numberOfProcessors;<br>static SYSTEM_INFO systemInfo;<br>static WORD processorArchitecture;<br>static DWORD pageSize;<br>static DWORD processorType;<br>static WORD processorLevel;<br>static WORD processorRevision;<br><br>#define INFO_BUFFER_SIZE 32768<br>#define BUFSIZE 2048<br><br>//BOOL flll = TRUE;<br>/* ------------------------------------------------------------------------- */<br><br>/*<br>&nbsp;* A helper function for converting FILETIME to a LONGLONG [safe from memory<br>&nbsp;* alignment point of view].<br>&nbsp;*/<br>static LONGLONG fileTimeToInt64 (const FILETIME * time)<br>{<br>&nbsp;&nbsp;&nbsp; ULARGE_INTEGER _time;<br><br>&nbsp;&nbsp;&nbsp; _time.LowPart = time-&gt;dwLowDateTime;<br>&nbsp;&nbsp;&nbsp; _time.HighPart = time-&gt;dwHighDateTime;<br><br>&nbsp;&nbsp;&nbsp; return _time.QuadPart;<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* This method was added in JNI 1.2. It is executed once before any other<br>&nbsp;* methods are called and is ostensibly for negotiating JNI spec versions, but<br>&nbsp;* can also be conveniently used for initializing variables that will not<br>&nbsp;* change throughout the lifetime of this process.<br>&nbsp;*/<br>JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved)<br>{<br>&nbsp; s_PID = _getpid ();<br>&nbsp; s_currentProcess = GetCurrentProcess ();<br>&nbsp; //externalCPUmon = 0;<br>&nbsp; alreadyDetached = 0;<br><br>&nbsp; GetSystemInfo (&amp;systemInfo);<br>&nbsp; s_numberOfProcessors = systemInfo.dwNumberOfProcessors;<br>&nbsp; processorArchitecture = systemInfo.wProcessorArchitecture;<br>&nbsp; pageSize = systemInfo.dwPageSize;<br>&nbsp; processorType = systemInfo.dwProcessorType;<br>&nbsp; processorLevel = systemInfo.wProcessorLevel;<br>&nbsp; processorRevision = systemInfo.wProcessorRevision;<br>&nbsp; printf("SystemInfo.dll is Loaded");<br>&nbsp; return JNI_VERSION_1_2;<br>}<br>/* ......................................................................... */<br><br>JNIEXPORT void JNICALL<br>JNI_OnUnload (JavaVM * vm, void * reserved)<br>{<br>&nbsp; if (!alreadyDetached &amp;&amp; s_currentProcess!=NULL) {<br>&nbsp;&nbsp;&nbsp; CloseHandle(s_currentProcess);<br>&nbsp;&nbsp;&nbsp; printf("[JNI Unload] Detached from native process.");<br>&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp; }<br>&nbsp; printf("SystemInfo.dll is UnLoaded");<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getCPUs<br>&nbsp;* Signature: ()I<br>&nbsp;*/<br>JNIEXPORT jint JNICALL Java_com_khan_system_SystemInfo_getCPUs(JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; return (jint)s_numberOfProcessors;<br>}<br>/* ......................................................................... */<br><br><br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getProcessID<br>&nbsp;* Signature: ()I<br>&nbsp;*/<br>JNIEXPORT jint JNICALL<br>Java_com_khan_system_SystemInfo_getProcessID(JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; return s_PID;<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; setPid<br>&nbsp;* Signature: ()I<br>&nbsp;*/<br>JNIEXPORT jint JNICALL<br>Java_com_khan_system_SystemInfo_setPid(JNIEnv * env, jclass cls, jint pid)<br>{<br>&nbsp;&nbsp;&nbsp; DWORD errCode;<br>&nbsp;&nbsp;&nbsp; LPVOID lpMsgBuf;<br>&nbsp;&nbsp;&nbsp; s_PID = pid;<br>&nbsp;&nbsp;&nbsp; s_currentProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);<br>&nbsp;&nbsp;&nbsp; if (s_currentProcess==NULL) {<br>&nbsp;&nbsp;&nbsp;&nbsp; errCode = GetLastError();<br>&nbsp;&nbsp;&nbsp;&nbsp; FormatMessage(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FORMAT_MESSAGE_ALLOCATE_BUFFER |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FORMAT_MESSAGE_FROM_SYSTEM,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errCode,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPTSTR) &amp;lpMsgBuf,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0, NULL );<br>&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; printf("[CPUmon] Could not attach to native process. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);<br>&nbsp;&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp; LocalFree(lpMsgBuf);<br>&nbsp;&nbsp;&nbsp;&nbsp; return errCode;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; printf("[CPUmon] Attached to native process.");<br>&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; detachProcess<br>&nbsp;* Signature: ()I<br>&nbsp;*/<br>JNIEXPORT jint JNICALL<br>Java_com_khan_system_SystemInfo_detachProcess(JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; if (!alreadyDetached &amp;&amp; s_currentProcess!=NULL) {<br>&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(s_currentProcess);<br>&nbsp;&nbsp;&nbsp;&nbsp; alreadyDetached = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp; printf("[CPUmon] Detached from native process.");<br>&nbsp;&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getProcessCPUTime<br>&nbsp;* Signature: ()J<br>&nbsp;*/<br>JNIEXPORT jlong JNICALL<br>Java_com_khan_system_SystemInfo_getProcessCPUTime (JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; FILETIME creationTime, exitTime, kernelTime, userTime;<br>&nbsp;&nbsp;&nbsp; DWORD errCode;<br>&nbsp;&nbsp;&nbsp; LPVOID lpMsgBuf;<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; BOOL resultSuccessful = GetProcessTimes (s_currentProcess, &amp; creationTime, &amp; exitTime, &amp; kernelTime, &amp; userTime);<br>&nbsp;&nbsp;&nbsp; if (!resultSuccessful) {<br>&nbsp;&nbsp;&nbsp;&nbsp; errCode = GetLastError();<br>&nbsp;&nbsp;&nbsp;&nbsp; FormatMessage(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FORMAT_MESSAGE_ALLOCATE_BUFFER |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FORMAT_MESSAGE_FROM_SYSTEM,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errCode,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPTSTR) &amp;lpMsgBuf,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0, NULL );<br>&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);<br><br>&nbsp;&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp; LocalFree(lpMsgBuf);<br>&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; return (jlong) ((fileTimeToInt64 (&amp; kernelTime) + fileTimeToInt64 (&amp; userTime)) /<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (s_numberOfProcessors * 10000));<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getMaxMem<br>&nbsp;* Signature: ()J<br>&nbsp;*/<br>JNIEXPORT jlong JNICALL<br>Java_com_khan_system_SystemInfo_getMaxMem(JNIEnv * env, jclass cls)<br>{<br>&nbsp;MEMORYSTATUS stat;<br>&nbsp;GlobalMemoryStatus (&amp;stat);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (jlong)(stat.dwTotalPhys/1024);<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getFreeMem<br>&nbsp;* Signature: ()J<br>&nbsp;*/<br>JNIEXPORT jlong JNICALL<br>Java_com_khan_system_SystemInfo_getFreeMem (JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MEMORYSTATUS stat;<br>&nbsp;GlobalMemoryStatus (&amp;stat);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (jlong)(stat.dwAvailPhys/1024);<br>}<br>/* ......................................................................... */<br><br><br>/* define min elapsed time (in units of 10E-7 sec): */<br>#define MIN_ELAPSED_TIME (10000)<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getProcessCPUUsage<br>&nbsp;* Signature: ()D<br>&nbsp;*/<br>JNIEXPORT jdouble JNICALL<br>Java_com_khan_system_SystemInfo_getProcessCPUUsage(JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; FILETIME creationTime, exitTime, kernelTime, userTime, nowTime; <br>&nbsp;&nbsp;&nbsp; LONGLONG elapsedTime;<br>&nbsp;&nbsp;&nbsp; DWORD errCode;<br>&nbsp;&nbsp;&nbsp; LPVOID lpMsgBuf;<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; BOOL resultSuccessful = GetProcessTimes (s_currentProcess, &amp; creationTime, &amp; exitTime, &amp; kernelTime, &amp; userTime);<br>&nbsp;&nbsp;&nbsp; if (!resultSuccessful) {<br>&nbsp;&nbsp;&nbsp;&nbsp; errCode = GetLastError();<br>&nbsp;&nbsp;&nbsp;&nbsp; FormatMessage(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errCode,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPTSTR) &amp;lpMsgBuf,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0, NULL );<br>&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);<br>&nbsp;&nbsp;&nbsp;&nbsp; fflush(stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp; LocalFree(lpMsgBuf);<br>&nbsp;&nbsp;&nbsp;&nbsp; return -1.0;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; GetSystemTimeAsFileTime (&amp; nowTime);<br><br>&nbsp;&nbsp;&nbsp; /*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NOTE: win32 system time is not very precise [~10ms resolution], use<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sufficiently long sampling intervals if you make use of this method.<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; elapsedTime = fileTimeToInt64 (&amp; nowTime) - fileTimeToInt64 (&amp; creationTime);<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; if (elapsedTime &lt; MIN_ELAPSED_TIME)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0.0;<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((jdouble) (fileTimeToInt64 (&amp; kernelTime) + fileTimeToInt64 (&amp; userTime))) /<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (s_numberOfProcessors * elapsedTime);<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getProcessCPUPercentage<br>&nbsp;* Signature: ()D<br>&nbsp;*/<br>JNIEXPORT jdouble JNICALL<br>Java_com_khan_system_SystemInfo_getProcessCPUPercentage (JNIEnv * env, jclass cls)<br>{<br>&nbsp;// Not implemented on Windows<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (jdouble)(-1.0);<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getMemoryUsage<br>&nbsp;* Signature: ()J<br>&nbsp;*/<br>JNIEXPORT jlong JNICALL<br>Java_com_khan_system_SystemInfo_getMemoryUsage (JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; PROCESS_MEMORY_COUNTERS pmc;<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; if ( GetProcessMemoryInfo( s_currentProcess, &amp;pmc, sizeof(pmc)) )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;return (jlong)(pmc.PagefileUsage/1024);<br>&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;return (jlong)(0);<br>&nbsp;&nbsp;&nbsp; }<br>}<br>/* ......................................................................... */<br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method: getMemoryResident * Signature: ()J<br>*/<br>JNIEXPORT jlong JNICALL<br>Java_com_khan_system_SystemInfo_getMemoryResident(JNIEnv * env, jclass cls)<br>{<br>&nbsp;&nbsp;&nbsp; PROCESS_MEMORY_COUNTERS pmc;<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; if ( GetProcessMemoryInfo( s_currentProcess, &amp;pmc, sizeof(pmc)) )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (jlong)(pmc.WorkingSetSize/1024);<br>&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (jlong)(0);<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br><br>/*<br>&nbsp;* Class:&nbsp;&nbsp;&nbsp;&nbsp; com_vladium_utils_SystemInformation<br>&nbsp;* Method:&nbsp;&nbsp;&nbsp; getSysInfo<br>&nbsp;* Signature: ()S<br>&nbsp;*/<br>JNIEXPORT jstring JNICALL<br>Java_com_khan_system_SystemInfo_getSysInfo(JNIEnv * env, jclass cls)<br>{<br>&nbsp; char buf[2048];<br>&nbsp; char buf2[512];<br>&nbsp; jstring retval;<br>&nbsp; OSVERSIONINFOEX osvi;<br>&nbsp; BOOL bOsVersionInfoEx;<br>&nbsp; TCHAR infoBuf[INFO_BUFFER_SIZE];<br><br>&nbsp; DWORD bufCharCount = INFO_BUFFER_SIZE;<br>&nbsp; *buf = 0; //c语言. 变量定义所有代码在前<br>&nbsp; *buf2 = 0;<br>&nbsp; ZeroMemory(&amp;osvi, sizeof(OSVERSIONINFOEX));<br>&nbsp; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);<br>&nbsp; if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &amp;osvi)) )<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);<br>&nbsp;&nbsp;&nbsp; if (! GetVersionEx ( (OSVERSIONINFO *) &amp;osvi) ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Return empty string in case of problems<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto next_label;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; &nbsp;<br>&nbsp; switch (osvi.dwPlatformId)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; // Test for the Windows NT product family.<br>&nbsp;&nbsp;&nbsp; case VER_PLATFORM_WIN32_NT:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Test for the specific product.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.dwMajorVersion == 5 &amp;&amp; osvi.dwMinorVersion == 2 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"WinServer2003, ");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.dwMajorVersion == 5 &amp;&amp; osvi.dwMinorVersion == 1 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"WinXP ");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.dwMajorVersion == 5 &amp;&amp; osvi.dwMinorVersion == 0 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Win2K ");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.dwMajorVersion &lt;= 4 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"WinNT ");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Display service pack (if any) and build number.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( osvi.dwMajorVersion == 4 &amp;&amp; lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HKEY hKey;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG lRet;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Test for SP6 versus SP6a.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWAREMicrosoftWindows NTCurrentVersionHotfixQ246009", 0, KEY_QUERY_VALUE, &amp;hKey );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( lRet == ERROR_SUCCESS ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buf2, "SP 6a (Build %d), ", (int)(osvi.dwBuildNumber &amp; 0xFFFF) );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,buf2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else // Windows NT 4.0 prior to SP6a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buf2, "%s (Build %d), ",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osvi.szCSDVersion,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (int)(osvi.dwBuildNumber &amp; 0xFFFF));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,buf2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RegCloseKey( hKey );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else // not Windows NT 4.0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buf2, "%s (Build %d), ", osvi.szCSDVersion, (int)(osvi.dwBuildNumber &amp; 0xFFFF));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,buf2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Test for the Windows Me/98/95.<br>&nbsp;&nbsp;&nbsp; case VER_PLATFORM_WIN32_WINDOWS:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (osvi.dwMajorVersion == 4 &amp;&amp; osvi.dwMinorVersion == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Win95 ");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"OSR2 " );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (osvi.dwMajorVersion == 4 &amp;&amp; osvi.dwMinorVersion == 10)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Win98 ");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( osvi.szCSDVersion[1] == 'A' )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"SE " );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (osvi.dwMajorVersion == 4 &amp;&amp; osvi.dwMinorVersion == 90)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"WinME ");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br><br>&nbsp;&nbsp;&nbsp; case VER_PLATFORM_WIN32s:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Win32s ");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp; }<br>&nbsp; &nbsp;<br>next_label:<br><br>&nbsp; strcat(buf,"on ");<br>&nbsp; // Get and display the name of the computer.<br>&nbsp; bufCharCount = INFO_BUFFER_SIZE;<br>&nbsp; if( !GetComputerName( infoBuf, &amp;bufCharCount ) )<br>&nbsp;&nbsp;&nbsp; goto next_label_2;<br>&nbsp; strcat(buf, infoBuf );<br>&nbsp; <br>next_label_2:<br>&nbsp; strcat(buf," (");<br>&nbsp; if (!(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS &amp;&amp; osvi.dwMajorVersion == 4 &amp;&amp; osvi.dwMinorVersion == 0)) {<br>&nbsp;&nbsp;&nbsp; // Win95 does not keep CPU info in registry<br>&nbsp;&nbsp;&nbsp; LONG lRet;<br>&nbsp;&nbsp;&nbsp; HKEY hKey;<br>&nbsp;&nbsp;&nbsp; char szOrigCPUType[BUFSIZE];<br>&nbsp;&nbsp;&nbsp; int i=0;<br>&nbsp;&nbsp;&nbsp; DWORD dwBufLen=BUFSIZE;<br>&nbsp;&nbsp;&nbsp; lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWAREDESCRIPTIONSystemCentralProcessor", 0, KEY_QUERY_VALUE, &amp;hKey );<br>&nbsp;&nbsp;&nbsp; if( lRet != ERROR_SUCCESS ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto next_label_3;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; lRet = RegQueryValueEx( hKey, "ProcessorNameString", NULL, NULL, (LPBYTE) szOrigCPUType, &amp;dwBufLen);<br>&nbsp;&nbsp;&nbsp; if( (lRet != ERROR_SUCCESS) || (dwBufLen &gt; BUFSIZE) ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto next_label_3;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; RegCloseKey( hKey );<br><br>&nbsp;&nbsp;&nbsp; if (strlen(szOrigCPUType)&gt;0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(szOrigCPUType[i]==' ' &amp;&amp; szOrigCPUType[i]!=0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i++;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,szOrigCPUType+i);<br>&nbsp;&nbsp;&nbsp; } else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto next_label_3;<br>&nbsp; } else {<br>next_label_3:<br>&nbsp;&nbsp; if (processorArchitecture==PROCESSOR_ARCHITECTURE_UNKNOWN)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"unknown_arch");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) {<br>&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Intel ");<br>&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buf2,"level %d ",processorLevel);<br>&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,buf2);<br>&nbsp;&nbsp; } else if (processorArchitecture==PROCESSOR_ARCHITECTURE_IA64)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"IA64 ");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_MIPS)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"MIPS ");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Alpha ");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_PPC)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"PowerPC ");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_SHX)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"SHX ");<br>&nbsp;&nbsp; else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA64)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"Alpha64 ");<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(buf,"unknown_arch ");<br>&nbsp; }<br>&nbsp; <br>&nbsp; strcat(buf,")");<br><br>&nbsp; retval = (*env)-&gt;NewStringUTF(env,buf);<br>&nbsp; return retval;<br>}<br>/* ......................................................................... */<br><br><br><br><br><br><br>#undef MIN_ELAPSED_TIME<br><br>/* ------------------------------------------------------------------------- */<br>/* end of file */<br><br><br><br><br><br>编写makefile<br>#&nbsp;&nbsp;&nbsp; Project: SystemInfo<br>#&nbsp;&nbsp;&nbsp; Makefile created by Khan.Lau<br>#&nbsp;&nbsp;&nbsp; Write&nbsp;&nbsp;&nbsp; by 2007-05-16<br><br><br>#&nbsp;&nbsp;&nbsp; 应用程序名<br>#LIB = SystemInfo.a<br>DLL =&nbsp;&nbsp;&nbsp; SystemInfo.dll<br>#BIN = SystemInfo.exe<br><br><br>#&nbsp;&nbsp;&nbsp; 输出目录<br>#&nbsp;&nbsp;&nbsp; CONFIGURATION = debug<br>CONFIGURATION&nbsp;&nbsp;&nbsp; =&nbsp;&nbsp;&nbsp; release<br><br>#&nbsp;&nbsp;&nbsp; 取得项目的当前工作路径<br>PROJECT_PATH = "D:/Project/Cplus/SystemInfo/src"<br><br>CPP = g++<br>CC = gcc<br>COMPILER = $(CC)<br><br>#&nbsp;&nbsp;&nbsp; c/c++库路径<br>LIBPATH = "D:/Develop/CPlus/MinGW/lib"<br><br>WINDRES = windres.exe<br>RES =<br><br>#&nbsp;&nbsp;&nbsp; 包路径<br>LIBS = -L$(LIBPATH) \<br>&nbsp;&nbsp;&nbsp; -lpsapi<br><br>INCS = -I$(LIBPATH)/include \<br>&nbsp;&nbsp;&nbsp; -ID:/Develop/Java/jdk1.5.0_02/include \<br>&nbsp;&nbsp;&nbsp; -ID:/Develop/Java/jdk1.5.0_02/include/win32 \<br>&nbsp;&nbsp;&nbsp; -I$(PROJECT_PATH)<br><br>CXXINCS = -I$(LIBPATH)/include \<br>&nbsp;&nbsp;&nbsp; -I$(LIBPATH)/include/c++/3.2.3 \<br>&nbsp;&nbsp;&nbsp; -I$(LIBPATH)/include/c++/3.2.3/backward \<br>&nbsp;&nbsp;&nbsp; -I$(LIBPATH)/include/c++/3.2.3/mingw32 \<br>&nbsp;&nbsp;&nbsp; -I$(PROJECT_PATH)<br><br>DLLFLAGS = -DBUILD_DLL<br>CXXFLAGS = $(DLLFLAGS) -g -Wall $(CXXINCS)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br>CFLAGS = $(DLLFLAGS) -Wall $(INCS)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br><br>COMPILER_FLAG = $(CFLAGS)<br><br>RM = rm -f<br><br>LINKOBJ = $(CONFIGURATION)/SystemInfo.o&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(RES)<br><br><br>.PHONY:&nbsp;&nbsp;&nbsp; all all-before all-after clean clean-custom rebuild&nbsp; &nbsp;<br><br>all: all-before $(DLL) all-after<br><br>clean: clean-custom<br>&nbsp;&nbsp;&nbsp; ${RM} $(LINKOBJ) $(CONFIGURATION)/$(DLL)&nbsp; &nbsp;<br><br>$(LIB): $(LINKOBJ)<br>&nbsp;&nbsp;&nbsp; ar -r $(CONFIGURATION)/$(LIB) $(LINKOBJ)&nbsp; &nbsp;<br><br>$(DLL): $(LINKOBJ)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(COMPILER)&nbsp; -shared -Wl,--add-stdcall-alias&nbsp; -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)<br><br>$(BIN):&nbsp;&nbsp;&nbsp; $(LINKOBJ)<br>&nbsp;&nbsp;&nbsp; $(COMPILER) -o $(CONFIGURATION)/$(BIN) $(LINKOBJ) $(LIBS)<br><br>#缩减可执行文件大小<br>strip:&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; strip&nbsp;&nbsp;&nbsp; $(CONFIGURATION)/$(LIB)<br>&nbsp; &nbsp;<br><br>################################################################################<br><br>$(CONFIGURATION)/SystemInfo.o: src/dll/SystemInfo.c<br>&nbsp;&nbsp;&nbsp; $(COMPILER) -c src/dll/SystemInfo.c -o $(CONFIGURATION)/SystemInfo.o $(COMPILER_FLAG)<br><br><br>################################################################################<br><br>rebuild: clean&nbsp;&nbsp;&nbsp; all<br><br><br><br>makefile中注意<br>$(DLL): $(LINKOBJ)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(COMPILER)&nbsp; -shared -Wl,--add-stdcall-alias&nbsp; -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)<br><br>-shared -Wl,--add-stdcall-alias 这3个参数是一定要的. 具体含义请参阅gcc帮助..<br>否则会出现如下异常:java.lang.UnsatisfiedLinkError<br>如果你确认自己的dll名没有错. loadlibrary的名字也没有填错. 那应该就要检查如上部分了<br><br>实际发布的时候. 不要使用调试版本. 也就是编译参数不能有-g<br><br>ok, 现在make出dll使用吧....<br><br><br>我本地测试的输出结果为 :<br><br>getMaxMem:506604<br>getCPUs:1<br>getSysInfo:WinXP Service Pack 2 (Build 2600), on A7648944D08843B (Intel level 15 )<br>SystemInfo.dll is Loaded<img src ="http://www.cppblog.com/Khan/aggbug/54364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-06-23 12:57 <a href="http://www.cppblog.com/Khan/archive/2008/06/23/54364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubuntu 下安装wine</title><link>http://www.cppblog.com/Khan/archive/2008/05/23/50909.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Fri, 23 May 2008 15:18:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/05/23/50909.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/50909.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/05/23/50909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/50909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/50909.html</trackback:ping><description><![CDATA[编译源码的方式就不写了， 无非就是解决依赖关系， down一堆的包， 然后make<br>简单粗暴的来......<br><br>1.安装<br>sudo apt-get install <span class="hilite1">wine<br><br>2.初始化<br>winecfg&nbsp; //不要用root模式, 也就是不要用sudo<br><br>如果出现以下警告或者错误:<br></span><span class="postbody">preloader: Warning: failed to reserve range 00000000-60000000
<br>
err:dosmem:setup_dos_mem Cannot use first megabyte for DOS address space, please report
</span><br><br>解决方法: 其实我不清楚为什么要这么做....唉.....<br><span class="postbody">sudo sysctl -w vm.mmap_min_addr=0
<br>
<br>
然后打开sysctl.conf
<br>
sudo gedit /etc/sysctl.conf
<br>
<br>
#vm.mmap_min_addr = 65536&nbsp;
//注释掉这行<br>
vm.mmap_min_addr = 0&nbsp;
//改为这行</span><br><span class="hilite1"><br><br></span>
<p>3、设置中文问题</p>
<p>&nbsp;&nbsp; 先把字体simsun.ttc（在你的windows的<span class="hilite2">安装</span>目录里的font文件夹里找，找不到可以从网上下到） 复制到 /home/你的用户名/.<span class="hilite1">wine</span>/drive_c/windows/fonts 文件夹中，<span style="color: #ff0000; font-size: small;">要显示隐藏文件夹按Ctrl+H</span>
</p>
<br>
<p>&nbsp; 修改注册表，在命令行输入 gedit&nbsp; ~/.<span class="hilite1">wine</span>/system.reg</p>
<p>&nbsp; 找到&#8220;[System\\CurrentControlSet\\Hardware
Profiles\\Current\\Software\\Fonts]&#8221;，将其中的&#8220;&#8220;LogPixels&#8221;=dword:00000060&#8221;改成
&#8220;&#8220;LogPixels&#8221;=dword:00000070&#8220;。<br>
<br>
再找到&#8221;[Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes] xxxx&#8220;项，将其中的&#8221;MS Shell Dlg&#8220;相关的两项修改成如下内容（即更换字体为宋体）：<br>
<br>
&#8220;MS Shell Dlg&#8221;=&#8221;SimSun&#8221;<br>
&#8220;MS Shell Dlg 2&#8243;=&#8221;SimSun&#8221;<br>
<br>
然后：gedit ~/.<span class="hilite1">wine</span>/drive_c/windows/win.ini</p>
<p>在其中加上（如果没有），有的话修改成如下</p>
<p> [Desktop]<br>
menufontsize=13<br>
messagefontsize=13<br>
statusfontsize=13<br>
IconTitleSize=13</p>
<p>现在中文显示应该正常了</p>
<br><span class="hilite1"><br></span><img src ="http://www.cppblog.com/Khan/aggbug/50909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-05-23 23:18 <a href="http://www.cppblog.com/Khan/archive/2008/05/23/50909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下执行java的脚本</title><link>http://www.cppblog.com/Khan/archive/2008/05/06/49008.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Tue, 06 May 2008 07:26:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/05/06/49008.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/49008.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/05/06/49008.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/49008.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/49008.html</trackback:ping><description><![CDATA[<br><font face="monospace"><font color="#0000ff">#!/bin/sh</font><br><font color="#0000ff"># Filename : StockDispatch</font><br><font color="#0000ff"># &amp; nohub</font><br># 思路: 遍历当前目录和$JAVA_HOME/lib下所有的jar文件, 加入-cp的环境变量 然后执行入口类<br><font color="#008080">SETCOLOR_BOLD</font>=<font color="#804040"><strong>"</strong></font><font color="#ff00ff">echo -en </font><font color="#6a5acd">\\</font><font color="#ff00ff">033[1;32m</font><font color="#804040"><strong>"</strong></font><br><font color="#008080">SETCOLOR_NORMAL</font>=<font color="#804040"><strong>"</strong></font><font color="#ff00ff">echo -en </font><font color="#6a5acd">\\</font><font color="#ff00ff">033[0;39m</font><font color="#804040"><strong>"</strong></font><br><br><font color="#008080"><br>CLASSPATH</font>=<font color="#804040"><strong>""</strong></font><br><font color="#008080">CURRDIR</font>=<font color="#804040"><strong>"</strong></font><span style="background-color: #ff0000;"><font color="#ffffff">$(</font></span><font color="#804040"><strong>pwd</strong></font><span style="background-color: #ff0000;"><font color="#ffffff">)</font></span><font color="#804040"><strong>"</strong></font><br><font color="#008080">LIBDIR</font>=<font color="#804040"><strong>"</strong></font><font color="#a020f0">$CURRDIR</font><font color="#ff00ff">&nbsp;/usr/local/jdk1.5.0_02/lib</font><font color="#804040"><strong>"</strong></font><br><font color="#008080">tmpFile</font>=./<font color="#ff00ff">11</font><br><font color="#008080">pidFile</font>=./<font color="#a020f0">${</font><font color="#a020f0">0</font><font color="#a020f0">}</font>pid<br><br><font color="#0000ff"># find all jar library from current dir and CLASSPATH</font><br>find <font color="#a020f0">$LIBDIR</font>&nbsp;<font color="#6a5acd">-name</font>&nbsp;<font color="#804040"><strong>"</strong></font><font color="#ff00ff">*.jar</font><font color="#804040"><strong>"</strong></font><font color="#804040"><strong>&gt;</strong></font><font color="#a020f0">$tmpFile</font><br><br><br><font color="#0000ff"># add jar library to CLASSPATH</font><br><font color="#008080">I</font>=<font color="#ff00ff">0</font><br><font color="#804040"><strong>while</strong></font><font color="#804040"><strong>&nbsp;</strong></font><font color="#804040"><strong>read</strong></font><font color="#804040"><strong>&nbsp;line </strong></font><br><font color="#804040"><strong>do</strong></font>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008080">I</font>=<font color="#6a5acd">`expr </font><font color="#a020f0">$I</font><font color="#6a5acd">&nbsp;+ </font><font color="#ff00ff">1</font><font color="#6a5acd">&nbsp;`</font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>if</strong></font>&nbsp;<font color="#804040"><strong>[</strong></font>&nbsp;<font color="#a020f0">$I</font>&nbsp;<font color="#804040"><strong>-eq</strong></font>&nbsp;<font color="#ff00ff">1</font>&nbsp;<font color="#804040"><strong>]</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>then</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008080">CLASSPATH</font>=<font color="#804040"><strong>"</strong></font><font color="#a020f0">${</font><font color="#a020f0">line</font><font color="#a020f0">}</font><font color="#804040"><strong>"</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>else</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008080">CLASSPATH</font>=<font color="#804040"><strong>"</strong></font><font color="#a020f0">${</font><font color="#a020f0">CLASSPATH</font><font color="#a020f0">}</font><font color="#ff00ff">:</font><font color="#a020f0">${</font><font color="#a020f0">line</font><font color="#a020f0">}</font><font color="#804040"><strong>"</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>fi</strong></font><br><font color="#804040"><strong>done</strong></font><font color="#804040"><strong>&lt;</strong></font>&nbsp;<font color="#a020f0">$tmpFile</font><br><br>rm <font color="#a020f0">$tmpFile</font><br><br><br><font color="#0000ff"># run program</font><br><font color="#804040"><strong>if</strong></font>&nbsp;<font color="#804040"><strong>[</strong></font>&nbsp;<font color="#804040"><strong>"</strong></font><font color="#ff00ff">-</font><font color="#a020f0">$1</font><font color="#804040"><strong>"</strong></font>&nbsp;<font color="#804040"><strong>!=</strong></font>&nbsp;<font color="#804040"><strong>"</strong></font><font color="#ff00ff">-</font><font color="#804040"><strong>"</strong></font>&nbsp;<font color="#804040"><strong>]</strong></font><font color="#804040"><strong>;</strong></font>&nbsp;<font color="#804040"><strong>then</strong></font>&nbsp;&nbsp; <font color="#0000ff"># if parameter 1 is not null</font><br>&nbsp;&nbsp;<font color="#804040"><strong>echo</strong></font><font color="#ff00ff">&nbsp;</font><font color="#804040"><strong>"</strong></font><font color="#ff00ff">java -cp .:</font><font color="#a020f0">${</font><font color="#a020f0">CLASSPATH</font><font color="#a020f0">}</font><font color="#ff00ff">&nbsp;&nbsp;com.khan.AppMain.UpdateCell2CBC </font><font color="#a020f0">$1</font><font color="#ff00ff">&nbsp;&gt; updatecell2cbc.log</font><font color="#804040"><strong>"</strong></font><br><font color="#0000ff">#&nbsp;&nbsp;java -cp .:${CLASSPATH} com.khan.AppMain.UpdateCell2CBC $1&gt; updatecell2cbc.log</font><br><font color="#804040"><strong>else</strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#804040"><strong>echo</strong></font><font color="#ff00ff">&nbsp;</font><font color="#804040"><strong>"</strong></font><font color="#ff00ff">&nbsp;&nbsp;usage: </font><font color="#a020f0">$0</font><font color="#ff00ff">&nbsp;&nbsp;CellListFile</font><font color="#804040"><strong>"</strong></font><br><font color="#804040"><strong>fi</strong></font><br><br><br></font><img src ="http://www.cppblog.com/Khan/aggbug/49008.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-05-06 15:26 <a href="http://www.cppblog.com/Khan/archive/2008/05/06/49008.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>epoll简介(转载)</title><link>http://www.cppblog.com/Khan/archive/2008/04/02/46015.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Wed, 02 Apr 2008 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/04/02/46015.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/46015.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/04/02/46015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/46015.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/46015.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Epoll  epoll_event epoll_wait epoll_ctl epoll_create&nbsp;&nbsp;<a href='http://www.cppblog.com/Khan/archive/2008/04/02/46015.html'>阅读全文</a><img src ="http://www.cppblog.com/Khan/aggbug/46015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-04-02 11:58 <a href="http://www.cppblog.com/Khan/archive/2008/04/02/46015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Epoll模型</title><link>http://www.cppblog.com/Khan/archive/2008/04/02/46013.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Wed, 02 Apr 2008 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/04/02/46013.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/46013.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/04/02/46013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/46013.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/46013.html</trackback:ping><description><![CDATA[&nbsp;Linux 2.6内核中提高网络I/O性能的新方法-epoll I/O多路复用技术在比较多的TCP网络服务器中有使用，即比较多的用到select函数。<br><br>1、为什么select落后<br>&nbsp;&nbsp;&nbsp; 首先，在Linux内核中，select所用到的FD_SET是有限的，即内核中有个参数__FD_SETSIZE定义了每个FD_SET的句柄个数，在我用的2.6.15-25-386内核中，该值是1024，搜索内核源代码得到：<br>include/linux/posix_types.h:<br>#define __FD_SETSIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1024<br>也就是说，如果想要同时检测1025个句柄的可读状态是不可能用select实现的。或者同时检测1025个句柄的可写状态也是不可能的。其次，内核中实现 select是用轮询方法，即每次检测都会遍历所有FD_SET中的句柄，显然，select函数执行时间与FD_SET中的句柄个数有一个比例关系，即 select要检测的句柄数越多就会越费时。当然，在前文中我并没有提及poll方法，事实上用select的朋友一定也试过poll，我个人觉得 select和poll大同小异，个人偏好于用select而已。<br><br>2、内核中提高I/O性能的新方法epoll<br>&nbsp;&nbsp;&nbsp; epoll是什么？按照man手册的说法：是为处理大批量句柄而作了改进的poll。要使用epoll只需要这三个系统调用：epoll_create(2)， epoll_ctl(2)， epoll_wait(2)。<br>当然，这不是2.6内核才有的，它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44)<br><br>Linux2.6内核epoll介绍<br>&nbsp;&nbsp;&nbsp; 先介绍2本书《The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel》，以2.4内核讲解Linux TCP/IP实现，相当不错.作为一个现实世界中的实现，很多时候你必须作很多权衡，这时候参考一个久经考验的系统更有实际意义。举个例子,linux内核中sk_buff结构为了追求速度和安全，牺牲了部分内存，所以在发送TCP包的时候，无论应用层数据多大,sk_buff最小也有272的字节.其实对于socket应用层程序来说，另外一本书《UNIX Network Programming Volume 1》意义更大一点.2003年的时候，这本书出了最新的第3版本，不过主要还是修订第2版本。其中第6章《I/O Multiplexing》是最重要的。Stevens给出了网络IO的基本模型。在这里最重要的莫过于select模型和Asynchronous I/O模型.从理论上说，AIO似乎是最高效的，你的IO操作可以立即返回，然后等待os告诉你IO操作完成。但是一直以来，如何实现就没有一个完美的方案。最著名的windows完成端口实现的AIO,实际上也是内部用线程池实现的罢了，最后的结果是IO有个线程池，你应用也需要一个线程池...... 很多文档其实已经指出了这带来的线程context-switch带来的代价。在linux 平台上，关于网络AIO一直是改动最多的地方，2.4的年代就有很多AIO内核patch,最著名的应该算是SGI那个。但是一直到2.6内核发布，网络模块的AIO一直没有进入稳定内核版本(大部分都是使用用户线程模拟方法，在使用了NPTL的linux上面其实和windows的完成端口基本上差不多了)。2.6内核所支持的AIO特指磁盘的AIO---支持io_submit(),io_getevents()以及对Direct IO的支持(就是绕过VFS系统buffer直接写硬盘，对于流服务器在内存平稳性上有相当帮助)。<br>&nbsp;&nbsp;&nbsp; 所以，剩下的select模型基本上就是我们在linux上面的唯一选择，其实，如果加上no-block socket的配置，可以完成一个"伪"AIO的实现，只不过推动力在于你而不是os而已。不过传统的select/poll函数有着一些无法忍受的缺点，所以改进一直是2.4-2.5开发版本内核的任务，包括/dev/poll，realtime signal等等。最终，Davide Libenzi开发的epoll进入2.6内核成为正式的解决方案<br><br>3、epoll的优点<br>&lt;1&gt;支持一个进程打开大数目的socket描述符(FD)<br>&nbsp;&nbsp;&nbsp; select 最不能忍受的是一个进程所打开的FD是有一定限制的，由FD_SETSIZE设置，默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核，不过资料也同时指出这样会带来网络效率的下降，二是可以选择多进程的解决方案(传统的 Apache方案)，不过虽然linux上面创建进程的代价比较小，但仍旧是不可忽视的，加上进程间数据同步远比不上线程间同步的高效，所以也不是一种完美的方案。不过 epoll则没有这个限制，它所支持的FD上限是最大可以打开文件的数目，这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右，具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。<br><br>&lt;2&gt;IO效率不随FD数目增加而线性下降<br>&nbsp;&nbsp;&nbsp; 传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合，不过由于网络延时，任一时间只有部分的socket是"活跃"的，但是select/poll每次调用都会线性扫描全部的集合，导致效率呈现线性下降。但是epoll不存在这个问题，它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么，只有"活跃"的socket才会主动的去调用 callback函数，其他idle状态socket则不会，在这点上，epoll实现了一个"伪"AIO，因为这时候推动力在os内核。在一些 benchmark中，如果所有的socket基本上都是活跃的---比如一个高速LAN环境，epoll并不比select/poll有什么效率，相反，如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。<br><br>&lt;3&gt;使用mmap加速内核与用户空间的消息传递。<br>&nbsp;&nbsp;&nbsp; 这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间，如何避免不必要的内存拷贝就很重要，在这点上，epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话，一定不会忘记手工 mmap这一步的。<br><br>&lt;4&gt;内核微调<br>&nbsp;&nbsp;&nbsp; 这一点其实不算epoll的优点了，而是整个linux平台的优点。也许你可以怀疑 linux平台，但是你无法回避linux平台赋予你微调内核的能力。比如，内核TCP/IP协议栈使用内存池管理sk_buff结构，那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大小--- 通过echo XXXX&gt;/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手的数据包队列长度)，也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。<br><br>4、epoll的工作模式<br>&nbsp;&nbsp;&nbsp; 令人高兴的是，2.6内核的epoll比其2.5开发版本的/dev/epoll简洁了许多，所以，大部分情况下，强大的东西往往是简单的。唯一有点麻烦是epoll有2种工作方式:LT和ET。<br>LT(level triggered)是缺省的工作方式，并且同时支持block和no-block socket.在这种做法中，内核告诉你一个文件描述符是否就绪了，然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作，内核还是会继续通知你的，所以，这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表．<br>&nbsp;&nbsp;&nbsp; ET (edge-triggered)是高速工作方式，只支持no-block socket。在这种模式下，当描述符从未就绪变为就绪时，内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪，并且不会再为那个文件描述符发送更多的就绪通知，直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如，你在发送，接收或者接收请求，或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误）。但是请注意，如果一直不对这个fd作IO操作(从而导致它再次变成未就绪)，内核不会发送更多的通知(only once),不过在TCP协议中，ET模式的加速效用仍需要更多的benchmark确认。<br>&nbsp;&nbsp;&nbsp; epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用，具体用法请参考http://www.xmailserver.org/linux-patches/nio-improve.html ，在http://www.kegel.com/rn/也有一个完整的例子，大家一看就知道如何使用了<br>Leader/follower模式线程pool实现，以及和epoll的配合。<br><br>5、 epoll的使用方法<br>&nbsp;&nbsp;&nbsp; 首先通过create_epoll(int maxfds)来创建一个epoll的句柄，其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄，之后的所有操作将通过这个句柄来进行操作。在用完之后，记得用close()来关闭这个创建出来的epoll句柄。之后在你的网络主循环里面，每一帧的调用epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的网络接口，看哪一个可以读，哪一个可以写了。基本的语法为：<br>nfds = epoll_wait(kdpfd, events, maxevents, -1);<br>其中kdpfd为用epoll_create创建之后的句柄，events是一个epoll_event*的指针，当epoll_wait这个函数操作成功之后，epoll_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket句柄数。最后一个timeout是 epoll_wait的超时，为0的时候表示马上返回，为-1的时候表示一直等下去，直到有事件范围，为任意正整数的时候表示等这么长的时间，如果一直没有事件，则范围。一般如果网络主循环是单独的线程的话，可以用-1来等，这样可以保证一些效率，如果是和主逻辑在同一个线程的话，则可以用0来保证主循环的效率。<br><br>epoll_wait范围之后应该是一个循环，遍利所有的事件：<br>for(n = 0; n &lt; nfds; ++n) {<br>&nbsp; if(events[n].data.fd == listener) { //如果是主socket的事件的话，则表示有新连接进入了，进行新连接的处理。<br>&nbsp;&nbsp;&nbsp; client = accept(listener, (struct sockaddr *) &amp;local,&nbsp; &amp;addrlen);<br>&nbsp;&nbsp;&nbsp; if(client &lt; 0){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror("accept");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; setnonblocking(client); // 将新连接置于非阻塞模式<br>&nbsp;&nbsp;&nbsp; ev.events = EPOLLIN | EPOLLET; // 并且将新连接也加入EPOLL的监听队列。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意，这里的参数EPOLLIN | EPOLLET并没有设置对写socket的监听，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果有写操作的话，这个时候epoll是不会返回事件的，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果要对写操作也监听的话，应该是EPOLLIN | EPOLLOUT | EPOLLET<br>&nbsp;&nbsp;&nbsp; ev.data.fd = client;<br>&nbsp;&nbsp;&nbsp; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &amp;ev) &lt; 0) {&nbsp; // 设置好event之后，将这个新的event通过epoll_ctl<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //加入到epoll的监听队列里面，这里用EPOLL_CTL_ADD<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //来加一个新的 epoll事件，通过EPOLL_CTL_DEL来减少<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //一个epoll事件，通过EPOLL_CTL_MOD来改变一个事件的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //监听方式。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, "epoll set insertion error: fd=%d0, client);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }&nbsp; else // 如果不是主socket的事件的话，则代表是一个用户socket的事件，<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //则来处理这个用户socket的事情，比如说read(fd,xxx)之类的，或者一些其他的处理。<br>&nbsp;&nbsp;&nbsp; do_use_fd(events[n].data.fd);<br>}<br><br>对，epoll的操作就这么简单，总共不过4个API：epoll_create, epoll_ctl, epoll_wait和close。<br>如果您对epoll的效率还不太了解，请参考我之前关于网络游戏的网络编程等相关的文章。<br><br><br>&nbsp;&nbsp;&nbsp; 以前公司的服务器都是使用HTTP连接，但是这样的话，在手机目前的网络情况下不但显得速度较慢，而且不稳定。因此大家一致同意用 SOCKET来进行连接。虽然使用SOCKET之后，对于用户的费用可能会增加(由于是用了CMNET而非CMWAP)，但是，秉着用户体验至上的原则，相信大家还是能够接受的(希望那些玩家月末收到帐单不后能够保持克制...)。<br>这次的服务器设计中，最重要的一个突破，是使用了EPOLL模型，虽然对之也是一知半解，但是既然在各大PC网游中已经经过了如此严酷的考验，相信他不会让我们失望，使用后的结果，确实也是表现相当不错。在这里，我还是主要大致介绍一下这个模型的结构。<br>6、Linux下EPOll编程实例<br>EPOLL模型似乎只有一种格式，所以大家只要参考我下面的代码，就能够对EPOLL有所了解了，代码的解释都已经在注释中：<br><br>while (TRUE) {<br>&nbsp; int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//等待EPOLL时间的发生，相当于监听，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //至于相关的端口，需要在初始化EPOLL的时候绑定。<br>&nbsp; if (nfds &lt;= 0)<br>&nbsp;&nbsp;&nbsp; continue;<br>&nbsp; m_bOnTimeChecking = FALSE;<br>&nbsp; G_CurTime = time(NULL);<br>&nbsp; for (int i=0; i&lt;nfds; i++) {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_events[i].data.fd == m_listen_http_fd)//如果新监测到一个HTTP用户连接到绑定的HTTP端口，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //建立新的连接。由于我们新采用了SOCKET连接，所以基本没用。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnAcceptHttpEpoll ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //建立新的连接。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnAcceptSockEpoll ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (m_events[i].events &amp; EPOLLIN)//如果是已经连接的用户，并且收到数据，那么进行读入。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnReadEpoll (i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据。<br>&nbsp;&nbsp;&nbsp; } catch (int) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINTF ("CATCH捕获错误\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; m_bOnTimeChecking = TRUE;<br>&nbsp; OnTimer ();//进行一些定时的操作，主要就是删除一些短线用户等。<br>}<br>　其实EPOLL的精华，也就是上述的几段短短的代码，看来时代真的不同了，以前如何接受大量用户连接的问题，现在却被如此轻松的搞定，真是让人不得不感叹，对哪。<br><br><br><br><img alt=""  src="http://www.cppblog.com/images/cppblog_com/khan/6584/r_epoll.jpg"><br><br>Epoll模型主要负责对大量并发用户的请求进行及时处理，完成服务器与客户端的数据交互。其具体的实现步骤如下：<br>(a) 使用epoll_create()函数创建文件描述，设定将可管理的最大socket描述符数目。<br>(b) 创建与epoll关联的接收线程，应用程序可以创建多个接收线程来处理epoll上的读通知事件，线程的数量依赖于程序的具体需要。<br>(c) 创建一个侦听socket描述符ListenSock；将该描述符设定为非阻塞模式，调用Listen（）函数在套接字上侦听有无新的连接请求，在epoll_event结构中设置要处理的事件类型EPOLLIN，工作方式为 epoll_ET，以提高工作效率，同时使用epoll_ctl()注册事件，最后启动网络监视线程。<br>(d) 网络监视线程启动循环，epoll_wait()等待epoll事件发生。<br>(e) 如果epoll事件表明有新的连接请求，则调用accept（）函数，将用户socket描述符添加到epoll_data联合体，同时设定该描述符为非阻塞，并在epoll_event结构中设置要处理的事件类型为读和写，工作方式为epoll_ET.<br>(f) 如果epoll事件表明socket描述符上有数据可读，则将该socket描述符加入可读队列，通知接收线程读入数据，并将接收到的数据放入到接收数据的链表中，经逻辑处理后，将反馈的数据包放入到发送数据链表中，等待由发送线程发送。<br><br>
<br><img src ="http://www.cppblog.com/Khan/aggbug/46013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Khan/" target="_blank">Khan's Notebook</a> 2008-04-02 11:37 <a href="http://www.cppblog.com/Khan/archive/2008/04/02/46013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>