??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
1. 静态函数库
q类库的名字一般是libxxx.aQ利用静态函数库~译成的文g比较大,因ؓ整个 函数库的所有数据都会被整合q目标代码中Q他的优点就显而易见了Q即~译后的执行E序不需要外部的函数库支持,因ؓ所有用的函数都已l被~译q去了。当然这也会成ؓ他的~点Q因为如果静态函数库改变了,那么你的E序必须重新~译?/p>
2. 动态函数库
q类库的名字一般是libxxx.so;相对于静态函数库Q动态函数库在编译的时?q没有被~译q目标代码中Q你的程序执行到相关函数时才调用该函数库里的相应函数Q因此动态函数库所产生的可执行文g比较。由于函数库没有被整合进你的E序Q而是E序q行时动态的甌q调用,所以程序的q行环境中必L供相应的库。动态函数库的改变ƈ不媄响你的程序,所以动态函数库的升U比较方ѝ?nbsp;
linuxpȝ有几个重要的目录存放相应的函数库Q如/lib /usr/lib?/p>
静态库的操作工Pgcc和ar 命o?nbsp;
~写及用静态库
(1)设计库源?pr1.c ?pr2.c
[root@billstone make_lib]# cat pr1.c
void print1()
{
printf("This is the first lib src!\n");
}
[root@billstone make_lib]# cat pr2.c
void print2()
{
printf("This is the second src lib!\n");
}
(2) ~译.c 文g
[bill@billstone make_lib]$ cc -O -c pr1.c pr2.c
[bill@billstone make_lib]$ ls -l pr*.o
-rw-rw-r-- 1 bill bill 804 4 ?nbsp; 15 11:11 pr1.o
-rw-rw-r-- 1 bill bill 804 4 ?nbsp; 15 11:11 pr2.o
(3) 链接静态库
Z在编译程序中正确扑ֈ库文?静态库必须按照 lib[name].a 的规则命?如下例中[name]=pr.
[bill@billstone make_lib]$ ar -rsv libpr.a pr1.o pr2.o
a - pr1.o
a - pr2.o
[bill@billstone make_lib]$ ls -l *.a
-rw-rw-r-- 1 bill bill 1822 4 ?nbsp; 15 11:12 libpr.a
[bill@billstone make_lib]$ ar -t libpr.a
pr1.o
pr2.o
(4) 调用库函C?main.c
[bill@billstone make_lib]$ cat main.c
int main()
{
print1();
print2();
return 0;
}
(5) ~译链接选项
-L ?l 参数攑֜后面.其中,-L 加蝲库文件\?-l 指明库文件名?
[bill@billstone make_lib]$ gcc -o main main.c -L./ -lpr
[bill@billstone make_lib]$ ls -l main*
-rwxrwxr-x 1 bill bill 11805 4 ?nbsp; 15 11:17 main
-rw-rw-r-- 1 bill bill 50 4 ?nbsp; 15 11:15 main.c
(6)执行目标E序
[bill@billstone make_lib]$ ./main
This is the first lib src!
This is the second src lib!
[bill@billstone make_lib]$
~写动态库
(1)设计库代?/strong>
[bill@billstone make_lib]$ cat pr1.c
int p = 2;
void print(){
printf("This is the first dll src!\n");
}
[bill@billstone make_lib]$
(2)生成动态库
[bill@billstone make_lib]$ gcc -O -fpic -shared -o dl.so pr1.c
[bill@billstone make_lib]$ ls -l *.so
-rwxrwxr-x 1 bill bill 6592 4 ?nbsp; 15 15:19 dl.so
[bill@billstone make_lib]$
动态库的隐式调?/strong>
在编译调用库函数代码时指明动态库的位|及名字, 看下面实?nbsp;
[bill@billstone make_lib]$ cat main.c
int main()
{
print();
return 0;
}
[bill@billstone make_lib]$ gcc -o tdl main.c ./dl.so
[bill@billstone make_lib]$ ./tdl
This is the first dll src!
[bill@billstone make_lib]$
当动态库的位|活名字发生改变? E序无法正常运? 而动态库取代静态库的好处之一则是通过更新动态库而随时升U库的内?
动态库的显式调?/strong>
昑ּ调用动态库需要四个函数的支持, 函数 dlopen 打开动态库, 函数 dlsym 获取动态库中对象基址, ?/strong>?dlerror 获取昑ּ动态库操作中的错误信息, 函数 doclose 关闭动态库.
[bill@billstone make_lib]$ cat main.c
#include <dlfcn.h>
int main()
{
void *pHandle;
void (*pFunc)(); // 指向函数的指?nbsp;
int *p;
pHandle = dlopen("./d1.so", RTLD_NOW); // 打开动态库
if(!pHandle){
printf("Can't find d1.so \n");
exit(1);
}
pFunc = (void (*)())dlsym(pHandle, "print"); // 获取库函?print 的地址
if(pFunc)
pFunc();
else
printf("Can't find function print\n");
p = (int *)dlsym(pHandle, "p"); // 获取库变?p 的地址
if(p)
printf("p = %d\n", *p);
else
printf("Can't find int p\n");
dlclose(pHandle); // 关闭动态库
return 0;
}
[bill@billstone make_lib]$ gcc -o tds main.c –ld1 –L.
此时q不能立?/tdsQ因为在动态函数库使用Ӟ会查?usr/lib?lib目录下的动态函数库Q而此时我们生成的库不在里辏V?q个时候有好几U方法可以让他成功运行: 最直接最单的Ҏ是把libstr_out.so拉到/usr/lib?lib中去?q有一U方?export LD_LIBRARY_PATH=$(pwd) 另外q可以在/etc/ld.so.conf文g里加入我们生成的库的目录Q然?sbin/ldconfig?/etc/ld.so.conf是非帔R要的一个目录,里面存放的是链接器和加蝲器搜索共享库时要查的目录Q默认是?usr/lib /lib中读取的Q所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中q执?sbin/ldconfig 。另外还有个文g需要了?etc/ld.so.cache,里面保存了常用的动态函数库Q且会先把他们加载到内存中,因ؓ内存的访问速度q远大于盘的访问速度Q这样可以提高Y件加载动态函数库的速度了?/p>
使用ldd命o来查看执行文件依赖于哪些库?/p>
该命令用于判断某个可执行?binary 档案含有什么动态函式库?br />
[root@test root]# ldd [-vdr] [filename]
参数说明Q?br />
--version 打印ldd的版本号
-v --verbose 打印所有信息,例如包括W号的版本信?br />
-d --data-relocs 执行W号重部|Ԍq报告缺的目标对象Q只对ELF格式适用Q?br />
-r --function-relocs 对目标对象和函数执行重新部vQƈ报告~少的目标对象和函数Q只对ELF格式适用Q?br />
--help 用法信息?/p>
如果命o行中l定的库名字包含'/'Q这个程序的libc5版本用它作ؓ库名字;否则它将在标准位|搜索库。运行一个当前目录下的共享库Q加前缀"./"?/p>
@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
假设l过一D|间的使用Q电脑里q行了很多程序,q些E序有些保留在内存中Q有?#8220;暂存”在硬盘中。如果这时候我们不打算使用电脑Q那?#8220;x”?#8220;休眠”Q和“睡眠”的不同点可以体现出来了?/p>
q?也就是说Q如果要让电脑关机,Windows首先要关闭所有运行中的程序,然后关闭pȝ后台的服务,接着向主板和甉|发出Ҏ的信P让电源切断对所有设 备的供电Q电脑彻底关闭。下ơ开机后Q电脑完成自工作Q然后将Windowspȝ载入内存Q接着l箋加蝲其他后台服务Qƈ昄d界面。登录后Q才可以 q行自己的程序,开始用电脑。整个过E因d关闭q头开始启动系l和E序Q因此所需的时间最常?br />
对于待机模式Q如果要电脑放?待机模式QWindows会自动向甉|发出另一U特D信P随后甉|会切断除了内存外其他讑֤的供电,内存中依然保存了pȝq行中的所有数据,q个q程一 两秒钟就可以完成。当从待机状态进入正常状态时Q只要通电Q然后Windows׃l箋从内存中保存的上一ơ的“状态数?#8221;下运行,q个q程也只需要几U?钟?br />
可见Q对于待机状态,完全可以不用关闭自己的程序,如果需要,随时可以待机。而要恢复时也只需要按下电源按钮,几秒钟即可恢复。但q?U模式虽然方便,但有一个致命的~陷Q不能停止对内存的供c因为内存是一U易失性存储设备,必须在保证供늚情况下才能维持其中的数据。因此一旦电脑在 待机状态下断电Q哪怕不CU钟Q内存中的数据将丢失Q下ơ开机的时候,Windows会像从关机状态下启动那样重新开始?br />
休眠模式和待 机模式类|只不q在休眠状态下QWindows会将内存中的数据保存到硬盘上pȝ盘根目录下的一个文件中Q可以将q个文g理解为内存状态的“镜像”Q?而下ơ开机后则从内存上的休眠文g内读取数据,q蝲入物理内存。休眠模式可以实现和待机模式cM的功能,只不q恢复速度E慢Q而且需要在盘上占据一块和 物理内存一样大的空间来保存休眠文g。物理内存越多,占用的空间就多Q而进入状态和从状态恢复所需的时间也p长(毕竟需要把文g从硬盘读入内存,而硬 盘的速度一直都是最慢的Q。但q种模式的优点也有很多,不怕断电!毕竟断电后硬盘上的数据ƈ不会丢失?br />
Windows Vista中开始新增了的一U睡眠模式则l合了待机和休眠模式的所有优炏V在q入睡眠模式后,Windows会首先将内存中的数据保存到硬盘上Q这一点类 g眠)Q同时切断除了内存外其他讑֤的供电(q一点类似待机)。在恢复Ӟ如果没有断过电,那么pȝ会从内存中直接恢复,只需要几U钟Q而就断电,?为硬盘中q保存有内存的状态镜像,因此q可以从盘上恢复,虽然速度要稍微慢一些,但至不用担心数据丢失?/p>
q入速度 | 恢复速度 | 是否耗电 | 断电后结?/span> | |
---|---|---|---|---|
睡眠 | 几秒?/span> | 不断늚情况下几U钟 | 需要对内存q行量供电 | 断电后,未保存数据不受损Q但恢复速度需要略微g长些 |
休眠 | 两分钟左?/span> | 两分钟左?/span> | 完全不耗电 | 未保存数据不会丢?/span> |
待机 | 几秒?/span> | 几秒?/span> | 需要对内存q行量供电 | 断电后所有未保存数据都会丢失 |
lg所qͼq几U模式各有利弊,但只要Windows和所用硬件支持,?span style="background-color: yellow; ">强烈使用睡眠功能代替以往习惯的关机操?/span>。毕竟睡眠功能的优势显而易见,不仅可以避免漫长的启动过E,而且完全可以把电脑当作电视一L一般电器,随开随关Q完全不用担心丢失数据?/p>
WINDOWS完成端口~程
摘要Q开发网l程序从来都不是一件容易的事情Q尽只需要遵守很的一些规?创徏socket,发vq接Q接受连接,发送和接受数据。真正的困难在于Q让你的E序可以适应从单单一个连接到几千个连接乃至于上万个连接。利用Windowsq_完成端口q行重叠I/O的技术和Linux?.6版本的内怸引入?strong>EPOll技术,可以很方便在在在Windows和Linuxq_上开发出支持大量q接的网l服务程序。本文介l在Windows和Linuxq_上用的完成端口?strong>EPoll模型开发的基本原理Q同时给出实际的例子。本文主要关注C/Sl构的服务器端程序,因ؓ一般来_开发一个大定wQ具可扩展性的winsockE序一般就是指服务E序?br />
1、基本概?br />
讑֤---windows操作pȝ上允讔R信的Q何东西,比如文g、目录、串行口、ƈ行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑盘、物理磁盘等。绝大多C讑֤打交道的函数都是CreateFile/ReadFile/WriteFile{。所以我们不能看?*File函数只惛_文g讑֤。与讑֤通信有两U方式,同步方式和异步方式。同步方式下Q当调用ReadFile函数Ӟ函数会等待系l执行完所要求的工作,然后才返回;异步方式下,ReadFileq类函数会直接返回,pȝ自己d成对讑֤的操作,然后以某U方式通知完成操作?br />
重叠I/O----思义Q当你调用了某个函数Q比如ReadFileQ就立刻q回做自q其他动作的时候,同时pȝ也在对I/0讑֤q行你要求的操作Q在q段旉内你的程序和pȝ的内部动作是重叠的,因此有更好的性能。所以,重叠I/O是用于异步方式下使用I/O讑֤的?重叠I/O需要用的一个非帔R要的数据l构OVERLAPPED?br />
2、WINDOWS完成端口的特?br />
Win32重叠I/O(Overlapped I/O)机制允许发v一个操作,然后在操作完成之后接受到信息。对于那U需要很长时间才能完成的操作来说Q重叠IO机制其有用Q因为发起重叠操作的U程在重叠请求发出后可以自q做别的事情了。在WinNT和Win2000上,提供的真正的可扩展的I/O模型是使用完成端口QCompletion PortQ的重叠I/O.完成端口---是一UWINDOWS内核对象?strong>完成端口用于异步方式的重叠I/0情况下,当然重叠I/O不一定非使用完成端口不可Q还有设备内核对象、事件对象、告警I/0{。但?strong>完成端口内部提供了线E池的管理,可以避免反复创徏U程的开销Q同时可以根据CPU的个数灵zȝ军_U程个数Q而且可以让减线E调度的ơ数从而提高性能其实cM于WSAAsyncSelect和select函数的机制更Ҏ兼容UnixQ但是难以实现我们想要的“扩展?#8221;。而且windows?strong>完成端口机制在操作系l内部已l作了优化,提供了更高的效率。所以,我们选择完成端口开始我们的服务器程序的开发?br />
1、发h作不一定完成,pȝ会在完成的时候通知你,通过用户?strong>完成端口上的{待Q处理操作的l果。所以要有检?strong>完成端口Q取操作l果的线E。在完成端口上守候的U程pȝ有优化,除非在执行的U程dQ不会有新的U程被激z,以此来减线E切换造成的性能代h。所以如果程序中没有太多的阻塞操作,没有必要启动太多的线E,CPU数量的两倍,一般这h启动U程?br />
2、操作与相关数据的绑定方式:在提交数据的时候用户对数据打相应的标记Q记录操作的cdQ在用户处理操作l果的时候,通过查自己打的标记和pȝ的操作结果进行相应的处理?nbsp;
3、操作返回的方式:一般操作完成后要通知E序q行后箋处理。但写操作可以不通知用户Q此时如果用户写操作不能马上完成Q写操作的相x据会被暂存到到非交换~冲ZQ在操作完成的时候,pȝ会自动释攄冲区。此时发起完写操作,使用的内存就可以释放了。此时如果占用非交换~冲太多会ɾpȝ停止响应?br />
3?strong>完成端口QCompletion Ports Q相x据结构和创徏
其实可以?strong>完成端口看成pȝl护的一个队列,操作pȝ把重叠IO操作完成的事仉知攑ֈ该队列里Q由于是暴露 “操作完成”的事仉知Q所以命名ؓ“完成端口”QCOmpletion PortsQ。一个socket被创建后Q可以在M时刻和一?strong>完成端口联系h?br />
完成端口相关最重要的是OVERLAPPED数据l构
typedef struct _OVERLAPPED {
ULONG_PTR Internal;//被系l内部赋|用来表示pȝ状?nbsp;
ULONG_PTR InternalHigh;// 被系l内部赋|传输的字节数
union {
struct {
DWORD Offset;//和OffsetHigh合成一?4位的整数Q用来表CZ文g头部的多字节开?nbsp;
DWORD OffsetHigh;//操作Q如果不是对文gI/O来操作,则必设定ؓ0
};
PVOID Pointer;
};
HANDLE hEvent;//如果不用,务必设?,否则误一个有效的Event句柄
} OVERLAPPED, *LPOVERLAPPED;
下面是异步方式用ReadFile的一个例?nbsp;
OVERLAPPED Overlapped;
Overlapped.Offset=345;
Overlapped.OffsetHigh=0;
Overlapped.hEvent=0;
//假定其他参数都已l被初始?nbsp;
ReadFile(hFile,buffer,sizeof(buffer),&dwNumBytesRead,&Overlapped);
q样完成了异步方式L件的操作Q然后ReadFile函数q回Q由操作pȝ做自q事情Q下面介l几个与OVERLAPPEDl构相关的函?nbsp;
{待重叠I/0操作完成的函?nbsp;
BOOL GetOverlappedResult (
HANDLE hFile,
LPOVERLAPPED lpOverlapped,//接受q回的重叠I/0l构
LPDWORD lpcbTransfer,//成功传输了多字节数
BOOL fWait //TRUE只有当操作完成才q回QFALSE直接q回Q如果操作没有完成,通过?/用GetLastError ( )函数会返回ERROR_IO_INCOMPLETE
);
宏HasOverlappedIoCompleted可以帮助我们试重叠I/0操作是否完成Q该宏对OVERLAPPEDl构的Internal成员q行了测试,查看是否{于STATUS_PENDING倹{?/p>
一般来_一个应用程序可以创建多个工作线E来处理完成端口上的通知事g。工作线E的数量依赖于程序的具体需要。但是在理想的情况下Q应该对应一个CPU创徏一个线E。因为在完成端口理想模型中,每个U程都可以从pȝ获得一?#8220;原子”性的旉片,轮番q行q检?strong>完成端口Q线E的切换是额外的开销。在实际开发的时候,q要考虑q些U程是否牉|到其他堵塞操作的情况。如果某U程q行堵塞操作Q系l则其挂vQ让别的U程获得q行旉。因此,如果有这L情况Q可以多创徏几个U程来尽量利用时间?br />
应用完成端口Q?br />
创徏完成端口Q?strong>完成端口是一个内核对象,使用时他L要和臛_一个有效的讑֤句柄q行兌Q?strong>完成端口是一个复杂的内核对象Q创建它的函数是Q?br />
HANDLE CreateIoCompletionPort(
IN HANDLE FileHandle,
IN HANDLE ExistingCompletionPort,
IN ULONG_PTR CompletionKey,
IN DWORD NumberOfConcurrentThreads
);
通常创徏工作分两步:
W一步,创徏一个新?strong>完成端口内核对象Q可以用下面的函数Q?br />
HANDLE CreateNewCompletionPort(DWORD dwNumberOfThreads)
{
return CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,dwNumberOfThreads);
};
W二步,刚创徏?strong>完成端口和一个有效的讑֤句柄兌hQ可以用下面的函数Q?br />
bool AssicoateDeviceWithCompletionPort(HANDLE hCompPort,HANDLE hDevice,DWORD dwCompKey)
{
HANDLE h=CreateIoCompletionPort(hDevice,hCompPort,dwCompKey,0);
return h==hCompPort;
};
说明
1Q?CreateIoCompletionPort函数也可以一ơ性的既创?strong>完成端口对象Q又兌C个有效的讑֤句柄
2Q?CompletionKey是一个可以自己定义的参数Q我们可以把一个结构的地址赋给它,然后在合适的时候取出来使用Q最好要保证l构里面的内存不是分配在栈上Q除非你有十分的把握内存会保留到你要使用的那一刅R?br />
3Q?NumberOfConcurrentThreads通常用来指定要允许同时运行的的线E的最大个数。通常我们指定?Q这Ll会ҎCPU的个数来自动定。创建和兌的动作完成后Q系l会?strong>完成端口兌的设备句柄、完成键作ؓ一条纪录加入到q个完成端口的设备列表中。如果你有多?strong>完成端口Q就会有多个对应的设备列表。如果设备句柄被关闭Q则表中自动删除该纪录?br />
4?strong>完成端口U程的工作原?/strong>
完成端口可以帮助我们理U程池,但是U程池中的线E需要我们用_beginthreadex来创建,凭什么通知完成端口理我们的新U程呢?{案在函数GetQueuedCompletionStatus。该函数原型Q?nbsp;
BOOL GetQueuedCompletionStatus(
IN HANDLE CompletionPort,
OUT LPDWORD lpNumberOfBytesTransferred,
OUT PULONG_PTR lpCompletionKey,
OUT LPOVERLAPPED *lpOverlapped,
IN DWORD dwMilliseconds
);
q个函数试图从指定的完成端口的I/0完成队列中抽取纪录。只有当重叠I/O动作完成的时候,完成队列中才有纪录。凡是调用这个函数的U程被攑օ?strong>完成端口的等待线E队列中Q因?strong>完成端口可以在自己的线E池中帮助我们维护这个线E?strong>完成端口的I/0完成队列中存放了当重叠I/0完成的结?--- 一条纪录,该纪录拥有四个字D,前三就对应GetQueuedCompletionStatus函数???参数Q最后一个字D|错误信息dwError。我们也可以通过调用PostQueudCompletionStatus模拟完成了一个重叠I/0操作?nbsp;
当I/0完成队列中出CU录Q?strong>完成端口会查等待线E队列,该队列中的线E都是通过调用GetQueuedCompletionStatus函数使自己加入队列的。等待线E队列很单,只是保存了这些线E的ID?strong>完成端口会按照后q先出的原则一个线E队列的ID攑օ到释攄E列表中Q同时该U程从{待GetQueuedCompletionStatus函数q回的睡眠状态中变ؓ可调度状态等待CPU的调度。所以我们的U程要想成ؓ完成端口理的线E,必要调用GetQueuedCompletionStatus函数。出于性能的优化,实际?strong>完成端口q维护了一个暂停线E列表,具体l节可以参考《Windows高~程指南》,我们现在知道的知识,已经_了?nbsp;完成端口U程间数据传递线E间传递数据最常用的办法是在_beginthreadex函数中将参数传递给U程函数Q或者用全局变量。但?strong>完成端口q有自己的传递数据的ҎQ答案就在于CompletionKey和OVERLAPPED参数?br />
CompletionKey被保存在完成端口的设备表中,是和讑֤句柄一一对应的,我们可以与讑֤句柄相关的数据保存到CompletionKey中,或者将CompletionKey表示为结构指针,q样可以传递更加丰富的内容。这些内容只能在一开始关?strong>完成端口和设备句柄的时候做Q因此不能在以后动态改变?br />
OVERLAPPED参数是在每次调用ReadFileq样的支持重叠I/0的函数时传递给完成端口的。我们可以看刎ͼ如果我们不是Ҏ件设备做操作Q该l构的成员变量就Ҏ们几乎毫无作用。我们需要附加信息,可以创徏自己的结构,然后OVERLAPPEDl构变量作ؓ我们l构变量的第一个成员,然后传递第一个成员变量的地址lReadFile函数。因为类型匹配,当然可以通过~译。当GetQueuedCompletionStatus函数q回Ӟ我们可以获取到第一个成员变量的地址Q然后一个简单的强制转换Q我们就可以把它当作完整的自定义l构的指针用,q样可以传递很多附加的数据了。太好了Q只有一点要注意Q如果跨U程传递,h意将数据分配到堆上,q且接收端应该将数据用完后释放。我们通常需要将ReadFileq样的异步函数的所需要的~冲区放到我们自定义的结构中Q这样当GetQueuedCompletionStatus被返回时Q我们的自定义结构的~冲区变量中存放了I/0操作的数据。CompletionKey和OVERLAPPED参数Q都可以通过GetQueuedCompletionStatus函数获得?br />
U程的安全退?br />
很多U程Z不止一ơ的执行异步数据处理Q需要用如下语?br />
while (true)
{
......
GetQueuedCompletionStatus(...);
......
}
那么如何退出呢Q答案就在于上面曾提到的PostQueudCompletionStatus函数Q我们可以用它发送一个自定义的包含了OVERLAPPED成员变量的结构地址Q里面包含一个状态变量,当状态变量ؓ退出标志时Q线E就执行清除动作然后退出?br />
5、Windows完成端口的实例代码:
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
ULONG_PTR *PerHandleKey;
OVERLAPPED *Overlap;
OVERLAPPEDPLUS *OverlapPlus,
*newolp;
DWORD dwBytesXfered;
while (1)
{
ret = GetQueuedCompletionStatus(
hIocp,
&dwBytesXfered,
(PULONG_PTR)&PerHandleKey,
&Overlap,
INFINITE);
if (ret == 0)
{
// Operation failed
continue;
}
OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, ol);
switch (OverlapPlus->OpCode)
{
case OP_ACCEPT:
// Client socket is contained in OverlapPlus.sclient
// Add client to completion port
CreateIoCompletionPort(
(HANDLE)OverlapPlus->sclient,
hIocp,
(ULONG_PTR)0,
0);
// Need a new OVERLAPPEDPLUS structure
// for the newly accepted socket. Perhaps
// keep a look aside list of free structures.
newolp = AllocateOverlappedPlus();
if (!newolp)
{
// Error
}
newolp->s = OverlapPlus->sclient;
newolp->OpCode = OP_READ;
// This function divpares the data to be sent
PrepareSendBuffer(&newolp->wbuf);
ret = WSASend(
newolp->s,
&newolp->wbuf,
1,
&newolp->dwBytes,
0,
&newolp.ol,
NULL);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// Error
}
}
// Put structure in look aside list for later use
FreeOverlappedPlus(OverlapPlus);
// Signal accept thread to issue another AcceptEx
SetEvent(hAcceptThread);
break;
case OP_READ:
// Process the data read
// Repost the read if necessary, reusing the same
// receive buffer as before
memset(&OverlapPlus->ol, 0, sizeof(OVERLAPPED));
ret = WSARecv(
OverlapPlus->s,
&OverlapPlus->wbuf,
1,
&OverlapPlus->dwBytes,
&OverlapPlus->dwFlags,
&OverlapPlus->ol,
NULL);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// Error
}
}
break;
case OP_WRITE:
// Process the data sent, etc.
break;
} // switch
} // while
} // WorkerThread
查看以上代码Q注意如果Overlapped操作立刻p|Q比如,q回SOCKET_ERROR或其他非WSA_IO_PENDING的错误)Q则没有M完成通知旉会被攑ֈ完成端口队列里。反之,则一定有相应的通知旉被放?strong>完成端口队列。更完善的关于Winsock?strong>完成端口机制Q可以参考MSDN的Microsoft PlatFormSDKQ那里有完成端口的例子。访?a >http://msdn.microsoft.com/library/techart/msdn_servrapp.htm可以获得更多信息?/p>
Linux?strong>EPoll模型
Linux 2.6内核中提高网lI/O性能的新Ҏ-epoll I/O多\复用技术在比较多的TCP|络服务器中有用,x较多的用到select函数?br />
1、ؓ什么select落后
首先Q在Linux内核中,select所用到的FD_SET是有限的Q即内核中有个参数__FD_SETSIZE定义了每个FD_SET的句柄个敎ͼ在我用的2.6.15-25-386内核中,该值是1024Q搜索内核源代码得到Q?br />
include/linux/posix_types.h:#define __FD_SETSIZE 1024
也就是说Q如果想要同时检?025个句柄的可读状态是不可能用select实现的。或者同时检?025个句柄的可写状态也是不可能的。其ơ,内核中实现select是用轮询ҎQ即每次都会遍历所有FD_SET中的句柄Q显Ӟselect函数执行旉与FD_SET中的句柄个数有一个比例关p,即select要检的句柄数越多就会越Ҏ。当Ӟ在前文中我ƈ没有提及pollҎQ事实上用select的朋友一定也试过pollQ我个h觉得select和poll大同异Q个人偏好于用select而已?/p>
2、内怸提高I/O性能的新Ҏepoll
epoll是什么?按照man手册的说法:是ؓ处理大批量句柄而作了改q的poll。要使用epoll只需要这三个pȝ调用Q?strong>epoll_create(2)Q?nbsp;epoll_ctl(2)Q?nbsp;epoll_wait(2)?br />
当然Q这不是2.6内核才有的,它是?.5.44内核中被引进?epoll(4) is a new API introduced in Linux kernel 2.5.44)
Linux2.6内核epoll介绍
先介l?本书《The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel》,?.4内核讲解Linux TCP/IP实现Q相当不?作ؓ一个现实世界中的实玎ͼ很多时候你必须作很多权衡,q时候参考一个久l考验的系l更有实际意义。D个例?linux内核中sk_buffl构Zq求速度和安全,牺牲了部分内存,所以在发送TCP包的时候,无论应用层数据多?sk_buff最也?72的字?其实对于socket应用层程序来_另外一本书《UNIX Network Programming Volume 1》意义更大一?2003q的时候,q本书出了最新的W?版本Q不q主要还是修订第2版本。其中第6章《I/O Multiplexing》是最重要的。Stevensl出了网lIO的基本模型。在q里最重要的莫q于select模型和Asynchronous I/O模型.从理Z_AIOg是最高效的,你的IO操作可以立即q回Q然后等待os告诉你IO操作完成。但是一直以来,如何实现没有一个完的Ҏ。最著名的windows完成端口实现的AIO,实际上也是内部用U程池实现的|了Q最后的l果是IO有个U程池,你应用也需要一个线E池...... 很多文档其实已经指出了这带来的线Econtext-switch带来的代仗在linux q_上,关于|络AIO一直是改动最多的地方Q?.4的年代就有很多AIO内核patch,最著名的应该算是SGI那个。但是一直到2.6内核发布Q网l模块的AIO一直没有进入稳定内核版?大部分都是用用LE模拟方法,在用了NPTL的linux上面其实和windows?strong>完成端口基本上差不多??.6内核所支持的AIOҎ盘的AIO---支持io_submit(),io_getevents()以及对Direct IO的支?是l过VFSpȝbuffer直接写硬盘,对于服务器在内存^Ex上有相当帮??br />
所以,剩下的select模型基本上就是我们在linux上面的唯一选择Q其实,如果加上no-block socket的配|,可以完成一??AIO的实玎ͼ只不q推动力在于你而不是os而已。不q传l的select/poll函数有着一些无法忍受的~点Q所以改q一直是2.4-2.5开发版本内核的dQ包?dev/pollQrealtime signal{等。最l,Davide Libenzi开发的epollq入2.6内核成ؓ正式的解x?br />
3?strong>epoll的优?/strong>
<1>支持一个进E打开大数目的socket描述W?FD)
select 最不能忍受的是一个进E所打开的FD是有一定限制的Q由FD_SETSIZE讄Q默认值是2048。对于那些需要支持的上万q接数目的IM服务器来说显然太了。这时候你一是可以选择修改q个宏然后重新编译内核,不过资料也同时指样会带来|络效率的下降,二是可以选择多进E的解决Ҏ(传统的ApacheҎ)Q不q虽然linux上面创徏q程的代h较小Q但仍旧是不可忽视的Q加上进E间数据同步q比不上U程间同步的高效Q所以也不是一U完的Ҏ。不q?nbsp;epoll则没有这个限Ӟ它所支持的FD上限是最大可以打开文g的数目,q个数字一般远大于2048,举个例子,?GB内存的机器上大约?0万左叻I具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和pȝ内存关系很大?br />
<2>IO效率不随FD数目增加而线性下?br />
传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合Q不q由于网lgӞM旉只有部分的socket?z跃"的,但是select/poll每次调用都会U性扫描全部的集合Q导致效率呈现线性下降。但?strong>epoll不存在这个问题,它只会对"z跃"的socketq行操作---q是因ؓ在内核实Cepoll是根据每个fd上面的callback函数实现的。那么,只有"z跃"的socket才会d的去调用 callback函数Q其他idle状态socket则不会,在这点上Q?strong>epoll实现了一??AIOQ因时候推动力在os内核。在一?benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境Q?strong>epollq不比select/poll有什么效率,相反Q如果过多?strong>epoll_ctl,效率相比q有E微的下降。但是一旦用idle connections模拟WAN环境,epoll的效率就q在select/poll之上了?br />
<3>使用mmap加速内怸用户I间的消息传递?br />
q点实际上涉及到epoll的具体实C。无论是select,pollq是epoll都需要内核把FD消息通知l用L_如何避免不必要的内存拯很重要Q在q点上,epoll是通过内核于用L间mmap同一块内存实现的。而如果你x一样从2.5内核关?strong>epoll的话Q一定不会忘记手?mmapq一步的?br />
<4>内核微调
q一点其实不?strong>epoll的优点了Q而是整个linuxq_的优炏V也怽可以怀疑linuxq_Q但是你无法回避linuxq_赋予你微调内核的能力。比如,内核TCP/IP协议栈用内存池理sk_buffl构Q那么可以在q行时期动态调整这个内存pool(skb_head_pool)的大?-- 通过echo XXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参?TCP完成3ơ握手的数据包队列长?Q也可以Ҏ你^台内存大动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本w大却很小的特D系l上试最新的NAPI|卡驱动架构?br />
4?strong>epoll的工作模?br />
令h高兴的是Q?.6内核?strong>epoll比其2.5开发版本的/dev/epollz了许多Q所以,大部分情况下Q强大的东西往往是简单的。唯一有点ȝ?strong>epoll?U工作方?LT和ET?br />
LT(level triggered)是缺省的工作方式Qƈ且同时支持block和no-block socket.在这U做法中Q内核告诉你一个文件描q符是否qA了,然后你可以对q个qA的fdq行IO操作。如果你不作M操作Q内核还是会l箋通知你的Q所以,q种模式~程出错误可能性要一炏V传l的select/poll都是q种模型的代表.
ET (edge-triggered)是高速工作方式,只支持no-block socket。在q种模式下,当描q符从未qA变ؓqAӞ内核通过epoll告诉你。然后它会假设你知道文g描述W已l就l,q且不会再ؓ那个文g描述W发送更多的qA通知Q直C做了某些操作D那个文g描述W不再ؓqA状态了(比如Q你在发送,接收或者接收请求,或者发送接收的数据于一定量时导致了一个EWOULDBLOCK 错误Q。但是请注意Q如果一直不对这个fd作IO操作(从而导致它再次变成未就l?Q内怸会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark认?br />
epoll只有epoll_create,epoll_ctl,epoll_wait 3个系l调用,具体用法请参?a >http://www.xmailserver.org/linux-patches/nio-improve.html Q在http://www.kegel.com/rn/也有一个完整的例子Q大家一看就知道如何使用?br />
Leader/follower模式U程pool实现Q以及和epoll的配合?br />
5?nbsp;epoll的用方?/strong>
首先通过create_epoll(int maxfds)来创Z?strong>epoll的句柄,其中maxfdsZepoll所支持的最大句柄数。这个函Cq回一个新?strong>epoll句柄Q之后的所有操作将通过q个句柄来进行操作。在用完之后Q记得用close()来关闭这个创建出来的epoll句柄?之后在你的网l主循环里面Q每一帧的调用epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的|络接口Q看哪一个可以读Q哪一个可以写了。基本的语法为:
nfds = epoll_wait(kdpfd, events, maxevents, -1);
其中kdpfd为用epoll_create创徏之后的句柄,events是一?strong>epoll_event*的指针,?strong>epoll_waitq个函数操作成功之后Q?strong>epoll_events里面储存所有的d事g。max_events是当前需要监听的所有socket句柄数。最后一个timeout?strong>epoll_wait的超Ӟ?的时候表C马上返回,?1的时候表CZ直等下去Q直到有事g范围QؓL正整数的时候表C等q么长的旉Q如果一直没有事Ӟ则范围。一般如果网l主循环是单独的U程的话Q可以用-1来等Q这样可以保证一些效率,如果是和主逻辑在同一个线E的话,则可以用0来保证主循环的效率?/p>
epoll_wait范围之后应该是一个@环,遍利所有的事gQ?nbsp;
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) { //如果是主socket的事件的话,则表C有新连接进入了Q进行新q接的处理?nbsp;
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client); // 新q接|于非阻塞模?nbsp;
ev.events = EPOLLIN | EPOLLET; // q且新q接也加?strong>EPOLL的监听队列?nbsp;
注意Q这里的参数EPOLLIN | EPOLLETq没有设|对写socket的监听,如果有写操作的话Q这个时?strong>epoll是不会返回事件的Q如果要对写操作也监听的话,应该是EPOLLIN | EPOLLOUT | EPOLLET
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
// 讄好event之后Q将q个新的event通过epoll_ctl加入?strong>epoll的监听队列里面,q里?strong>EPOLL_CTL_ADD来加一个新?strong>epoll事gQ通过EPOLL_CTL_DEL来减一?strong>epoll事gQ通过EPOLL_CTL_MOD来改变一个事件的监听方式?nbsp;
fprintf(stderr, "epoll set insertion error: fd=%d0,
client);
return -1;
}
}
else // 如果不是主socket的事件的话,则代表是一个用户socket的事Ӟ则来处理q个用户socket的事情,比如说read(fd,xxx)之类的,或者一些其他的处理?nbsp;
do_use_fd(events[n].data.fd);
}
对,epoll的操作就q么单,d不过4个APIQ?strong>epoll_create, epoll_ctl, epoll_wait和close?nbsp;
如果您对epoll的效率还不太了解Q请参考我之前关于|络游戏的网l编E等相关的文章?/p>
以前公司的服务器都是使用HTTPq接Q但是这L话,在手机目前的|络情况下不但显得速度较慢Q而且不稳定。因此大家一致同意用SOCKET来进行连接。虽然用SOCKET之后Q对于用L费用可能会增?׃是用了CMNET而非CMWAP)Q但是,U着用户体验至上的原则,怿大家q是能够接受?希望那些玩家月末收到帐单不后能够保持克制...)?br />
q次的服务器设计中,最重要的一个突_是用了EPOLL模型Q虽然对之也是一知半解,但是既然在各大PC|游中已l经q了如此严酷的考验Q相信他不会让我们失望,使用后的l果Q确实也是表现相当不错。在q里Q我q是主要大致介绍一下这个模型的l构?br />
6、Linux?strong>EPOll~程实例
EPOLL模型g只有一U格式,所以大家只要参考我下面的代码,p够对EPOLL有所了解了,代码的解释都已经在注释中Q?/p>
while (TRUE)
{
int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//{待EPOLL旉的发生,相当于监听,至于相关的端口,需要在初始?strong>EPOLL的时候绑定?br />
if (nfds <= 0)
continue;
m_bOnTimeChecking = FALSE;
G_CurTime = time(NULL);
for (int i=0; i
{
try
{
if (m_events[i].data.fd == m_listen_http_fd)//如果新监到一个HTTP用户q接到绑定的HTTP端口Q徏立新的连接。由于我们新采用了SOCKETq接Q所以基本没用?br />
{
OnAcceptHttpEpoll ();
}
else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监到一个SOCKET用户q接Cl定的SOCKET端口Q徏立新的连接?br />
{
OnAcceptSockEpoll ();
}
else if (m_events[i].events & EPOLLIN)//如果是已l连接的用户Qƈ且收到数据,那么q行d?br />
{
OnReadEpoll (i);
}
OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据?br />
}
catch (int)
{
PRINTF ("CATCH捕获错误\n");
continue;
}
}
m_bOnTimeChecking = TRUE;
OnTimer ();//q行一些定时的操作Q主要就是删除一些短U用L?br />
}
其实EPOLL的精华,也就是上q的几段短短的代码,看来时代真的不同了,以前如何接受大量用户q接的问题,现在却被如此L的搞定,真是让h不得不感叹,对哪?/p>
ȝ
Windows完成端口与Linux epoll技术方案是q?个^C实现异步IO和设计开发一个大定wQ具可扩展性的winsockE序指服务程序的很好的选择Q本文对q?中技术的实现原理和实际的使用Ҏ做了一个详l的介绍?/p>
@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
在本文中Q将l大家介l如何?nbsp;autoconf和automake两个工具来帮助我们自动地生成W合自由软g惯例的MakefileQ这样就可以象常见的GNUE序一P只要使用“./configure”Q?#8220;make”Q?#8220;make install”可以把E序安装到Linuxpȝ中去了。这特别适合惛_开放源代码软g的程序开发h员,又或如果你只是自己写些小的ToyE序Q那么这个文章对你也会有很大的帮助?/p>
~译一个简单的源文件main.c,需要自动生成一个makefile,以下是步骤:
W一步:
----------
?root/project/main目录下创Z个文件main.c,其内容如下:
------------------------------------------------
#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello, Auto Makefile!\n");
return 0;
}
------------------------------------------------
此时状态如下:
[root@localhost main]# pwd
/root/project/main
[root@localhost main]# ls
main.c
[root@localhost main]#
W二步:
----------
q行 autoscan , 自动创徏两个文gQ?autoscan.log configure.scan
此时状态如下:
[root@localhost main]# autoscan
[root@localhost main]# ls
autoscan.log configure.scan main.c
[root@localhost main]#
W三步:
----------
修改configure.scan的文件名为configure.in
查看configure.in的内容:
------------------------------------------------
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_OUTPUT
------------------------------------------------
解读以上的文Ӟ
------------------------------------------------
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
# AC_PREREQ:
# 保使用的是_新的Autoconf版本。如果用于创建configure的Autoconf的版
# 本比version 要早Q就在标准错误输出打C条错误消息ƈ不会创徏configure?/p>
AC_PREREQ(2.61)
#
# 初始?定义软g的基本信?包括讄包的全称,版本号以及报告BUG旉要用的邮地址
#
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
#
# 用来侦测所指定的源码文件是否存在,来确定源码目录的有效?/p>
#
AC_CONFIG_SRCDIR([main.c])
#
# 用于生成config.h文gQ以便autoheader使用
#
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
#
# 创徏输出文g。在`configure.in'的末调用本宏一ơ?/p>
#
AC_OUTPUT
------------------------------------------------
修改动作:
1.修改AC_INIT里面的参? AC_INIT(main,1.0, pgpxc@163.com)
2.d宏AM_INIT_AUTOMAKE, 它是automake所必备的宏Q也同前面一PPACKAGE是所要生Y件套件的名称QVERSION是版本编受?/p>
3.在AC_OUTPUT后添加输出文件Makefile
修改后的l果:
------------------------------------------------
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT(main, 1.0, pgpxc@163.com)
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(main,1.0)
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_OUTPUT([Makefile])
------------------------------------------------
W四?
q行 aclocal, 生成一?#8220;aclocal.m4”文g和一个缓冲文件夹autom4te.cacheQ该文g主要处理本地的宏定义?/p>
此时的状态是Q?/p>
[root@localhost main]# aclocal
[root@localhost main]# ls
aclocal.m4 autom4te.cache autoscan.log configure.in configure.in~ main.c
[root@localhost main]#
W五步:
q行 autoconf, 目的是生?configure
此时的状态是Q?/p>
[root@localhost main]# autoconf
[root@localhost main]# ls
aclocal.m4 autoscan.log configure.in main.c
autom4te.cache configure configure.in~
[root@localhost main]#
W六步:
q行 autoheaderQ它负责生成config.h.in文g。该工具通常会从“acconfig.h”文g中复制用户附加的W号定义Q因此此处没有附加符号定义,所以不需要创?#8220;acconfig.h”文g?/p>
此时的状态是Q?/p>
[root@localhost main]# autoheader
[root@localhost main]# ls
aclocal.m4 autoscan.log configure configure.in~
autom4te.cache config.h.in configure.in main.c
[root@localhost main]#
W七步:
下面卛_q行 automake, 但在此之前应该做一下准备工?
首先
创徏一?nbsp;Makefile.am.q一步是创徏Makefile很重要的一步,automake要用的脚本配|文件是Makefile.amQ用户需要自己创建相应的文g。之后,automake工具转换成Makefile.in?/p>
q个Makefile.am的内容如下:
------------------------------------------------
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=main
main_SOURCES=main.c
------------------------------------------------
下面对该脚本文g的对应项q行解释?/p>
其中的AUTOMAKE_OPTIONS|automake的选项。由于GNUQ在W?章中已经有所介绍Q对自己发布的Y件有严格的规范,比如必须?带许可证声明文gCOPYING{,否则automake执行时会报错。automake提供了三UY件等U:foreign、gnu和gnitsQ让?户选择采用Q默认等Uؓgnu。在本例使用foreign{Q它只检必ȝ文g?/p>
bin_PROGRAMS定义要生的执行文g名。如果要产生多个执行文gQ每个文件名用空格隔开?/p>
main_SOURCES定义“main”q个执行E序所需要的原始文g。如?#8221;main”q个E序是由多个原始文g所产生的,则必L它所用到的所有原 始文仉列出来,q用I格隔开。例如:若目标体“main”需?#8220;main.c”?#8220;sunq.c”?#8220;main.h”三个依赖文gQ则定义 main_SOURCES=main.c sunq.c main.h。要注意的是Q如果要定义多个执行文gQ则Ҏ个执行程序都要定义相应的file_SOURCES?/p>
其次
使用automake对其生成“configure.in”文gQ在q里使用选项“—adding-missing”可以让automake自动d有一些必需的脚本文件?/p>
q行后的状态是Q?/p>
------------------------------------------------
[root@localhost main]# automake --add-missing
configure.in:8: installing `./missing'
configure.in:8: installing `./install-sh'
Makefile.am: installing `./depcomp'
[root@localhost main]# ls
aclocal.m4 config.h.in configure.in~ main.c Makefile.in
autom4te.cache configure depcomp Makefile.am missing
autoscan.log configure.in install-sh Makefile.am~
[root@localhost main]#
------------------------------------------------
W八?/p>
q行configureQ在q一步中Q通过q行自动配置讄文gconfigureQ把Makefile.in变成了最l的Makefile?/p>
q行的结果如下:
------------------------------------------------
[root@localhost main]# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
[root@localhost main]# ls
aclocal.m4 config.h.in configure.in main.c Makefile.in
autom4te.cache config.log configure.in~ Makefile missing
autoscan.log config.status depcomp Makefile.am stamp-h1
config.h configure install-sh Makefile.am~
[root@localhost main]#
------------------------------------------------
W九?/p>
q行 makeQ对配置文gMakefileq行试一?/p>
此时的状态如?
------------------------------------------------
[root@localhost main]# make
cd . && /bin/sh /root/project/main/missing --run aclocal-1.10
cd . && /bin/sh /root/project/main/missing --run automake-1.10 --foreign
cd . && /bin/sh /root/project/main/missing --run autoconf
/bin/sh ./config.status --recheck
running CONFIG_SHELL=/bin/sh /bin/sh ./configure --no-create --no-recursion
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
/bin/sh ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
cd . && /bin/sh /root/project/main/missing --run autoheader
rm -f stamp-h1
touch config.h.in
make all-am
make[1]: Entering directory `/root/project/main'
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc -g -O2 -o main main.o
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make[1]: Leaving directory `/root/project/main'
[root@localhost main]# ls
aclocal.m4 autoscan.log config.h.in config.status configure.in depcomp main main.o Makefile.am Makefile.in stamp-h1
autom4te.cache config.h config.log configure configure.in~ install-sh main.c Makefile Makefile.am~ missing
[root@localhost main]#
------------------------------------------------
W十?/p>
q行生成的文?mainQ?/p>
------------------------------------------------
[root@localhost main]# ./main
Hello, Auto Makefile!
[root@localhost main]#
------------------------------------------------
我用的是ubuntu
以上是全文?但有一处要?用aclocal
全报有一个m4文g有错.扑ֈ报错的那一?把变量加个中括号可以了
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:mx=”library://ns.adobe.com/flex/halo”
xmlns:s=”library://ns.adobe.com/flex/spark”
1、xmlns:fx=”http://ns.adobe.com/mxml/2009″
fx命名I间下包含ActionScript元素和内建到MXML~译器里的标{?/p>
前者ActionScript元素是?Object、Number、Boolean以及Array对象{等Q在《Adobe Flex 4 Beta Language Reference》的包(Top LevelQ里可以查看完整的顶U元素。后者内建到MXML~译器里的标{?lt;fx:Script>?lt;fx:Declarations>?lt;fx:Style>{等Q在《Adobe Flex 4 Beta Language Reference》附录(AppendixesQ里?#8220;MXML Only Tags”可以查看完整的编译器元素。值得注意的是Q这个命名空间ƈ不包?Halo ?Spark lgQHalo是以前版本的lg库,而Spark是Flex 4新出的组件库Q。在Flash Builder安装目录下可以找?#8220;mxml-2009-manifest.xml”文gQ例如我的电脑是C:\Program Files\Adobe\Flash Builder Beta\sdks\4.0.0\frameworks\mxml-2009-manifest.xmlQ,q个xml文g描述了完整的 ActionScriptcR不q你可以注意刎ͼ它ƈ没有包含MXML~译器标{,那是因ؓq些标签是内建到MXML~译器?/p>
2、xmlns:mx=”library://ns.adobe.com/flex/halo”
mx命名I间包含着攑֜ mx.* 包里那些lgQFlex图表、Flex数据可视化组件等{。对Flex 3很熟悉的话,mx包里的组件你也不陌生了。在Flex 4 SDK的安装目录下可以扑ֈ“halo-manifest.xml”文gQ例如我的电脑是C:\Program Files\Adobe\Flash Builder Beta\sdks\4.0.0\frameworks\halo-manifest.xmlQ,q个XML文g列出了所有组件了?/p>
3、xmlns:s=”library://ns.adobe.com/flex/spark”
s命名I间可真是新鲜事了,spark.* 包里的组仉在这个命名空间里Q不只spark包,flashx.*包的text frameworkcM在这个命名空间里。这个命名空间包含不RPCc,例如 WebService、HTTPService和RemoteObjectlgQ这些组件同时也在mx命名I间下,也就是说Q创些组件时Q你不但可以使用“S:”前缀Q也可以使用“mx:”前缀。其实不只这些RPClgq两个命名I间Q像graphics、effect和statecM是共?s ?mx 命名I间的。在Flex 4 SDK安装目录下打开spark-manifest.xml文g来看看完整的sparklg吧?/p>
用了一q多FlexQ感触多多。偶有同行的朋友问我啥是FlexQ说实话Q一时半会儿我还真说不清楚。尤其是对于一个从未接触过Flex的朋友,惌由浅入深地只用嘴巴不用电脑给他讲明白Q这实难ؓ一个整天只跟机器打交道的程序员了。后来我想了一个办法,我说你知道开心农场吧Q那是拿Flex做的。这下子很多人有兴趣了,呵呵Q如果你也有兴趣Q请l箋往下看。失a未察之处Q欢q拍砖?/p>
一般来_一Ҏ术的产生都是Z解决业界的重大难题而出现的。那么说到Flex我们׃得不先说一下RIA。RIAq个概念其实早就出现了,我最初是07q在《程序员》杂志上关于Ajax技术的介绍时看到的。到?8q_伴随着|络视频的飞速发展,RIA应用已经搞得有声有色热火朝天了,其实译q来是个富客户端(Rich Internet ApplicationQ,相较于BS的瘦客户端,也可以称之ؓ胖客L。当然如果你已经被这些名词概늆得焦头烂额,误跛_D(黑好心提示Q本部分仅余四段。。。)?/p>
RIA单的_是CS+BS的开发部|模式。CS和BS大家都很熟悉QCS的全拼是Client/ServerQ它的优点在于借助局域网的信息安全和带宽优势Q充分利用客h器的q算能力从而降低服务器压力Q缺点就是安装部|更新麻烦,比如老板让我跑到一千公里外的客户那安装一千台机器的客LQ过几天我回来了Q老板说那Ҏ几台机器q行有问题,你去l护一下~Q过几个月,老板说你L那一千台机器全部升一遍,他们自己不会装。。。呵呵,q些痛苦我当然不曄历,我杜撰的?/p>
那么?998q_互联|风起云涌的时候,BSQBrowser/ServerQ逢时而生。BS充分利用互联|的优势Q解决了CS安装部v更新的一大难题。通过把业务逻辑处理攑֜服务器端Q然后解析ؓHTMLQ利用HTTP协议传输到客L览器上׃事大吉。看h很美Q其实干q就知道也很痛苦。哪儿痛呢,痛的当然是我们这些开发者。安装部|更新倒是省事儿了Q装个IEQ给个网址p让客L录了。但是,ZHTML+JavaScript的技术让人很崩溃。JavaScript我好久不用了Q在以前毕业实习的时候,感觉开发和调试都不方便Q而且q面临着不同览器不兼容的噩梦(据说现在上述问题随着Ajax的风行有所改善Q我不太了解Q。另外,BSq有一些潜在的~点。比如,客户端体验简单,不易开发丰富的效果来展C数据(q和当时的网l带宽也有关p)Q必联|才能运行,信息安全无法保障Q应用程序需要通过其他技术辅助才能操作客L资源Q服务器负蝲q高而客hq算能力未充分用等?/p>
l合来讲QBS仍然是一个不错的解决ҎQ它的Web应用E序和CS的桌面应用程序曾一度二分天下,各领风骚数十q。从解耦角度来看,CS以数据库的方式把数据从程序中分离QBS以浏览器面的方式把界面和逻辑再次分离Q然而第二次分离是不d的。表面上只是代码l构的分,从实质上看表现层仍然是逻辑层的附庸Q前台UI完全和后台实现技术绑死(把已有项目后CC#换成JAVA是不可能的。。。)Z解决q个问题QRIA出现了(Z搞定了一些其他问题,比如面异步hQ前台UI不够丰富{等Q,RIA基本实现了不依赖于特定后台技术,能与多种服务端搭配用?/p>
?002q_MacroMedia公司Q简UMMQ?5q被Adobe收购Q首先在Flash Player6中引入了RIA概念?004q_MM正式发布Flex1.0Q汗Q终于说到Flex了)Q随着Ajax的火爆,RIA开始受到广泛关注。RIA主要有两个方面的含义Q一是用L面的丰富卛_客户端,二是数据模型的智能,服务器已l变成了支持客户端正常运行的数据服务Qƈ提供了异步数据传输和脱机~存机制{复杂的数据处理能力。前面提刎ͼRIA本质上就是CS+BSQ它想集大成Q想搞ȝQ想l结CS和BS二分天下的局面。说显点就是,如果以前的CSE序现在能在|络上运行,q且保持了原来的功能和特征,那么q就是一个RIA。关于RIA的详l介lGOOGLE上一搜一大把Q在此就不l作详细展开。回到当下,RIA各种技术一番拼杀Q现在广Zh知的只剩下四个NB伙QAjax、Flex、SilverLight、JavaFx。在本文W二部分中,我将要介l一下FlexQ貌D度有点儿慢,多谢支持。。。)
Flex是咋回事之二 前世今生
先说一下Flash PlayerQ简UFPQ。经怸|的朋友一定遇到过Flash Player版本升的提C吧Q这东西其实是览器插Ӟ据说已经有了98%的安装普及率Q没办法Q谁让咱们这么爱看视频呢QFP具体介绍误http://baike.baidu.com/view/1585492.htmQ。Flex生成的页面主要是通过Html包装一下生成的swf文gQ和Flash生成的swf一P它也靠FP才能完美q行Q这有点cMJVM虚拟机和.NET FRAMEWORKQFP里内嵌了AVM虚拟机)。FP又分调试版和产品版,M来讲Q咱们只用FP提供的APIQ以及及时关注最新版本的功能Q其余不会过多接触(我对FP10关于3D斚w的支持很感兴,不过貌似其支持效果不太理惻I?/p>
再说一下Flash的历双Ӏ在1996q?Y件公司FutureWave SoftwareZlNetscape开发一个全新的|页览插gQ创Z名ؓFuture Splash Animator的动态小E序Q该产品ZJavaQ是׃个称为SmartSketch的品演化而来Q这是Flash的老祖了。具有讽刺意味的是,q家FutureWave的公司本来是打算把这Ҏ术卖lAdobe的,但在那个时候AdobeҎ不睬它。而MacromediaQ简UMMQ却很有兴趣Q就q样?996q?1?MM在拥有了FutureWaveq家公司的技术后Q把FutureSplash重新命名为Flash Player 1.0。在随后的许多年_Flash被打包ؓStudio套g的一部分Qƈ与其他Studio产品Q如Dreamweaver和FireworksQ一起发布,世hU网三剑客。。。三剑客横行无敌Q到?5q??8日这天,ADOBE实在看不下去了,阔Ԓ出手Q又?4亿美元天h购MM。。。ADOBE大叔估计很后悔当q没收购Future SplashQ搞到现在,被MMl做大了QFlash具体历史介绍参见http://flash.9ria.com/viewthread.php?tid=13194?a >http://space.flash8.net/space/?625743/viewspace-350122Q?/p>
如同今年4月Oracle收购Sun一PMM嫁入ADOBE豪门Q在当时的业界也是一片哗然炸雗许多MM的忠实粉丝觉得,那三剑客是被ADOBE大叔招安了啊Q依据其收购产品的一贯猥琐恶行,q几位剑侠估计很快就会被不声不响地给整掉了(当时Flexq是襁褓Q大安没注意到。。。)Fireworks是PhotoShop的老对头了Q肯定是斩立冻IDreamweaver要不是改装变nQ要不就是各U理q接缓死;Flash日子会好q些Q但其一贯的MM风格是否能gl也很难保证?/p>
然而ADOBEq次Z意料的善良,三剑客无一遗弃Q相反还忍痛把自己推行多q的SVGȝQ个Z很喜ƢSVGQ无奈和FLASH冲突Q出于商业策略,q孩子被牺牲了)。在最新的CS4QCreative Suite 4Q品系列中Q三剑客依然zd四射C其他成员工具们和谐奋q。那么事隔收购事件四q多之后Q我们已l渐渐接受了MM产品前面加上的ADOBE标签。可以说QADOBE充分吸纳整合了MM的精和风格Q无论是FPq是三剑客,ADOBE一直都在努力地做得更好更和谐。(本h现在已经是ADOBE FANS了,哈哈Q不q还是挺怀念Flash MX2004 和Dreamweaver2004那个时代的,管当时也没闪出啥东西来。。。)
说了q么多关于Flash的事情,其实是因为Flash比Flex更出名,ADOBE也察觉到q一点,所以在预备推出FLEX4Ӟ又将其更名ؓFlashQ只是SDK仍然沿用FLEX的名受FLEX和FLASHq没有本质区别,它们最l都是{为ActionScript源文Ӟ然后被编译ؓ二进制的swf文gQ就和JAVA文g被编译成class一PQ再交由FPQFP像JVM虚拟ZP来执行。不同的是,FLASH更偏向于设计人员Q它有时间u和的概念,能更好地实现动画、特效、短片等工效果。Flex是面向开发者的Q隐藏了旉轴的概念Q只有两帧)Q更专注于解决企业应用的表现层方案,提供了大量的通用lg用于构徏前端面、通过数据服务技术能更好的分ȝ面和逻辑业务层?/p>
?4q?月MM手中的Flex1.0Q到05q?0月ADOBE手中的Flex2.0Q再?7q?月伴随着强大的面向对象语aActionScript3出现的Flex3.0,再到明年初发布的强力Flex4.0。借着RIA的春风,Flex在不断走向成熟的同时Q也被更多的业界开发者和企业用户所x接受。如果看到这里你很感兴趣Q推荐在GOOGLE上搜索一把,现在不是08q了Q网上已l涌现出大量的简易教E供我们参考学习。当然如果你有些闲钱Q或是想pȝ地学习一下,也可以买几本书。(有时间我会整理些|站博客和书c推荐的Q?/p>
在本文第三部分中Q我结合项目经验谈一下Flex的优~点和用心得。没用过Flex的可能无法共鸣吧Q那q接蟩q不看了Q呵?/p>
Flex是咋回事之三 谁用谁知?/strong>
一Ҏ术,从概忉|出到技术研发到商业发布Q再到实际应用,最l将产品呈现在用户面前,q是一个O长而复杂的q程。在q当中,很多有创意有生命力的技术因为各U原因小遗憑֜不幸夭折了。Flex能走C天确实不易,下面让我们从不同的角度来看一下它是如何过x,赢得众多青睐的?/p>
技术角度:
Q1Q具备了RIA时代富客L的优点(C/S+B/SQ?/p>
Q2Q支持多U服务器语言QJAVA?NET、PHPQ及L框架QSpring、HibernateQ?/p>
Q3Q与Javal合后相当强大,能充分利用Java的资源背?/p>
Q4Q拥有丰富的lg和第三方lgQ对企业U的数据汇d业务程展现力较强悍
Q5Q借助开源的力量Q拥有众多民间组l和牛h支持
Q6QAdobe公司Q还有MM多年U篏Q的强大背景
Q7Q源于Flash的天生丽质,L使用多媒体资源,动态交互性强
Q8Q借助FlashPlayer的安装普及度Q轻村֮现跨览器跨q_
Q9Q良好的架构设计和制作精良的文档CZQ明qFLEXQ同步推Z文版Q?/p>
Q1Q)借助于插件丰富的Eclipse开发^台ƈ拥有独立的IDE
Q1Q)框架设计重用性高Q有利于模块化设?/p>
Q1Q)q几q发展态势良好Q获得了q泛认可Q品和技术也发成熟
开发者角度:
Q1Q开源,透明Q国人没有不喜欢开源的Q哈哈)
Q2Q基于Eclipse开发^収ͼ易上手,且插件丰富(巨h的肩膀啊~Q?/p>
Q3Q基于Eclipseq_Q开发调试方?FB4中的条g断点Q?/p>
Q4QActionScript语言与Java的融合度和相似度较高Q易学易?/p>
Q5QMXML标签与XML怼Q逻辑清晰可读性强
Q6Q架构设计良好,耦合度低Q有利于lg重用
Q7Q无需针对不同览器编写代码,摆脱~写和调试的噩梦Q针对JS说的Q?/p>
Q8Q类似VB的可视化拖拽lgQ快速创建界?/p>
Q9Q方便定制及使用W三方的皮肤和样式,无需工也有好效?/p>
Q1Q)支持多媒体资源,L开发动态交互性强的界?/p>
Q1Q)众多的RPClg保障对后台数据访问的安全性和效率
Q1Q)文档CZ丰富Q通过|络可以获取大量的学习资?/p>
Q1Q)q两q发展态势良好Q前景光?/p>
企业角度Q?/p>
Q1Q开源,免费Q其实很多时候还是直接用破解的。。。)
Q2Q具备了RIA时代富客L的优点(C/S+B/SQ(潮流啊~Q)
Q3Q项目和lg的重用性高Q易于资源积累和快速构?/p>
Q4QFlex提供了与其他语言的结合,能广泛利用已有的资源
Q5Q界面华丽,客户认可度高
Q6Q学习曲U一般,培训成本?/p>
用户角度Q?/p>
Q1Q部|和更新方便
Q2Q界面漂亮,交互性强
Q3Q安?/p>
说了q么多好话,再来l合说一下缺炏V鉴于我着q于Flex的光环效应,没有看到的缺点还误位多多提出?/p>
~点Q?/p>
Q1Q不擅长处理复杂的业务流E,主要q是适合展现QFlex不是万能的)
Q2Q承了Flash的诸多优点,却唯独丢掉了Flash的小巧轻盈(减肥是永恒的话题Q?/p>
Q3Q目前尚没有比较好的减肥{略Q带宽较好时q不是问题(不是一般的卡。。。)
Q4Q对服务器和客户端的g讑֤都有一定要求(CPU和内存占用很生猛。。。)
Q5Q运行期内存泄露状况严重Q尽可以通过一定手D|善(q个很崩溃)
Q6Q对一些较专业的领域涉及较,需要第三方lg支持Q比如地质方面的Q?/p>
Q7QAdobe公司对中国分部的支持不够Q感觉宣讲和文档都做得不够)
Q8Q搜索引擎对swf文g的支持不够(Adobe一直在努力Q?/p>
Q9Q与以往览习惯不同Q比如右键被屏蔽Q图片无法保存(可以改善Q?/p>
鉴于Flex生成的swf文g太肥是其主要~点Q加载慢Q运行慢Q内存占用多Q,我就主要从减肥和优化的角度来说一下用心得?/p>
使用心得Q?/p>
Q1QFlex只是前台展现Q需要搭配强大的后台Q注意前后台的均衡和优化Q?/p>
Q2Q考虑异步加蝲Q比如分步加载外部资源)
Q3Q界面推荐用相对布局Q合理组合,避免多余嵌套
Q4Q界面加载图片推荐用外部加载方式,可能多使用矢量囑Ş
Q5Q规范CSS样式表,其注意使用的外部字体大?/p>
Q6Q用额外的皮肤和特效时需要综合考虑生成的文件大和执行效率
Q7Q适当地考虑延时加蝲{略Q主界面只显C必要的内容
Q8Q规范编码,提高执行效率Q避免内存泄?/p>
Q9Q用RSL和Module和其他有效方式努力减?/p>
Q1Q)可能重写一些承底层类的组Ӟ执行效率更好
Q1Q)慎重使用重量U组Ӟ比如DataGridQAdvancedDataGridQ?/p>
原文来自Q雨枫技术教E网 http://www.fengfly.com
做网l模块的时候经怼遇到有关|址的处?一般大致的情Ş?U?
1.得到的是域名,?www.3322.org
2.得到的是实际的IP地址,?61.160.235.203
3.得到的是l过inet_addr处理q的IP,为unsigned long(DWORD)
一.那么如果是给出点分制的IP要{为DWORD型是如何转化?q个其实最?有专门的函数专门处理此事
unsigned long dwIP = inet_addr("222.212.12.77"); printf("IP(%s)->DWORD(%lu)\n"); //output IP(222.212.12.77)->DWORD(1292686558)
?W一U情늚逆{?/p>
#include <stdio.h> #include <stdlib.h> #include <sys/select.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> int main(int argc, char *argv[]) { struct in_addr net; char tmp[16] = {0}; if(argc != 3) { printf("You MUST enter 3 varibal.No.1:func name No.2:case.No.3:ip(string or DWORD)\n"); return 0; } if(strcmp("1", argv[1]) == 0) { char* ip_string; ip_string = argv[2]; unsigned long dword = inet_addr(ip_string); printf("IP(%s)-->DWORD(%lu)\n", ip_string, dword); } else if(strcmp("2", argv[1]) == 0) { net.s_addr = (unsigned long)atol(argv[2]); strcpy(tmp, inet_ntoa(net)); printf("DWORD(%s)-->IP(%s)\n",argv[2], tmp); } return 0; }
q里l出一个点分制IP和DWORD怺转化的程?/pre>?如果l出的是域名而想得到点分制的IP?q里l出一个接?支持输入的类型是点分制和域名2中类?q回的是DWORD型的IP有一点要声明的是gethostbynameq个函数必须在网l连通的情况下才能正完成域名的解析,你想,q个|都不?它怎么解析?#include <stdio.h> #include <stdlib.h> #include <sys/select.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> #define DWORD unsigned long DWORD platform_domain2ip(const char *szDomain, char *szDotNumIP) { char szAddr[32] = {0}; struct hostent *pHost; printf("input domain name(%s)\n", szDomain); if((pHost = gethostbyname(szDomain)) == NULL) { printf("can not parse domain\n"); return -1; } printf("HostName :%s\n",pHost->h_name); strcpy(szAddr, inet_ntoa(*((struct in_addr *)pHost->h_addr))); printf("IP Address :%s\n", szAddr); strcpy(szDotNumIP, szAddr); return inet_addr(szAddr); } int main(int argc, char *argv[]) { DWORD dwip; char *ip = malloc(32); //dwip = platform_domain2ip("www.3322.org", ip); dwip = platform_domain2ip("61.160.235.203", ip); printf("ip 1 (%s) 2 dw(%lu)\n", ip, dwip); return 0; }//可以main的注册分别打开来判断下l果是否正确,q里l出q行的结?有图有真?/pre>~译的命令再说下?怕有Z知道gcc gethost.c –Wall –o gethost//在linux?/pre>arm-hismall-linux-gcc gethost.c –Wall –o gethost//嵌入式环境下此接口已l在我的工程中?在^台IP的解析和3322的解析中得到了应?所以是E_可行?q?中IP的{化都了解了的?那么|络~程不就扫除了一个大矛_?呵呵,大家功能q步|上比较行的gethostbyname的例子如?受到了启?/pre>#include <stdio.h> #include <stdlib.h> #include <sys/select.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> int main(int argc, char **argv) { char *ptr,**pptr; struct hostent *hptr; char str[32]; /* 取得命o后第一个参敎ͼ卌解析的域名或L?*/ ptr = argv[1]; /* 调用gethostbyname()。调用结果都存在hptr?*/ if((hptr = gethostbyname(ptr)) == NULL) { printf("gethostbyname error for host:%s\n", ptr); return 1; /* 如果调用gethostbyname发生错误Q返? */ } printf("official hostname:%s\n",hptr->h_name); /* L可能有多个别名,所有别名分别打出来 */ for(pptr = hptr->h_aliases; *pptr != NULL; pptr++) printf(" alias:%s\n",*pptr); /* Ҏ地址cdQ将地址打出?*/ switch(hptr->h_addrtype) { case AF_INET: case AF_INET6: pptr=hptr->h_addr_list; /* 刚才得到的所有地址都打出来。其中调用了inet_ntop()函数*/ for(;*pptr!=NULL;pptr++) printf(" address:%s\n", inet_ntop(hptr->h_addrtype,*pptr, str, sizeof(str))); break; default: printf("unknown address type\n"); break; } return 0; }
学习Unix常用的命?ls,ll,cd,su,mkdir,cp,mv,rm -rf,Vim操作Q安装CTagsQTList插g?/p>
学习MakeFile文g?/p>
特别注意当前E序需要哪?h文gQ哪些lib文g。需要编译成什么文件。注意编译的路径好了?/p>
Svn操作。上传,下蝲Q更新?/p>
主要是svn coQ下?/p>
svn add d文g或者文件夹
|
svn info 查看信息
svn ci 提交修改
svn up 下蝲信息?/p>
SecureCRTQputty?/p>
lcd 变更本地路径。put 上传Qget 下蝲?/p>
shell脚本QsedQpython
目前我公司开发的Nexus Engine的底层对象序列化使用了TinyXML来读写XML文g。TinyXML有两个不爽的地方Q一是它的接口用FILE*Q另外一个是它对 wchar_t不能很好的支持。前阵子看Boost库的更新中多了一个PropertyTreeQ他在处理XML时用C另外一个小的库 –RapidXML。既焉接的是Boost库的一部分Q所以是值得一试的。于是找到其官方|站Q?a title=http://rapidxml.sourceforge.net/ target=_blank>http://rapidxml.sourceforge.net/Q研I了一番。一看之下,甚是满意Q也推荐l大家看看!
首先是速度Q据它自己宣U比TinyXML?0?0倍,比Xerces DOM?0?00倍!详细的测试比较请见其用户手册Q?a title=http://rapidxml.sourceforge.net/manual.html target=_blank>http://rapidxml.sourceforge.net/manual.htmlQ的“4. Performance ”一节?/p>
其次它的设计非常的简z,只依赖于标准库中的几个基本的cR它的输入输出都是字W串Q这样很好,一个库应该关注自己核心的内容Q做量的事情。它的API其实和TinyXML倒是有几分相|用过TinyXML的h应该很容易上手:
TinyXML主要接口c? RapidXML的主要接口类
TinyXML主要接口c?/strong> | RapidXML的主要接口类 |
class TiXmlDocument | template<class Ch = char> class xml_document |
class TiXmlNode | template<class Ch = char> class xml_node |
class TiXmlAttribute | template<class Ch = char> class xml_attribute |
下面q是看一个具体的例子来体验一下,下面是TinyXML官方教程中创建XML文档的一D代码:
void build_simple_doc( )
{
// Make xml: <?xml ..><Hello>World</Hello>
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( “1.0″, “”, “” );
TiXmlElement * element = new TiXmlElement( “Hello” );
TiXmlText * text = new TiXmlText( “World” );
element->LinkEndChild( text );
doc.LinkEndChild( decl );
doc.LinkEndChild( element );
doc.SaveFile( “madeByHand.xml” );
}
下面是用RapidXML实现cM功能的代码:
void build_simple_doc_by_rapidxml()
{
xml_document<> doc;
xml_node<>* decl = doc.allocate_node(node_declaration);
xml_attribute<>* decl_ver =
doc.allocate_attribute(“version”, “1.0″);
decl->append_attribute(decl_ver);
doc.append_node(decl);xml_node<>* node =
doc.allocate_node(node_element, “Hello”, “World”);
doc.append_node(node);string text;
rapidxml::print(std::back_inserter(text), doc, 0);// write text to file by yourself
}
下面是用RapidXML分析XML的样例代码:
void parse_doc_by_rapidxml(char* xml_doc)
{
xml_document<> doc; // character type defaults to char
doc.parse<0>(xml_doc); // 0 means default parse flagsxml_node<> *node = doc.first_node(“Hello”);
string node_val = node->value();
}
前两天有朋友问,我的SlimXml有没有和RapidXmlҎq效率?我是W一ơ听说这个库Q更不用说对比效率了Q于是上他们|站看了下?/p>
好家伙,居然L?a target=_blank>TinyXml?0?0倍,而且?a >Boost.PropertyTree的默认xml解析器?/p>
于是有点好奇Q因Z前也没有特别兛_qSlimXml的效率?/p>
于是分别下蝲了TinyXml-2.6.1和RapidXml-1.13Q迅速用vc8建立了两个测试工E,在系l中?#8221;*.xml”Q找C一个比较合适的试文g。它_大(1.5MQ,utf-8~码q且包含?英文Q有一定层ơ深度,大约3.3万行。测试文件可?a target=_blank>从这里下?/span>
试对象是三个库从内存字W串解析xml的函敎ͼq样能排除从盘上读文gq种不稳定因素的q扰Q而且RapidXml貌似只支持从内存里解?/p>
要说明的是,RapidXml的这个parse是一个模板函敎ͼ必须l一个flag的参敎ͼ我测试的时候给的是默认?
试l果Q解析这?.3万行Q?.5M大小的xmlQ三个库分别׃
l论是,RapidXml果然很强悍,居然比我的SlimXml?倍多。但是ƈ没有如作者所说比TinyXml?0~60倍,只有不到15倍。据说对比用的是一个约50k大小的xml文gQ可惜ƈ没有提供下蝲Q不然可以验证一下?/p>
比较ƣ慰的是Q在我ƈ没有很关注效率的情况下,SlimXml仍然比TinyXml?.5倍。SlimXml走的是简单小巧\U,源代码只?2kQ而TinyXml和RapidXml的源码分别是147k?41kQ有q样的效率可以满意了。在我有很多I闲以前Q估计我也不会再M化它Q因个库主要q是针对几十上百行的文Ӟ解析特别大的xml不在我考虑的范围之内?/p>
以下是RapidXml提供的常见xml库效率对照表Q其中还很牛d提供了和strlen()函数的效率对?/p>
我估计RapidXml速度快的主要原因是对memory pool的用,毕竟在解析过E中需要创建大量的stringQ可以想象用memory pool和直接走默认的new很容易生超q一个数量的效率差异?/p>
控制语句 | 格式 | CZ |
If | if 条g then ... elseif 条g then ... else ... end |
if 1+1=2 then print("true")
elseif 1+2~=3 then print("true") else print("false") end |
While | while 条g do ... end |
while 1+1~=2 do print("true") end
|
Repeat | repeat ... until 条g |
repeat print("Hello") until 1+1~=2
|
For | for 变量=初? l点? 步进 do ... end |
for i = 1, 10, 2 do print(i) end
|
For | for 变量1, 变量2, ... 变量n in 表或枚D函数 do ... end |
for a,b in mylist do print(a, b) end
|
比较W号 | < | > | <= | >= | == | ~= |
含义 | 于 | 大于 | 于或等?/td> | 大于或等?/td> | 相等 | 不相{?/td> |
or and < > <= >= ~= == .. (字符串连? + - * / % not #(lua5.1 取长度运?/span>) - (一元运? ^ |
and | break | do | else | elseif | |
end | false | for | function | if | |
in | local | nil | not | or | |
repeat | return | then | true | until | while |
Nil | I|所有没有用过的变量,都是nil。nil既是|又是cd?/td> |
Boolean | 布尔|只有两个有效|true和false |
Number | 数|在Lua里,数值相当于C语言的double |
String | 字符Ԍ如果你愿意的话,字符串是可以包含"\0"字符的(q和C语言L?\0"l尾是不一LQ?/td> |
Table | 关系表类型,q个cd功能比较强大Q请参考后面的内容?/td> |
Function | 函数cdQ不要怀疑,函数也是一U类型,也就是说Q所有的函数Q它本n是一个变量?/td> |
Userdata | 嗯,q个cd专门用来和Lua的宿L交道的。宿主通常是用C和C++来编写的Q在q种情况下,Userdata可以是宿ȝL数据cdQ常用的有Struct和指针?/td> |
Thread | U程cdQ在Lua中没有真正的U程。Lua中可以将一个函数分成几部䆾q行?/span>如果感兴的话,可以ȝ看Lua的文档?br>现在回过头来看看Q倒觉得不是线E类型。反而象是用来做遍历的,象是Iterator函数?br>如: function range(n)
可惜的是要l运行,需要coroutine.resume函数Q有炚w肋。请指教?br>local i = 0 while(i < n) do coroutine.yield( i ) i = i + 1 end end |
首席执行官【CEO?/strong>
国人在20世纪60q代q行公司ȝl构攚w创新时的产物、它的出现在某种意义上代表着原来董事会手中一些决{权q渡到经营层手中、CEO概念最早出现在一些网l企业。在那里CEO往往是自的、也很少有hȝI这一U谓对企业到底意味着什么。但是,?#8220;CEO”在中国叫得越来越响时候、高层h员称谓改变不是一件小事、设立CEO职位不仅仅是Ҏ追赶。事实上QCEO做的事情重点在于“执行”。大多数中国公司往往CEO做的事情恰恰不是“执行”Q更像是“董事?#8221;?/p>
首席财政官或财务ȝ【CFO?/strong>
C公司中最重要、最有h值顶管理职位之一、掌握着企业经pȝ(财务信息)和血液系l?现金资源)灵魂人物。做一名成功CFO需要具备丰富金融理论知识和实务l验。公司理财与金融市场交互、项目估仗风险管理、品研发、战略规划、企业核心竞争力识别与徏立及z悉信息技术及电子商务对企业冲ȝ都是CFO职责范围内事。大型公司运作中CFO是穿插在金融市场操作和公司内部胦务管理之间角艌Ӏ担当CFO人才大多是拥有多q在金融市场驰骋l验的h。在国优秀的CFO常常在华街做过成功基金l理人?/p>
首席营运官【COO?/strong>
负责公司日常营运、辅助CEO工作。一般来讲COO负责公司职能理l织体系、ƈ代表CEO处理企业日常职能事务。如公司未设有总裁职务则COOq要承担整体业务理职能、主企业营销与综合业务拓展、负责徏立公司整个销售策略与政策、组l生产经营、协助CEO制定公司业务发展计划、对公司l营l效q行考核。也有把q营ȝU呼为COO的?/p>
首席市场官【CMO?/strong>
指市场ȝ
首席技术官【CTO?/strong>
技术ȝ
销售ȝ【CSO?/strong>
渠道销售ȝ
公关ȝ【CPO?/strong>
政府事务、媒体、重要公怸人物公共关系Q主要是搞定人?/p>
首席信息官【CIO?/strong>
大多数公司把q个职位变成了盯人盯,有点象明朝时候的“东厂”Q所以说中国是个很神奇的国家?/p>
Zȝ 【CHO?/p>
首席品牌官【CBO?/p>
首席文化官【CCO?/p>
首席知识官【CKO?/p>
首席谈判官【CNO?/p>
质量ȝ【CQO?/p>
评估ȝ【CVO?/p>
专门负责解答媒体、债权人和用户{有关问题询问?/p>
首席财务官助理之一、专门针对不同投资h制订相应BP?/p>
凡超qXXXX元以上支出必ȝCC0批准?/p>
负责公司域名注册、网站清盘时域名拍卖、域名法律纠UL相关问题?/p>
一般由国际CEO自由联盟随时更换、常讄期职能岗位、类D球教l?/p>
规划公司宏伟蓝图、一般是5q以后目标?/p>
调解投资者和l营者之间的冲突、确保公司内部矛盾不要泄霌Ӏ?/p>
查公司内部工作状c监督员工工作态度?/p>
解决内部劌U纷、包括员工对降薪、辞退补偿{所引v问题?/p>
最J忙的岗位之一、当中国电信|络q接中断时及时向员工通报?/p>
负责公司被控侉|时应诉以及各U合同文本审核。主要是灭h的打手?/p>
保持和媒体之间友好关[来源QGameRes.com]pMؓ公司随时发布新闻做准备,cM首席代表?/p>
向媒体披露公司被黑、裁员、被收购{重大新闅R一般由公司市场ȝ担QQ类似政府部门新da人,主要由司长部门领导担QQ公司声音的l一出口?/p>
负责公司内部员工Email、ICQ、OICQ{通信内容监控?/p>
负责注册用户数量、页面浏览、营业收入等指标~造?/p>
负责与裁员有关事务、直接向股东大会负责、包括董事长在内都不得干预工作?/p>
由已l退位公怸要创Zh担QQ在政府机关一般称研员或顾问?/p>
以战略联盟名义专门寻找有收购自己意向的公司?/p>
首席财务官另一重要助理?/p>
负责小事扩大化、通过炒作辑ֈ扩大公司名度目的QM用文人,比如l陈天桥Q史玉柱~故事,造神?/p>
Q中国特有)一般由学历不高且没有什么网l知识的q轻人担仅R?/p>
荣誉U号授予在公司工作满Xq员工(通常I缺Q?br>
开发ȝ【CDO?/p>
首席发言人【CAO?/strong>
首席商业计划官【CBO?/strong>
首席成本控制官【CCO?/strong>
首席域名官【CDO?/strong>
首席交换官【CEO?/strong>
首席斚w制订官【CGO?/strong>
首席协调官【CHO?/strong>
首席查官【CIO?/strong>
首席执法官【CJO?/strong>
|络q接专员【CKO?/strong>
首席律师【CLO?/strong>
首席媒体官【CMO?/strong>
首席新闻官【CNO?/strong>
首席隐私官【CPO?/strong>
数量指标~造专家【CQO?/strong>
首席裁员官【CRO?/strong>
首席战略官【CSO?/strong>
首席联盟官【CUO?/strong>
投资者关pRCVO?/strong>
首席|络写手【CWO?/strong>
形象代言人【CXO?/strong>
公司元老【CYO?/strong>
]]>
【用h?-注册用户?/font>不同目注册用户质量完全不同Q运营商l出不真实数据,那数据调查报告真实性呢Q根本没有明白用戯量的意义?br> 2、不同游戏每个^均在U是׃同数量用户造就的。一个好游戏可以大量_住玩家长时间舍不得下线?/p>
3、如果活跃用hơ上U^均在U?时Q那么需?个活跃用户增?个^均在U,如每ơ只让用L游戏5分钟p了,哪怕游戏非常好用户每天都上?分钟Q那么必L60/5*24=288个活跃用h能达?个^均在Uh数。要Ҏ情况判断推广z跃用户ҎQ还是增加游戏粘着更容易?/p>
2、很多愣头青听见大师宣传免费模式Q连免费模式数据都不清楚情况下凭感觉坚定认ؓ免费模式是潮、趋ѝ陈天桥不看产品数据Q道h费增加到可替代收Ҏ式,凭灵光一闪把每季度几亿时间点卡给扔了Q看到这两年来盛大从免费模式赚取过收费模式q是有瑕늚Q至在Uh数没有按盛大惌的大q度增加?/p>
2、注意以上部分数据,不要L怿q告商瞎吹,自己掌握的数据才是最真实不会ƺ骗你的?/p>
3、精掌握各U营销方式效果数据Q相信你不会随便p钱,拍着脑瓜子就上一些性h比不合适的q告?/p>
2、近两年很火Uv和蓝hc?br> 2、很多游戏h都分析《梦q西游》从技?span style="DISPLAY: none; FONT-SIZE: 0px">[来源QGameRes.com]层面完全没有优势产品Z黏着度那么高Q流q那么低。游戏内涉|最重要的因素,q关pd游戏生命周期。如果玩家把所有内定w全部玩到需?个月Q那?个月是|络游戏每个用户生命周期Q当玩家感觉没有可玩内容时他自然会离开。有的游戏是可以让玩家玩几年q有新内容,有的游戏虽然好但是生命周期短。现在有来多游戏学会利用循环dQ或随即生成d增加生命周期 3、有些数据可以告诉哪些收Ҏ玩家能够接受的(管有些收费内容Q玩家可能永q会骂,但每天都有大量用户在付费Q有些收费看h没h骂,实际上根本没有h使用Q都要通过q营数据分析Q?br> 5、数据很清楚告诉你游戏经体制是否稳固,游戏中不断增加的金钱奖励Q道具销售是否造成通货膨胀{更多的l节问题?/p>
【在Uh数】【最高在Uѝ?/font>某个旉能达到的最高在Uѝ?br>
【活跃h数?/font>hƺ骗性的数字Q必L“每日z跃用户”“每周z跃用户”“每月z跃用户”“每季z跃用户”“最q多天内活跃用?#8221;{。在q段旉内进入游戏的人?br>
【每个活跃用户^均在U时间?/font>上面说了z跃用户敎ͼ如果没有本数据上面那个也没有意义、每个用户都在线2分钟马上׃U,z跃用户价值是多少呢?能和上线十几个时在线玩家{gQ?/p>
【游戏^均在Uh数?/font>
1?4时内^均在Uh敎ͼ数据采样旉密集越_?/p>
【^均在UѝL册用戗活跃h数及最高在U比例?/font>
曄有专家说是xxxx?%Qxxxx?.7%{,他们可能针对某款能接触到的网游数据而来Q如果不知道数据是在什么条件下产生的,每款产品都不一栗比例随着不同市场、不同品、不同渠道、不同服务会D_数据和比例完全不一栗哪怕一模一样品都可能完全不一h据,别h注册100万用戯?万在U,不代表你宣传注册100万也?万。各斚wl节太多Q资本家很少全面看成功创业者所付出的努力?/p>
【Arpu值定义之争?/font>
1、有是每个消费用L每日p?br>2、有是每个活跃用L每月p?br>3、上市公司胦报数据定义:产品毛收?qAPA/arpuQ要么增加APA数量Q要么增加ARPU。对于运营商要根据多^均在U确定服务器、带宽、客h务、需要多推q成本才能篏计^均在U等q营成本?br>
【收Ҏ式固定倹{?/font>
很好:每小?毛(或点卡定P*24时*30?288?月,一Ƅ万在U收费网游大致收入是1000000*288Q每?.88亿毛收入Q有很多数字,如免费用期用户比例D真实值减、各U因素导致免Ҏ戏用h例导致真实收入减、用戯买点卡很多h没用完导致真实收入增多,渠道压了货最后没有退D收入增多{)?/p>
【免费制动态arpu倹{?/font>
1、大多数|游都在学习免费模式Q利用收贚wL盈利Qarpu值大关pd生存的重要指标?/p>
【收费制?/font>
推广1个收费制游戏在线用户q比推广N个免Ҏ戏在U用h加困难,免费模式arpu值大于收Ҏ式时Q自然免Ҏ式要比收Ҏ式更好?br>
【推q成本?/font>
1、打花多少钱宣传推q品?br>2、除了资金还要考虑人力成本和时间成本?br>3、仔l计每个在U用hq成本,花多钱才能增加1个^均在Uѝ?br>4、大部分情况?个^均在Uarpug?个^均在U推q成本。如能找到廉hq方式增加在U,费用低于用户arpu|别犹豫赶紧推q吧?br>
【推q效果?/font>
1、作为市Zh员是掌握每种营销方式效果数据。有多少看到q告AQ有多少目标用户看到q告、引起多目标用戯住、让多少目标用户感兴、多用户尝试、剩下是产品本n和客h务的事。对个市场来说撒谎不是缺炏V无法让更多用户来尝试品才是失败?/p>
【市场潜力分U?/font>
不要定义一个遥不可及的市场目标Q例如全世界有多hQ每个h都需要住房,而你是个有房Cx的年MhQ你告诉别h你的市场目标是多亿亿全球用L房。这L标是没有意义的。可执行的目标是很重要的Q只要是可执行哪怕在旁h眼里看v来很狂妄Q也没有什么不可以?/p>
【运营网l游戏一定要知道分?/font>
1. 可以直接推广到的那些人?手把手,或者通过你的个h媒体Q言传n教)
2. 能在你所拥有预算内控制哪些媒体,做哪些事情,有多用户会因ؓ怎样宣传内容而尝?br>3. q有哪些资源Q哪些朋友支持,帮助Q在你所拥的预算内能帮你打开哪些市场?br>4. 人才Q能否找到比你更优秀的h才、专家帮助你宣传、推q扩大市?/p>
【用L分举例?/font>
1、非常关注你的品网游用h可能成ؓ你的用户
2、宣传推qƈ引v他们注意的网l游戏用?br>3、到处寻找新游戏的网l游戏用?br>4、同cȝl游戏的用户
5、异cȝl游戏的用户
【所有h?/font>以上分不一定准,不一定适合你,对于你很可能每需要投入成本不一P没有史玉׃个亿׃要开始把目标用户定义为所有h而去打全国广告,否则会发现投入成本一定收不回来?/p>
【目标市场定义?/font>
1、每个h都想产品占领最大最多市场,由各斚w条g有限必须按对市场分Q分析目前阶D能覆盖目标市场?/p>
3、准定位市场、细分市场目的是降低市场推广成本Q增加推q有效程度。如果有_的推q成本,你自然可以多做泛媒体Q广大增加知名度Q宣传面?/p>
【流q?/font>很容易被遗忘却异帔R要,军_游戏生死重要数据Q市场推q好不容易拉的玩家留不留得住?br>【初期流q?/font>试用户转变为成熟活跃用P所需耗费的时?br>【自然流q?/font>成熟z跃用户自然失率,产品好坏Q内涵丰富最大程度决定着自然失率高低?/p>
1、品本w有很多问题会带来非常高自然流qQ品的画面、操作、各斚wl节都是关系C品品质直接开发因素?/p>
3、网游开发者不要冲着单新概念做游戏,不是做噱_做有内涵的好游戏Q充分利用你的技术团队实现效果,而不是盲目专门搞效果搞噱_让用户乐意留在游戏里面?/p>
【客h务?/font>很重要作用是减少失率,没有客户服务游戏不可避免扩大流qQ流q大神仙也没得救。盛大第一W收入用来徏立客h务中心ؓ了什么?商业数据上说是降低失率?/p>
【线上活动?/font>通过zdQ可能是CQ务、策划活动、客服执行活动)临时性增加拉高在U,减缓或阻止短旉内玩家流失?/p>
【用戯然增长率?/font>在推q下增加1个^均在U成本低于【用户arpu倹{?【^均每个用L命周期】。可以不断持l增加用h况下、新q入玩家大于产品失率就q入滚雪球效应了。大多数产品一停止大规模推q成本投入流q都远大于增长率。很多项目在初期炒作后很快用h量陆l流失,最后不得不倒闭的原因?/p>
【收入潜力倹{?/font>和arpu值矛盄|arpuD低证明潜力越大,arpuD高反而说明相同用h量下收入增长潜力。有些公司(q没扑ֈ盈利模式却有较多用户的网站或游戏Q把q个作ؓ他们的未来卖炏V?/p>
【更多细节数据?/font>做好游戏不仅仅看l果型数据,更多对于开发策划要看过E走向型数据?/p>
【例如?/font>
1、有些数据可以告诉你在推q过E中哪个环节失用户最多?br>
2、有些数据可以告诉你、玩家喜Ƣ哪些系l,讨厌什么。无论喜p是讨厌都比不q【态度p|】漠不关心、死鸭子嘴硬。玩家对_ֿ{划的内Ҏ不关心,q是最p|的策划?/p>
4、有些数据可以很清楚告诉你用户在刷钱、在作弊、在利用漏洞、在用外挂、修改封包。如果有自动化数据分析技术几乎可以发C多玩家作弊。注意只是发玎ͼ能否解决q取决于高层重视态度及技术h员能力和速度Q要知道而这些问题几乎导致了大量游戏M?/p>
全部?DMARK06默认分L率得分计?游戏内实际C计算在内(因ؓNVIDIA和ATIҎ戏优化造成得分不公?排名120后的昑֍因时间过长无法测?只按历年来网上评分排?(所有排名显卡均为官方公杉K率测?.
001 NVIDIA GTX295
002 ATI HD4870X2
003 NVIDIA GTX285
004 ATI HD4850X2
005 NVIDIA GTX280
006 ATI HD4870
007 NVIDIA GTX260
008 ATI HD3870X2
009 ATI HD4850
010 NVIDIA 9800GTX+=NVIDIA GTX250
011 NVIDIA 8800Ultra
012 NVIDIA 8800GTX
013 NVIDIA 9800GTX
014 ATI HD4830
015 NVIDIA 8800GT=NVIDIA 9800GT
016 NVIDIA 8800GTS
017 NVIDIA 8800GS 768M=NVIDIA 9600GSO 768M
018 NVIDIA 9600GT 512
019 NVIDIA 7950GX2
020 ATI HD2900XT
021 ATI HD3870
022 NVIDIA 8800GS 384M=NVIDIA 9600gso 384M
023 ATI X1950XTX
024 NVIDIA 7900GTX
025 ATI HD3850
026 ATI HD4670
027 9600GSO 512M
028 NVIDIA 9600GT 256
029 ATI X1900XTX
030 ATI X1950XT
031 NVIDIA 7950GT
032 ATI 1900XT
033 ATI HD3690
034 NVIDIA 8600GTS
035 NVIDIA 7900GT
036 ATI X1800XT
037 ATI X1950Pro
038 NVIDIA 7800GTX
039 NVIDIA 7900GS
040 ATI X1950GT
041 ATI X1900GT
042 ATI X1800XL
043 NVIDIA 7800GT
044 ATI X850XT/XTPE
045 ATI HD3670
046 ATI HD4650
047 NVIDIA 9500GT
048 NVIDIA 8600GT
049 ATI HD3650
050 ATI X1800GTO
051 ATI X800XT/XTPE
052 NVIDIA 7600GT
053 ATI HD2600XT
054 ATI X1650XT
055 NVIDIA 6800Ultra
056 NVIDIA 6800GT
057 NVIDIA 6800GS
058 ATI X800XL
059 ATI X850Pro
060 NVIDIA 6800
061 ATI X1650 Pro
062 ATI X800pro/GTO
063 ATI X1600XT
064 NVIDIA 7600GS
065 ATI X800SE
066 ATI X1300XT
067 NVIDIA 8500GT=NVIDIA 9400GT
068 ATI X1600Pro
069 NVIDIA 7300GT
070 NVIDIA 6800XT/LE
071 NVIDIA 6600GT
072 ATI X700Pro
073 ATI 9800XT
074 ATI 9800Pro
075 ATI 9700Pro
076 ATI 9800
077 S3 Chrome S27
078 ATI X700
079 NVIDIA 5950Ultra
080 ATI 9700
081 NVIDIA 5900Ultra
082 NVIDIA 5800Ultra
083 NVIDIA 5900
084 NVIDIA 5800
085 ATI X1300Pro
086 NVIDIA 8400GS
087 ATI HD2400Pro
088 NVIDIA 7300GS
089 NVIDIA 6600
090 NVIDIA 5900XT
091 ATI X1300
092 ATI X600XT
093 NVIDIA 7300LE
094 NVIDIA TI4800
095 NVIDIA TI4600
096 ATI 9600XT
097 NVIDIA TI4800SE
098 NVIDIA 5700Ultra
099 ATI 9500 256bit
100 9800SE 128bit
101 ATI X600
102 ATI X550
103 ATI 9600Pro
104 NVIDIA TI4400
105 ATI 9500Pro
106 NVIDIA 6600LE
107 ATI X1300SE
108 NVIDIA 5700
109 ATI 9600
110 NVIDIA 6200
111 NVIDIA TI4200
112 NVIDIA 5600
113 ATI 9550
114 NVIDIA 5600XT
115 ATI 9600SE
116 NVIDIA 5500
117 NVIDIA 7100GS
118 ATI X300
119 ATI 9550SE
120 NVIDIA 6200A
121 ATI 9200Pro
122 ATI 9000Pro
123 ATI 8500Pro
124 NVIDIA GeForce3 TI500
125 ATI 8500
126 ATI 8500LE
127 NVIDIA 5200Ultra
128 ATI 9200
129 ATI 9250
130 NVIDIA GeForce4 MX460
131 NVIDIA 5200
132 ATI 9000
133 ATI 9200SE
134 NVIDIA GeForce3 TI200
135 NVIDIA GeForce3
136 NVIDIA GeForce4 MX 440
137 ATI 7500
138 ATI 7200
139 NVIDIA GeForce2 Ultra
140 ATI 7000
141 NVIDIA GeForce2 GTS
142 NVIDIA GeForce4 MX 420
143 ATI Radeon
144 Voodoo5 5500
145 NVIDIA GeForce2 MX 400
146 NVIDIA GeForce256
147 NVIDIA GeForce2 MX
148 Voodoo4 4500
149 NVIDIA TNT2
150 ATI Rage128 Pro
151 Voodoo3
152 TNT
153 ATI Rage128
154 NVIDIA Riva128
155 ATI Rage3D Pro
156 Voodoo Banshee
157 Voodoo2
158 NVIDIA Riva
159 ATI Rage3D
160 Voodoo