﻿<?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/category/775.html</link><description>路漫漫，长修远，我们不能没有钱</description><language>zh-cn</language><lastBuildDate>Wed, 24 Dec 2008 15:12:48 GMT</lastBuildDate><pubDate>Wed, 24 Dec 2008 15:12:48 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>2</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>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>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><item><title>内存越界和泄露调试工具(转载自赛迪网)</title><link>http://www.cppblog.com/Khan/archive/2008/03/20/44933.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Thu, 20 Mar 2008 04:23:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/03/20/44933.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/44933.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/03/20/44933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/44933.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/44933.html</trackback:ping><description><![CDATA[<span id="zoom" class="a14c">
<p style="text-indent: 2em;"><span class="b">作者：sixth</span></p>
<p style="text-indent: 2em;">用C/C++开发其中最令人头疼的一个问题就是内存管理，有时候为了查找一个内存泄漏或者一个内存访问越界，需要要花上好几天时间，如果有一款工具能够帮助我们做这件事情就好了，valgrind正好就是这样的一款工具。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">Valgrind是一款基于模拟linux下的程序调试器和剖析器的软件套件，可以
运行于x86,
amd64和ppc32架构上。valgrind包含一个核心，它提供一个虚拟的CPU运行程序，还有一系列的工具，它们完成调试，剖析和一些类似的任
务。valgrind是高度模块化的，所以开发人员或者用户可以给它添加新的工具而不会损坏己有的结构。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind的官方网址是：http://valgrind.org
</p>
<p style="text-indent: 2em;">你可以在它的网站上下载到最新的valgrind，它是开放源码和免费的。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;"><strong>一、介绍</strong>
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind包含几个标准的工具，它们是：
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">1、memcheck
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">memcheck探测程序中内存管理存在的问题。它检查所有对内存的读/写操作，并截取所有的malloc/new/free/delete调用。因此memcheck工具能够探测到以下问题：
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">1）使用未初始化的内存
</p>
<p style="text-indent: 2em;">2）读/写已经被释放的内存
</p>
<p style="text-indent: 2em;">3）读/写内存越界
</p>
<p style="text-indent: 2em;">4）读/写不恰当的内存栈空间
</p>
<p style="text-indent: 2em;">5）内存泄漏
</p>
<p style="text-indent: 2em;">6）使用malloc/new/new[]和free/delete/delete[]不匹配。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">2、cachegrind
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">cachegrind是一个cache剖析器。它模拟执行CPU中的L1,
D1和L2
cache，因此它能很精确的指出代码中的cache未命中。如果你需要，它可以打印出cache未命中的次数，内存引用和发生cache未命中的每一行
代码，每一个函数，每一个模块和整个程序的摘要。如果你要求更细致的信息，它可以打印出每一行机器码的未命中次数。在x86和amd64上，
cachegrind通过CPUID自动探测机器的cache配置，所以在多数情况下它不再需要更多的配置信息了。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">3、helgrind
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">helgrind查找多线程程序中的竞争数据。helgrind查找内存地址，那些被多于一条线程访问的内存地址，但是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步，很可能会引起很难查找的时序问题。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;"><strong>二、valgrind对你的程序都做了些什么</strong>
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind被设计成非侵入式的，它直接工作于可执行文件上，因此在检查前不需要重新编译、连接和修改你的程序。要检查一个程序很简单，只需要执行下面的命令就可以了
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=tool_name  program_name
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">比如我们要对ls -l命令做内存检查，只需要执行下面的命令就可以了
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=memcheck ls -l
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">不管是使用哪个工具，valgrind在开始之前总会先取得对你的程序的控制权，从
可执行关联库里读取调试信息。然后在valgrind核心提供的虚拟CPU上运行程序，valgrind会根据选择的工具来处理代码，该工具会向代码中加
入检测代码，并把这些代码作为最终代码返回给valgrind核心，最后valgrind核心运行这些代码。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">如果要检查内存泄漏，只需要增加--leak-check=yes就可以了，命令如下
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=memcheck --leak-check=yes ls -l
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">不同工具间加入的代码变化非常的大。在每个作用域的末尾，memcheck加入代码检查每一片内存的访问和进行值计算，代码大小至少增加12倍，运行速度要比平时慢25到50倍。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind模拟程序中的每一条指令执行，因此，检查工具和剖析工具不仅仅是对你的应用程序，还有对共享库，GNU C库，X的客户端库都起作用。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;"><strong>三、现在开始</strong>
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">首先，在编译程序的时候打开调试模式（gcc编译器的-g选项）。如果没有调试信
息，即使最好的valgrind工具也将中能够猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind检查，valgrind将会
给你的个详细的报告，比如哪一行代码出现了内存泄漏。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">当检查的是C++程序的时候，还应该考虑另一个选项
-fno-inline。它使得函数调用链很清晰，这样可以减少你在浏览大型C++程序时的混乱。比如在使用这个选项的时候，用memcheck检查
openoffice就很容易。当然，你可能不会做这项工作，但是使用这一选项使得valgrind生成更精确的错误报告和减少混乱。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">一些编译优化选项(比如-O2或者更高的优化选项)，可能会使得memcheck提交错误的未初始化报告，因此，为了使得valgrind的报告更精确，在编译的时候最好不要使用优化选项。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">如果程序是通过脚本启动的，可以修改脚本里启动程序的代码，或者使用--trace-children=yes选项来运行脚本。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">下面是用memcheck检查ls -l命令的输出报告，在终端下执行下面的命令
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=memcheck ls -l
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">程序会打印出ls -l命令的结果，最后是valgrind的检查报告如下：
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">==4187==
</p>
<p style="text-indent: 2em;">==4187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 19 from 2)
</p>
<p style="text-indent: 2em;">==4187== malloc/free: in use at exit: 15,154 bytes in 105 blocks.
</p>
<p style="text-indent: 2em;">==4187== malloc/free: 310 allocs, 205 frees, 60,093 bytes allocated.
</p>
<p style="text-indent: 2em;">==4187== For counts of detected errors, rerun with: -v
</p>
<p style="text-indent: 2em;">==4187== searching for pointers to 105 not-freed blocks.
</p>
<p style="text-indent: 2em;">==4187== checked 145,292 bytes.
</p>
<p style="text-indent: 2em;">==4187==
</p>
<p style="text-indent: 2em;">==4187== LEAK SUMMARY:
</p>
<p style="text-indent: 2em;">==4187==    definitely lost: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4187==      possibly lost: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4187==    still reachable: 15,154 bytes in 105 blocks.
</p>
<p style="text-indent: 2em;">==4187==         suppressed: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4187== Reachable blocks (those to which a pointer was found) are not shown.
</p>
<p style="text-indent: 2em;">==4187== To see them, rerun with: --show-reachable=yes
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">这里的&#8220;4187&#8221;指的是执行ls -l的进程ID，这有利于区别不同进程的报告。memcheck会给出报告，分配置和释放了多少内存，有多少内存泄漏了，还有多少内存的访问是可达的，检查了多少字节的内存。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">下面举两个用valgrind做内存检查的例子
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">例子一 (test.c)：
</p>
<p style="text-indent: 2em;">
</p>
<center><ccid_nobr>
</ccid_nobr>
<table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
            <pre><ccid_code>#include &lt;string.h&gt;<br><br>int main(int argc, char *argv[])<br>{<br>    char *ptr;<br><br>    ptr = (char*) malloc(10);<br>    strcpy(ptr, "01234567890");<br><br>    return 0;<br>}</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">编译程序
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">gcc -g -o test test.c
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">用valgrind执行命令
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=memcheck --leak-check=yes ./test
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">报告如下
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">==4270== Memcheck, a memory error detector.
</p>
<p style="text-indent: 2em;">==4270== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
</p>
<p style="text-indent: 2em;">==4270== Using LibVEX rev 1606, a library for dynamic binary translation.
</p>
<p style="text-indent: 2em;">==4270== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
</p>
<p style="text-indent: 2em;">==4270== Using valgrind-3.2.0, a dynamic binary instrumentation framework.
</p>
<p style="text-indent: 2em;">==4270== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
</p>
<p style="text-indent: 2em;">==4270== For more details, rerun with: -v
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270== Invalid write of size 1
</p>
<p style="text-indent: 2em;">==4270==    at 0x4006190: strcpy (mc_replace_strmem.c:271)
</p>
<p style="text-indent: 2em;">==4270==    by 0x80483DB: main (test.c:8)
</p>
<p style="text-indent: 2em;">==4270==  Address 0x4023032 is 0 bytes after a block of size 10 alloc'd
</p>
<p style="text-indent: 2em;">==4270==    at 0x40044F6: malloc (vg_replace_malloc.c:149)
</p>
<p style="text-indent: 2em;">==4270==    by 0x80483C5: main (test.c:7)
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270== Invalid write of size 1
</p>
<p style="text-indent: 2em;">==4270==    at 0x400619C: strcpy (mc_replace_strmem.c:271)
</p>
<p style="text-indent: 2em;">==4270==    by 0x80483DB: main (test.c:8)
</p>
<p style="text-indent: 2em;">==4270==  Address 0x4023033 is 1 bytes after a block of size 10 alloc'd
</p>
<p style="text-indent: 2em;">==4270==    at 0x40044F6: malloc (vg_replace_malloc.c:149)
</p>
<p style="text-indent: 2em;">==4270==    by 0x80483C5: main (test.c:7)
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 1)
</p>
<p style="text-indent: 2em;">==4270== malloc/free: in use at exit: 10 bytes in 1 blocks.
</p>
<p style="text-indent: 2em;">==4270== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.
</p>
<p style="text-indent: 2em;">==4270== For counts of detected errors, rerun with: -v
</p>
<p style="text-indent: 2em;">==4270== searching for pointers to 1 not-freed blocks.
</p>
<p style="text-indent: 2em;">==4270== checked 51,496 bytes.
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
</p>
<p style="text-indent: 2em;">==4270==    at 0x40044F6: malloc (vg_replace_malloc.c:149)
</p>
<p style="text-indent: 2em;">==4270==    by 0x80483C5: main (test.c:7)
</p>
<p style="text-indent: 2em;">==4270==
</p>
<p style="text-indent: 2em;">==4270== LEAK SUMMARY:
</p>
<p style="text-indent: 2em;">==4270==    definitely lost: 10 bytes in 1 blocks.
</p>
<p style="text-indent: 2em;">==4270==      possibly lost: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4270==    still reachable: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4270==         suppressed: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4270== Reachable blocks (those to which a pointer was found) are not shown.
</p>
<p style="text-indent: 2em;">==4270== To see them, rerun with: --show-reachable=yes
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">从这份报告可以看出，进程号是4270，test.c的第8行写内存越界了，引起写内存越界的是strcpy函数，
</p>
<p style="text-indent: 2em;">第7行泄漏了10个字节的内存，引起内存泄漏的是malloc函数。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">例子二（test2.c)
</p>
<p style="text-indent: 2em;">
</p>
<center><ccid_nobr>
</ccid_nobr>
<table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
            <pre><ccid_code>#include &lt;stdio.h&gt;<br><br>int foo(int x)<br>{<br>    if (x &lt; 0) {<br>        printf("%d ", x);<br>    }<br><br>    return 0;<br>}<br><br>int main(int argc, char *argv[])<br>{<br>    int x;<br>   <br>    foo(x);<br><br>    return 0;<br>}</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">编译程序
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">gcc -g -o test2 test2.c
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">用valgrind做内存检查
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind --tool=memcheck ./test2
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">输出报告如下
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">==4285== Memcheck, a memory error detector.
</p>
<p style="text-indent: 2em;">==4285== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
</p>
<p style="text-indent: 2em;">==4285== Using LibVEX rev 1606, a library for dynamic binary translation.
</p>
<p style="text-indent: 2em;">==4285== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
</p>
<p style="text-indent: 2em;">==4285== Using valgrind-3.2.0, a dynamic binary instrumentation framework.
</p>
<p style="text-indent: 2em;">==4285== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
</p>
<p style="text-indent: 2em;">==4285== For more details, rerun with: -v
</p>
<p style="text-indent: 2em;">==4285==
</p>
<p style="text-indent: 2em;">==4285== Conditional jump or move depends on uninitialised value(s)
</p>
<p style="text-indent: 2em;">==4285==    at 0x8048372: foo (test2.c:5)
</p>
<p style="text-indent: 2em;">==4285==    by 0x80483B4: main (test2.c:16)
</p>
<p style="text-indent: 2em;">==4285==p p
</p>
<p style="text-indent: 2em;">==4285== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 1)
</p>
<p style="text-indent: 2em;">==4285== malloc/free: in use at exit: 0 bytes in 0 blocks.
</p>
<p style="text-indent: 2em;">==4285== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
</p>
<p style="text-indent: 2em;">==4285== For counts of detected errors, rerun with: -v
</p>
<p style="text-indent: 2em;">==4285== All heap blocks were freed -- no leaks are possible.
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">从这份报告可以看出进程PID是4285，test2.c文件的第16行调用了foo函数，在test2.c文件的第5行foo函数使用了一个未初始化的变量。
</p>
<p style="text-indent: 2em;">
</p>
<p style="text-indent: 2em;">valgrind还有很多使用选项，具体可以查看valgrind的man手册页和valgrind官方网站的在线文档。</p>
<br>
<p style="text-indent: 2em;"><br></p>
<br>
<p style="text-indent: 2em;"><br></p>
<p style="text-indent: 2em;">Windows用户不必沮丧，虽然在Windows上没有Valgrind可用，但是你可以试一试IBM的<a  href="http://www-306.ibm.com/software/awdtools/purify/">Purify</a>，它在功能上和Valgrind相似。<br>
</p>
</span><img src ="http://www.cppblog.com/Khan/aggbug/44933.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-03-20 12:23 <a href="http://www.cppblog.com/Khan/archive/2008/03/20/44933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过两个点的经纬度计算距离</title><link>http://www.cppblog.com/Khan/archive/2008/02/28/43390.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Thu, 28 Feb 2008 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2008/02/28/43390.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/43390.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2008/02/28/43390.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/43390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/43390.html</trackback:ping><description><![CDATA[最近开始做一个类似gis的东西. 需要求一些经纬度相关的值..<br><br>看了<a href="http://panyee.cnblogs.com/archive/2006/07/04/442771.html" target="_blank">通过两个点的经纬度计算距离</a>这篇，据说是Google里扒来的算法，于是决定验证一下。<br>通过计算发现非常正确。<br>用30,120和31,121两个坐标点进行验证，同Mapinfo中计算的结果非常的相近。<br>后来又把坐标系直接当成直角坐标系来计算，发现误差很大。<br>于是仍然用直角坐标系方法来计算，给纬度加上了个0.86的参数，这样计算下来和结果相近。<br><br><br><br><br>c#代码<br>private const double EARTH_RADIUS = 6378.137; //地球半径<br>private static double rad(double d)<br>{<br>&nbsp;&nbsp;&nbsp;return d * Math.PI / 180.0;<br>}
<p>public static double GetDistance(double lat1, double lng1, double lat2, double lng2)<br>{<br>&nbsp;&nbsp;&nbsp;double radLat1 = rad(lat1);<br>&nbsp;&nbsp;&nbsp;double radLat2 = rad(lat2);<br>&nbsp;&nbsp;&nbsp;double a = radLat1 - radLat2;<br>&nbsp;&nbsp;&nbsp;double b = rad(lng1) - rad(lng2);<br>&nbsp;&nbsp;&nbsp;double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a/2),2) + <br>&nbsp;&nbsp;&nbsp;&nbsp;Math.Cos(radLat1)*Math.Cos(radLat2)*Math.Pow(Math.Sin(b/2),2)));<br>&nbsp;&nbsp;&nbsp;s = s * EARTH_RADIUS;<br>&nbsp;&nbsp;&nbsp;s = Math.Round(s * 10000) / 10000;<br>&nbsp;&nbsp;&nbsp;return s;<br>}</p>
<br>
<p>vb代码</p>
<img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Const&nbsp;EARTH_RADIUS&nbsp;=&nbsp;6378.137<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Const&nbsp;Pi&nbsp;=&nbsp;3.1415926535898<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Function&nbsp;rad(ByVal&nbsp;d&nbsp;As&nbsp;Double)&nbsp;As&nbsp;Double<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">rad&nbsp;=&nbsp;d&nbsp;*&nbsp;Pi&nbsp;/&nbsp;180<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">End&nbsp;Function<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Function&nbsp;GetDistance(lat1&nbsp;As&nbsp;Double,&nbsp;lng1&nbsp;As&nbsp;Double,&nbsp;lat2&nbsp;As&nbsp;Double,&nbsp;lng2&nbsp;As&nbsp;Double)&nbsp;As&nbsp;Double<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Dim&nbsp;radlat1&nbsp;As&nbsp;Double,&nbsp;radlat2&nbsp;As&nbsp;Double<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Dim&nbsp;a&nbsp;As&nbsp;Double,&nbsp;b&nbsp;As&nbsp;Double,&nbsp;s&nbsp;As&nbsp;Double,&nbsp;Temp&nbsp;As&nbsp;Double<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">radlat1&nbsp;=&nbsp;rad(lat1)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">radlat2&nbsp;=&nbsp;rad(lat2)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">a&nbsp;=&nbsp;radlat1&nbsp;-&nbsp;radlat2<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">b&nbsp;=&nbsp;rad(lng1)&nbsp;-&nbsp;rad(lng2)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Temp&nbsp;=&nbsp;Sqr(Sin(a&nbsp;/&nbsp;2)&nbsp;^&nbsp;2&nbsp;+&nbsp;Cos(radlat1)&nbsp;*&nbsp;Cos(radlat2)&nbsp;*&nbsp;Sin(b&nbsp;/&nbsp;2)&nbsp;^&nbsp;2)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">s&nbsp;=&nbsp;2&nbsp;*&nbsp;Atn(Temp&nbsp;/&nbsp;Sqr(-Temp&nbsp;*&nbsp;Temp&nbsp;+&nbsp;1))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'没有反正弦函数，网上找了个<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">s&nbsp;=&nbsp;s&nbsp;*&nbsp;EARTH_RADIUS<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">GetDistance&nbsp;=&nbsp;s<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">End&nbsp;Function<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Private&nbsp;Sub&nbsp;Command1_Click()<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Text5.Text&nbsp;=&nbsp;Str(GetDistance(Val(Text1.Text),&nbsp;Val(Text2.Text),&nbsp;Val(Text3.Text),&nbsp;Val(Text4.Text)))<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">End&nbsp;Sub<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Private&nbsp;Sub&nbsp;Command2_Click()<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Text5.Text&nbsp;=&nbsp;Str((Sqr((Val(Text3.Text)&nbsp;-&nbsp;Val(Text1.Text))&nbsp;^&nbsp;2&nbsp;+&nbsp;(Val(Text4.Text)&nbsp;-&nbsp;Val(Text2.Text))&nbsp;^&nbsp;2))&nbsp;*&nbsp;111.3199338)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">End&nbsp;Sub<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Private&nbsp;Sub&nbsp;Command3_Click()<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">Text5.Text&nbsp;=&nbsp;Str((Sqr((Val(Text3.Text)&nbsp;*&nbsp;0.86&nbsp;-&nbsp;Val(Text1.Text)&nbsp;*&nbsp;0.86)&nbsp;^&nbsp;2&nbsp;+&nbsp;(Val(Text4.Text)&nbsp;-&nbsp;Val(Text2.Text))&nbsp;^&nbsp;2))&nbsp;*&nbsp;111.3199338)<br><img src="http://tangf.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">End&nbsp;Sub
<p><br></p>
<p><br></p>
同纬度计算比较简单<br>
<p>A（60，30），B（60，90）两点之间，此段代码和我用余弦定理算出来的结果很一致。
<br>余弦定理的步骤是：1、算A、B弦长：地球半径R*cos（经度差60）=R/2；
<br>2、算角AOB,O为地球圆心，利用余弦定理，
<br>cosAOB=(2R*R-(R/2)^2) /2*R*R=7/8;
<br>3、弧AB的长为：R*arc cos(7/8);求毕 <br></p>
<br>
<p><br></p>
<p>原理:<br></p>
<p>
地球赤道上环绕地球一周走一圈共40075.04公里,而@一圈分成360&#176;,而每1&#176;(度)有60,每一度一秒在赤道上的长度计算如下：
<br>
<br>　　40075.04km/360&#176;=111.31955km
<br>
<br>　　111.31955km/60=1.8553258km=1855.3m
<br>
<br>　　而每一分又有60秒,每一秒就代表1855.3m/60=30.92m
<br>
<br>　　任意两点距离计算公式为
<br>
<br>　　d＝111.12cos{1/[sin&#934;Asin&#934;B十cos&#934;Acos&#934;Bcos(&#955;B—&#955;A)]}
<br>
<br>　　其中A点经度，纬度分别为&#955;A和&#934;A，B点的经度、纬度分别为&#955;B和&#934;B，d为距离。</p>
<br>  <img src ="http://www.cppblog.com/Khan/aggbug/43390.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-02-28 15:18 <a href="http://www.cppblog.com/Khan/archive/2008/02/28/43390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>技巧: 用 uniq 除去重复行(转载自ibm论坛)</title><link>http://www.cppblog.com/Khan/archive/2007/11/19/36921.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Mon, 19 Nov 2007 02:23:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2007/11/19/36921.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/36921.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2007/11/19/36921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/36921.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/36921.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 重复行通常不会造成问题，但是有时候它们的确会引起问题。<br>&nbsp;&nbsp;&nbsp; 此时，不必花上一个下午的时间来为它们编制过滤器，uniq 命令便是唾手可得的好工具。了解一下它是如何节省您的时间和精力的。<br><br>进行排序之后，您会发现有些行是重复的。有时候该重复信息是不需要的，可以将它除去以节省磁盘空间。<br>不必对文本行进行排序，但是您应当记住 uniq 在读取行时会对它们进行比较并将只除去两个或更多的连续行。<br>下面的示例说明了它实际上是如何工作的：<br>清单 1. 用 uniq 除去重复行<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ cat happybirthday.txt<br>Happy Birthday to You!<br>Happy Birthday to You!<br>Happy Birthday Dear Tux!<br>Happy Birthday to You!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ sort happybirthday.txt <br>Happy Birthday Dear Tux!<br>Happy Birthday to You!<br>Happy Birthday to You!<br>Happy Birthday to You!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ sort happybirthday.txt | uniq<br>Happy Birthday Dear Tux!<br>Happy Birthday to You!<br><br><br><br>警告：请不要使用 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uniq 或任何其它工具从包含财务或其它重要数据的文件中除去重复行。<br>&nbsp;&nbsp;&nbsp; 在这种情况下，重复行几乎总是表示同一金额的另一个交易，将它除去会给会计部造成许多困难。千万别这么干！<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>如果您希望您的工作轻松点，比如只显示唯一的或重复的行，那么该怎么办呢？您可以用 -u （唯一）和 -d （重复）选项来做到这一点，例如：<br>清单 2. 使用 -u 和 -d 选项<br>$ sort happybirthday.txt | uniq -u<br>Happy Birthday Dear Tux!<br>$ sort happybirthday.txt | uniq -d<br>Happy Birthday to You!<br><br><br>清单 3. 使用 -c 选项<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ sort happybirthday.txt | uniq -uc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 Happy Birthday Dear Tux!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ sort happybirthday.txt | uniq -dc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 Happy Birthday to You!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br><br>就算 uniq 对完整的行进行比较，它仍然会很有用，但是那并非该命令的全部功能。特别方便的是：使用 -f 选项，<br>后面跟着要跳过的字段数，它能够跳过给定数目的字段。当您查看系统日志时这非常有用。<br>通常，某些项要被复制许多次，这使得查看日志很难。使用简单的 uniq 无法完成任务，因为每一项都以不同的时间戳记开头。<br>但是如果您告诉它跳过所有的时间字段，您的日志一下子就会变得更加便于管理。试一试 uniq -f 3 /var/log/messages ，亲眼看看。<br><br>还有另一个选项 -s ，它的功能就像 -f 一样，但是跳过给定数目的字符。您可以一起使用 -f 和 -s 。 <br>uniq 先跳过字段，再跳过字符。如果您只想使用一些预先设置的字符进行比较，那么该怎么办呢？试试看 -w 选项。<br><br><br><img src ="http://www.cppblog.com/Khan/aggbug/36921.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> 2007-11-19 10:23 <a href="http://www.cppblog.com/Khan/archive/2007/11/19/36921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gawk使用记录</title><link>http://www.cppblog.com/Khan/archive/2007/11/16/36752.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Fri, 16 Nov 2007 07:23:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2007/11/16/36752.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/36752.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2007/11/16/36752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/36752.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/36752.html</trackback:ping><description><![CDATA[这是一个强大的处理格式化文本的工具,通过使用其脚本,几乎可以把文本当作数据库处理<br><br><br>分隔符为逗号, 标尺格式化显示各个字段<br>gawk&nbsp; -F"," "{printf \"%-6s %-9s %-9s %-9s %-9s\n\", NR, $1, $2, $4, $12}"&nbsp;&nbsp; aStockList.csv&nbsp; <br>如:<br>1&nbsp;&nbsp;&nbsp;&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>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000001&nbsp;&nbsp;&nbsp; 深发展Ａ&nbsp; 40.45&nbsp;&nbsp;&nbsp;&nbsp; 40.7&nbsp;&nbsp;&nbsp;&nbsp; <br>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000002&nbsp;&nbsp;&nbsp; 万&nbsp; 科Ａ&nbsp; 35.8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 35.69&nbsp;&nbsp;&nbsp; <br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000004&nbsp;&nbsp;&nbsp; ST 国 农&nbsp; 9.72&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9.91&nbsp;&nbsp;&nbsp;&nbsp; <br>5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000005&nbsp;&nbsp;&nbsp; ST 星 源&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000006&nbsp;&nbsp;&nbsp; 深振业Ａ&nbsp; 33.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 33.31&nbsp;&nbsp;&nbsp; <br>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000007&nbsp;&nbsp;&nbsp; ST 达 声&nbsp; 7.18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000008&nbsp;&nbsp;&nbsp; *ST 宝投&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000009&nbsp;&nbsp;&nbsp; S深宝安A&nbsp; 13.59&nbsp;&nbsp;&nbsp;&nbsp; 13.6&nbsp;&nbsp;&nbsp;&nbsp; <br>10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000010&nbsp;&nbsp;&nbsp; S ST华新&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br><br>取文件最后一行的行号.实际就是取总行数<br>gawk "END {print NR}"&nbsp; aStockList.csv&nbsp;&nbsp; <br><br><br><br>将数据分类汇总<br>gawk -F"," "{pos=(NR-1)%40; page=int((NR-1)/40); a=int((NR-1)/600) } <br>&nbsp;&nbsp;&nbsp; {print $1\",\",$2\",\",pos\",\",page\",\",a}"&nbsp; aStockList.csv |<br>&nbsp; gawk -F"," "BEGIN <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { printf \"%-6s %-9s %-9s&nbsp; %-4s\n\", \"&nbsp; \", \"代码\", \"名称\", \"条/页/位置\"; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print \"----------------------------------\"&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { printf\"%-6s %-9s %-9s %-4s \n\", NR, $1, $2, $5\"/\"$4%15\"/\"$3}"<br><br><br>原始数据:<br>代码&nbsp;&nbsp; ,名称,涨幅%%,现价,日涨跌,买入价,卖出价,总量,现量,涨速%%,换手%%,今开<br>000001,深发展Ａ,-0.32,40.45,-0.54,40.45,40.48,90119,32,0.24,0.58,40.7<br>000002,万&nbsp; 科Ａ,-0.56,35.8,-0.2,35.79,35.8,172067,3,0.56,0.33,35.69<br>000004,ST 国 农,-1.82,9.72,-0.18,9.7,9.72,18424,8,0,2.82,9.91<br>000005,ST 星 源,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000006,深振业Ａ,0,33.3,0,33.22,33.3,8753,6,0.27,0.4,33.31<br>000007,ST 达 声,2.43,7.18,0.17,7.15,7.18,11955,2,0.7,0.83,7.1<br>000008,*ST 宝投,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000009,S深宝安A,-1.02,13.59,-0.14,13.59,13.6,31747,150,0.22,0.55,13.6<br>000010,S ST华新,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000011,S深物业A,-0.86,12.65,-0.11,12.6,12.65,1608,24,0.39,0.18,12.43<br>000012,南&nbsp; 玻Ａ,0.17,18.16,0.03,18.16,18.18,32715,149,0.66,0.85,18<br>000014,沙河股份,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000016,深康佳Ａ,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000017,S ST中华,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000018,ST中冠Ａ,-0.39,7.66,-0.03,7.66,7.67,1182,2,0.13,0.28,7.69<br>000019,深深宝Ａ,-2.81,17.3,-0.5,17.3,17.38,12168,9,0.69,1.66,17.6<br>000020,ST华发Ａ,-0.14,6.91,-0.01,6.86,6.91,3235,6,0,0.5,6.91<br>000021,长城开发,-1.97,15.39,-0.31,15.38,15.39,18408,3,0.39,0.5,15.68<br>000022,深赤湾Ａ,-3.59,24.45,-0.91,24.45,24.46,5446,9,0.16,0.46,25.18<br>000023,深天地Ａ,-1.79,10.41,-0.19,10.4,10.41,3878,17,-0.19,0.58,10.78<br>000024,招商地产,-3.42,87.7,-3.11,87.71,87.99,2213,51,-0.11,0.07,91.9<br>000025,特&nbsp; 力Ａ,-1.48,13.99,-0.21,13.95,13.99,6856,4,-0.07,1.43,14.18<br>000026,飞亚达Ａ,-3.49,11.6,-0.42,11.6,11.65,20177,3,0.6,2.54,11.9<br>000027,深能源Ａ,-0.23,21.3,-0.05,21.28,21.3,30689,5,0.37,0.51,21.4<br>000028,一致药业,-1.35,15.38,-0.21,15.31,15.38,6399,3,0.32,0.57,15.58<br>000029,深深房Ａ,-1.21,7.36,-0.09,7.35,7.36,16261,7,1.51,0.6,7.49<br>000030,S*ST盛润,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000031,中粮地产,0.89,27.29,0.24,27.28,27.29,46135,78,0.25,0.94,27.05<br>000032,深桑达Ａ,-2.2,11.1,-0.25,11.07,11.1,5361,50,0.18,0.47,11.31<br>000033,新都酒店,-1.94,6.07,-0.12,6.06,6.07,19441,5,0.66,1.23,6.13<br>000034,SST 深泰,-0.48,8.24,-0.04,8.24,8.27,3797,15,0.12,0.45,8.21<br>000035,ST 科 健,--- ,0,--- ,--- ,--- ,0,0,--- ,0,--- <br>000036,华联控股,1.28,7.91,0.1,7.9,7.91,97065,300,0.5,1.26,7.73<br>000037,深南电Ａ,-1.9,8.25,-0.16,8.24,8.25,8874,62,0.24,0.55,8.4<br>000039,中集集团,-1.41,23.7,-0.34,23.7,23.72,55243,9,0.21,0.59,24.05<br>000040,深 鸿 基,-1.96,8.02,-0.16,8.01,8.02,24508,10,0.62,0.62,8.2<br>000042,深 长 城,-1.42,23.66,-0.34,23.66,23.7,3064,4,0.25,0.23,24.1<br>000043,深南光Ａ,1.83,23.9,0.43,23.85,23.9,1543,11,0.42,0.17,23.53<br>000045,深纺织Ａ,-1.88,7.31,-0.14,7.31,7.36,3779,5,-0.67,0.81,7.45<br>000046,泛海建设,-0.32,59.89,-0.19,59.89,59.9,4754,4,-0.01,0.21,60.11<br>000048,*ST 康达,-0.95,5.2,-0.05,5.2,5.22,11110,2,0,0.5,5.27<br>000049,德赛电池,2.26,10.86,0.24,10.85,10.86,8425,44,0.09,1.33,10.62<br>000050,深天马Ａ,-0.66,13.58,-0.09,13.56,13.58,10580,4,0.36,0.88,13.76<br>000055,方&nbsp; 大Ａ,-1.48,7.32,-0.11,7.32,7.33,7959,5,0.68,0.67,7.47<br>000056,深 国 商,-2.46,11.1,-0.28,11.12,11.19,5911,8,0.45,0.6,11.38<br>000058,*ST 赛格,-0.21,9.64,-0.02,9.63,9.64,25708,60,-0.41,1.22,9.87<br>000059,辽通化工,0.27,11.32,0.03,11.31,11.32,62685,28,0.17,1.9,11.32<br>000060,中金岭南,2.16,47.2,1,47.18,47.2,135188,3,1.17,3.13,46.19<br><br><br><br>目标数据:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 名称&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 条/页/位置<br>----------------------------------<br>1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000001&nbsp;&nbsp;&nbsp;&nbsp; 深发展Ａ&nbsp; 0/0/ 0 <br>2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000002&nbsp;&nbsp;&nbsp;&nbsp; 万&nbsp; 科Ａ&nbsp; 0/0/ 1 <br>3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000004&nbsp;&nbsp;&nbsp;&nbsp; ST 国 农&nbsp; 0/0/ 2 <br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000005&nbsp;&nbsp;&nbsp;&nbsp; ST 星 源&nbsp; 0/0/ 3 <br>5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000006&nbsp;&nbsp;&nbsp;&nbsp; 深振业Ａ&nbsp; 0/0/ 4 <br>6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000007&nbsp;&nbsp;&nbsp;&nbsp; ST 达 声&nbsp; 0/0/ 5 <br>7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000008&nbsp;&nbsp;&nbsp;&nbsp; *ST 宝投&nbsp; 0/0/ 6 <br>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000009&nbsp;&nbsp;&nbsp;&nbsp; S深宝安A&nbsp; 0/0/ 7 <br>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 000010&nbsp;&nbsp;&nbsp;&nbsp; S ST华新&nbsp; 0/0/ 8 <br>10&nbsp;&nbsp;&nbsp;&nbsp; 000011&nbsp;&nbsp;&nbsp;&nbsp; S深物业A&nbsp; 0/0/ 9 <br>11&nbsp;&nbsp;&nbsp;&nbsp; 000012&nbsp;&nbsp;&nbsp;&nbsp; 南&nbsp; 玻Ａ&nbsp; 0/0/ 10 <br>12&nbsp;&nbsp;&nbsp;&nbsp; 000014&nbsp;&nbsp;&nbsp;&nbsp; 沙河股份&nbsp; 0/0/ 11 <br>13&nbsp;&nbsp;&nbsp;&nbsp; 000016&nbsp;&nbsp;&nbsp;&nbsp; 深康佳Ａ&nbsp; 0/0/ 12 <br>14&nbsp;&nbsp;&nbsp;&nbsp; 000017&nbsp;&nbsp;&nbsp;&nbsp; S ST中华&nbsp; 0/0/ 13 <br>15&nbsp;&nbsp;&nbsp;&nbsp; 000018&nbsp;&nbsp;&nbsp;&nbsp; ST中冠Ａ&nbsp; 0/0/ 14 <br>16&nbsp;&nbsp;&nbsp;&nbsp; 000019&nbsp;&nbsp;&nbsp;&nbsp; 深深宝Ａ&nbsp; 0/0/ 15 <br>17&nbsp;&nbsp;&nbsp;&nbsp; 000020&nbsp;&nbsp;&nbsp;&nbsp; ST华发Ａ&nbsp; 0/0/ 16 <br>18&nbsp;&nbsp;&nbsp;&nbsp; 000021&nbsp;&nbsp;&nbsp;&nbsp; 长城开发&nbsp; 0/0/ 17 <br>19&nbsp;&nbsp;&nbsp;&nbsp; 000022&nbsp;&nbsp;&nbsp;&nbsp; 深赤湾Ａ&nbsp; 0/0/ 18 <br>20&nbsp;&nbsp;&nbsp;&nbsp; 000023&nbsp;&nbsp;&nbsp;&nbsp; 深天地Ａ&nbsp; 0/0/ 19 <br>21&nbsp;&nbsp;&nbsp;&nbsp; 000024&nbsp;&nbsp;&nbsp;&nbsp; 招商地产&nbsp; 0/0/ 20 <br>22&nbsp;&nbsp;&nbsp;&nbsp; 000025&nbsp;&nbsp;&nbsp;&nbsp; 特&nbsp; 力Ａ&nbsp; 0/0/ 21 <br>23&nbsp;&nbsp;&nbsp;&nbsp; 000026&nbsp;&nbsp;&nbsp;&nbsp; 飞亚达Ａ&nbsp; 0/0/ 22 <br>24&nbsp;&nbsp;&nbsp;&nbsp; 000027&nbsp;&nbsp;&nbsp;&nbsp; 深能源Ａ&nbsp; 0/0/ 23 <br>25&nbsp;&nbsp;&nbsp;&nbsp; 000028&nbsp;&nbsp;&nbsp;&nbsp; 一致药业&nbsp; 0/0/ 24 <br>26&nbsp;&nbsp;&nbsp;&nbsp; 000029&nbsp;&nbsp;&nbsp;&nbsp; 深深房Ａ&nbsp; 0/0/ 25 <br>27&nbsp;&nbsp;&nbsp;&nbsp; 000030&nbsp;&nbsp;&nbsp;&nbsp; S*ST盛润&nbsp; 0/0/ 26 <br>28&nbsp;&nbsp;&nbsp;&nbsp; 000031&nbsp;&nbsp;&nbsp;&nbsp; 中粮地产&nbsp; 0/0/ 27 <br>29&nbsp;&nbsp;&nbsp;&nbsp; 000032&nbsp;&nbsp;&nbsp;&nbsp; 深桑达Ａ&nbsp; 0/0/ 28 <br>30&nbsp;&nbsp;&nbsp;&nbsp; 000033&nbsp;&nbsp;&nbsp;&nbsp; 新都酒店&nbsp; 0/0/ 29 <br>31&nbsp;&nbsp;&nbsp;&nbsp; 000034&nbsp;&nbsp;&nbsp;&nbsp; SST 深泰&nbsp; 0/0/ 30 <br>32&nbsp;&nbsp;&nbsp;&nbsp; 000035&nbsp;&nbsp;&nbsp;&nbsp; ST 科 健&nbsp; 0/0/ 31 <br>33&nbsp;&nbsp;&nbsp;&nbsp; 000036&nbsp;&nbsp;&nbsp;&nbsp; 华联控股&nbsp; 0/0/ 32 <br>34&nbsp;&nbsp;&nbsp;&nbsp; 000037&nbsp;&nbsp;&nbsp;&nbsp; 深南电Ａ&nbsp; 0/0/ 33 <br>35&nbsp;&nbsp;&nbsp;&nbsp; 000039&nbsp;&nbsp;&nbsp;&nbsp; 中集集团&nbsp; 0/0/ 34 <br>36&nbsp;&nbsp;&nbsp;&nbsp; 000040&nbsp;&nbsp;&nbsp;&nbsp; 深 鸿 基&nbsp; 0/0/ 35 <br>37&nbsp;&nbsp;&nbsp;&nbsp; 000042&nbsp;&nbsp;&nbsp;&nbsp; 深 长 城&nbsp; 0/0/ 36 <br>38&nbsp;&nbsp;&nbsp;&nbsp; 000043&nbsp;&nbsp;&nbsp;&nbsp; 深南光Ａ&nbsp; 0/0/ 37 <br>39&nbsp;&nbsp;&nbsp;&nbsp; 000045&nbsp;&nbsp;&nbsp;&nbsp; 深纺织Ａ&nbsp; 0/0/ 38 <br>40&nbsp;&nbsp;&nbsp;&nbsp; 000046&nbsp;&nbsp;&nbsp;&nbsp; 泛海建设&nbsp; 0/0/ 39 <br>41&nbsp;&nbsp;&nbsp;&nbsp; 000048&nbsp;&nbsp;&nbsp;&nbsp; *ST 康达&nbsp; 0/1/ 0 <br>42&nbsp;&nbsp;&nbsp;&nbsp; 000049&nbsp;&nbsp;&nbsp;&nbsp; 德赛电池&nbsp; 0/1/ 1 <br>43&nbsp;&nbsp;&nbsp;&nbsp; 000050&nbsp;&nbsp;&nbsp;&nbsp; 深天马Ａ&nbsp; 0/1/ 2 <br>44&nbsp;&nbsp;&nbsp;&nbsp; 000055&nbsp;&nbsp;&nbsp;&nbsp; 方&nbsp; 大Ａ&nbsp; 0/1/ 3 <br>45&nbsp;&nbsp;&nbsp;&nbsp; 000056&nbsp;&nbsp;&nbsp;&nbsp; 深 国 商&nbsp; 0/1/ 4 <br>46&nbsp;&nbsp;&nbsp;&nbsp; 000058&nbsp;&nbsp;&nbsp;&nbsp; *ST 赛格&nbsp; 0/1/ 5 <br>47&nbsp;&nbsp;&nbsp;&nbsp; 000059&nbsp;&nbsp;&nbsp;&nbsp; 辽通化工&nbsp; 0/1/ 6 <br>48&nbsp;&nbsp;&nbsp;&nbsp; 000060&nbsp;&nbsp;&nbsp;&nbsp; 中金岭南&nbsp; 0/1/ 7 <br>49&nbsp;&nbsp;&nbsp;&nbsp; 000061&nbsp;&nbsp;&nbsp;&nbsp; 农 产 品&nbsp; 0/1/ 8 <br>50&nbsp;&nbsp;&nbsp;&nbsp; 000062&nbsp;&nbsp;&nbsp;&nbsp; 深圳华强&nbsp; 0/1/ 9 <br>51&nbsp;&nbsp;&nbsp;&nbsp; 000063&nbsp;&nbsp;&nbsp;&nbsp; 中兴通讯&nbsp; 0/1/ 10 <br>52&nbsp;&nbsp;&nbsp;&nbsp; 000065&nbsp;&nbsp;&nbsp;&nbsp; 北方国际&nbsp; 0/1/ 11 <br> <img src ="http://www.cppblog.com/Khan/aggbug/36752.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> 2007-11-16 15:23 <a href="http://www.cppblog.com/Khan/archive/2007/11/16/36752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Symbian s60 app初步研究</title><link>http://www.cppblog.com/Khan/archive/2007/10/19/34621.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Fri, 19 Oct 2007 09:04:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2007/10/19/34621.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/34621.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2007/10/19/34621.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/34621.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/34621.html</trackback:ping><description><![CDATA[CApaApplication 类实现两个接口 NewApplication 和 E32Dll<br><br>整个程序的入口就是 NewApplication&nbsp; , <br>启动顺序 NewApplication&nbsp; --&gt;　New CAknApplication -&gt; New CApaDocument <br>Document -&gt; CreateAppUiL 启动APPUI <br>appui装入一个view 然后进入消息响应模块<br><br><br>UI程序的panel图标和list图标的名称固定为context_pane_icon.bmp list_icon.bmp, mask图标名称固定为context_pane_icon_mask.bmp, list_icon_mask.bmp , 名称不能够自定义, 不能错..否则会显示不出图标.. <br><br><br> <img src ="http://www.cppblog.com/Khan/aggbug/34621.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> 2007-10-19 17:04 <a href="http://www.cppblog.com/Khan/archive/2007/10/19/34621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>symbian 的ini文件类.</title><link>http://www.cppblog.com/Khan/archive/2007/08/22/30582.html</link><dc:creator>Khan's Notebook</dc:creator><author>Khan's Notebook</author><pubDate>Wed, 22 Aug 2007 04:29:00 GMT</pubDate><guid>http://www.cppblog.com/Khan/archive/2007/08/22/30582.html</guid><wfw:comment>http://www.cppblog.com/Khan/comments/30582.html</wfw:comment><comments>http://www.cppblog.com/Khan/archive/2007/08/22/30582.html#Feedback</comments><slash:comments>26</slash:comments><wfw:commentRss>http://www.cppblog.com/Khan/comments/commentRss/30582.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Khan/services/trackbacks/30582.html</trackback:ping><description><![CDATA[//2007.12.22 修正<br><br><br>//CFile.h<br><br>#ifndef __C_FILE_H__<br>#define __C_FILE_H__<br><br>#include &lt;f32file.h&gt;<br>#include &lt;badesca.h&gt;<br><br><br><br>class CFile:public CBase<br>{<br><br>public:<br>&nbsp; static CFile *NewL(const TDesC &amp;p_fileName);<br>&nbsp; static CFile *NewLC(const TDesC &amp;p_fileName);<br>&nbsp; CFile(const TDesC&amp; p_fileName);<br>&nbsp; ~CFile();<br><br>public:<br>&nbsp; void ConstructL(TUint p_shareMode);<br>&nbsp; TInt FPuts(const TDesC8 &amp;aDes);<br>&nbsp; TInt FGets(TDes8 &amp;aDes) const;<br>&nbsp; TInt FSeek(TSeek aMode, TInt &amp;aPos) const;<br>&nbsp; TInt FSetSize(TInt aSize);<br>&nbsp; TInt FileSize() const;<br>&nbsp; void DostroyL();<br>&nbsp; <br>public:<br>&nbsp; static void GetDirFiles(const TDesC &amp;path, CDesCArray&amp; files);<br>&nbsp; static void LogToFile(const TDesC&amp; filename,TDesC8&amp;&nbsp; pdu);<br>&nbsp; //static void LogToFile(const TDesC&amp; filename,TDesC&amp;&nbsp; pdu);<br>&nbsp; static void GetLinesFromFile(const TDesC&amp; filename,CDesCArray&amp;&nbsp; lines);<br>&nbsp; static void GetLinesFromFile(const TDesC&amp; filename,CDesC8Array&amp;&nbsp; lines);<br>&nbsp; static bool MakeCbmDir(const TDesC&amp; aPath);<br>protected:<br>&nbsp; TBuf&lt;128&gt; mFileName;<br>&nbsp; RFs fs;<br>&nbsp; RFile file;<br>&nbsp; TInt mFileSize;<br>&nbsp; <br>};<br><br><br>#endif //__C_FILE_H__<br><br><br><br><br>//CFile.cpp<br><br>#include "CFile.h"<br><br>#include &lt;bautils.h&gt;<br>#include &lt;utf.h&gt;<br><br>_LIT8(KCRLF, "\r\n");<br><br>CFile *CFile::NewL(const TDesC &amp;p_fileName)<br>{<br>&nbsp; CFile *self = CFile::NewLC(p_fileName);<br>&nbsp; CleanupStack::Pop(self);<br>&nbsp; return self;<br>}<br><br><br>CFile *CFile::NewLC(const TDesC &amp;p_fileName)<br>{<br>&nbsp; CFile *self = new(ELeave) CFile(p_fileName);<br>&nbsp; CleanupStack::PushL(self);<br>&nbsp; return self;<br>}<br><br><br>CFile::CFile(const TDesC &amp;p_fileName)<br>{<br>&nbsp; mFileName.Copy(p_fileName);<br>&nbsp; mFileSize = 0;<br>}<br><br>CFile::~CFile()<br>{<br>&nbsp;&nbsp;&nbsp; <br>}<br><br>void CFile::ConstructL(TUint p_shareMode)<br>{<br>&nbsp; User::LeaveIfError(fs.Connect() );<br>&nbsp; TInt err = file.Open( fs, mFileName, p_shareMode);<br>&nbsp; <br>&nbsp; if(err==KErrNotFound) // file does not exist - create it<br>&nbsp;&nbsp;&nbsp; err=file.Create(fs, mFileName, p_shareMode);<br>&nbsp; <br>&nbsp; file.Size(mFileSize);<br>}<br><br><br><br>TInt CFile::FileSize() const<br>{<br>&nbsp;&nbsp;&nbsp; return mFileSize;<br>}<br><br><br><br>TInt CFile::FPuts(const TDesC8 &amp;aDes)<br>{<br>&nbsp; return file.Write(aDes);<br>}<br><br><br><br><br>TInt CFile::FGets(TDes8 &amp;aDes) const<br>{<br>&nbsp; return file.Read(aDes);<br>}<br><br><br>TInt CFile::FSeek(TSeek aMode, TInt &amp;aPos) const<br>{<br>&nbsp; return file.Seek(aMode, aPos);<br>}<br><br>TInt CFile::FSetSize(TInt aSize)<br>{<br>&nbsp; return file.SetSize(aSize);<br>}<br><br>void CFile::DostroyL()<br>{<br>&nbsp; file.Close();<br>&nbsp; fs.Close();<br>}<br><br><br><br>bool&nbsp; CFile::MakeCbmDir(const TDesC&amp; aPath){<br>&nbsp;&nbsp;&nbsp; RFs fs;<br>&nbsp;&nbsp;&nbsp; User::LeaveIfError(fs.Connect() );<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; if( BaflUtils::FolderExists(fs,aPath)&nbsp; ){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fs.Close();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if(KErrNone==fs.MkDirAll(aPath) ){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fs.Close();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return&nbsp; true;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; fs.Close();<br>&nbsp;&nbsp;&nbsp; return false;<br>}<br><br><br>void CFile::GetDirFiles(const TDesC&amp; path,CDesCArray&amp;&nbsp; files)<br>{<br>&nbsp; RFs fs;<br>&nbsp; User::LeaveIfError(fs.Connect() );<br><br>&nbsp; if( BaflUtils::FolderExists(fs,path)&nbsp; ){<br>&nbsp;&nbsp;&nbsp; CDir* dir=NULL;<br>&nbsp;&nbsp;&nbsp; User::LeaveIfError( fs.GetDir(path, KEntryAttNormal|KEntryAttMatchMask, ESortByName, dir) );<br>&nbsp;&nbsp;&nbsp; TInt ii=dir-&gt;Count();<br>&nbsp;&nbsp;&nbsp; for(TInt i=0;i&lt;ii;i++){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TEntry aEntry=(*dir)[i];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBuf&lt;256&gt; filePath(path);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; filePath.Append(aEntry.iName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; files.AppendL(filePath);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; fs.Close();<br>}<br><br><br>void CFile::LogToFile(const TDesC&amp; filename,TDesC8&amp;&nbsp; pdu)<br>{<br>&nbsp; //_LIT(name, "C:\\log.txt");<br>&nbsp; //TBuf&lt;32&gt; filename(name);<br>&nbsp; RFs fs;<br>&nbsp; RFile file;<br><br>&nbsp; User::LeaveIfError(fs.Connect() );<br>&nbsp; //CleanupClosePushL(fs);&nbsp; <br>&nbsp; //CleanupClosePushL(file);&nbsp; <br><br>&nbsp; TUint shareMode=EFileRead | EFileWrite ;<br>&nbsp; TInt err= file.Open( fs, filename,shareMode ) ;<br><br>&nbsp; if(err==KErrNotFound) // file does not exist - create it<br>&nbsp;&nbsp;&nbsp; err=file.Crea