tqsheng

go.....
随笔 - 366, 文章 - 18, 评论 - 101, 引用 - 0
数据加载中……

epoll两种机制的区别

7、epoll两种机制的区别

说明:本文来自翻译epoll man文档。

1、ETLT这两种事件分发机制的不同。我们假定一个环境:

   1. The file descriptor that represents the read side of a pipe ( RFD ) is added inside the epoll device.

   2. Pipe writer writes 2Kb of data on the write side of the pipe.

   3. A call to epoll_wait(2) is done that will return RFD as ready file descriptor.

   4. The pipe reader reads 1Kb of data from RFD.

   5. A call to epoll_wait(2) is done.

Edge Triggered 工作模式:

    如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起因为剩余的数据还存在于文件的输入缓冲区内而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候ET工作模式才会汇报事件Edge Triggered event distribution delivers events。因此在第5步的时候调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据the caller might end up waiting for some data that is already present inside the input buffer.。在上面的例子中会有一个事件产生在RFD句柄上,是因为在第2步执行了一个写操作然后事件将会在第3步被销毁consumed。因为第4步的读取操作没有读空文件输入缓冲区内的数据因此我们在第5步调用 epoll_wait(2)完成后might lock indefinitely。epoll工作在ET模式的时候必须使用非阻塞套接口以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。最好以下面的方式调用ET模式的epoll接口在后面会介绍避免可能的缺陷。

    i 基于非阻塞文件句柄

    ii 只有当read(2)或者write(2)返回EAGAIN时才需要挂起等待(意为此时,缓存区满或无数据)。

Level Triggered 工作模式

相反的以LT方式调用epoll接口的时候,它就相当于一个速度比较快的poll,and can be used wherever the latter is used since it shares the same semantics。因为即使使用ET模式的epoll在收到多个chunk的数据的时候仍然会产生多个事件Since even with the Edge Triggered epoll multiple events can be generated up on receival of multiple chunks of data。the caller has the option to specify the EPOLLONESHOT flag, to tell epoll to disable the associated file descriptor after the receival of an event with epoll_wait(2). When the EPOLLONESHOT flag is specified, it is caller responsibility to rearm(重新设置) the file descriptor using epoll_ctl(2) with EPOLL_CTL_MOD.

2、While the usage of epoll when employed(使用) like a Level Triggered interface does have the same semantics of poll(2), an Edge Triggered usage requires more clarification(澄清) to avoid stalls(拖延) in the application event loop.

In this example, listener is a non-blocking socket on which listen(2) has been called. The function do_use_fd() uses the new ready file descriptor until EAGAIN is returned by either read(2) or write(2). An event driven state machine(事件驱动状态机) application should, after having received EAGAIN, record its current state so that at the next call to do_use_fd() it will continue to read(2) or write(2) from where it stopped before.

示例代码

View Code 

struct epoll_event ev, *events;
for(;;) {
    nfds 
= epoll_wait(kdpfd, events, maxevents, -1);
    
for(n = 0; n < nfds; ++n) {
        
if(events[n].data.fd == listener) {
            client 
= accept(listener, (struct sockaddr *&local,
                            
&addrlen);
            
if(client < 0){
                perror(
"accept");
                
continue;
            }

            setnonblocking(client);
            ev.events 
= EPOLLIN | EPOLLET;
            ev.data.fd 
= client;
            
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0{
                fprintf(stderr, 
"epoll set insertion error: fd=%d0,
                        client);
                
return -1;
            }

        }

        
else
            do_use_fd(events[n].data.fd);
    }

}


When used as an Edge triggered interface, for performance reasons, it is possible to add the file descriptor inside the epoll interface ( EPOLL_CTL_ADD ) once by specifying ( EPOLLIN|EPOLLOUT ). This allows you to avoid continuously switching between EPOLLIN and EPOLLOUT calling epoll_ctl(2) with EPOLL_CTL_MOD.



水平触发(LT, Level Triggered),默认方式
支持阻塞/非阻塞socket。
内核通知某fd就绪,如果不对fd操作,内核会继续通知
边缘触发(Edge-Triggered)
只支持非阻塞socket
内核通知某fd就绪,如果不对fd操作,内核不再继续通知

posted @ 2012-06-26 14:14 tqsheng 阅读(145) | 评论 (0)编辑 收藏

epoll_create, epoll_ctl和epoll_wait 实例讲解,总结得不错

NAME
       epoll - I/O event notification facility

SYNOPSIS
       #include <sys/epoll.h>

DEscrīptION
       epoll is a variant of poll(2) that can be used either as Edge or Level
       Triggered interface and scales well to large numbers of watched fds.
       Three system calls are provided to set up and control an epoll set:
       epoll_create(2), epoll_ctl(2), epoll_wait(2).

       An epoll set is connected to a file descrīptor created by epoll_create(2).   Interest for certain file descrīptors is then registered via
       epoll_ctl(2). Finally, the actual wait is started by epoll_wait(2).

其实,一切的解释都是多余的,按照我目前的了解,EPOLL模型似乎只有一种格式,所以大家只要参考我下面的代码,就能够对EPOLL有所了解了,代码的解释都已经在注释中:

while (TRUE)
{
int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//等待EPOLL事件的发生,相当于监听,至于相关的端口,需要在初始化EPOLL的时候绑定。
if (nfds <= 0)
   continue;
m_bOnTimeChecking = FALSE;
G_CurTime = time(NULL);
for (int i=0; i<nfds; i++)
{
   try
   {
    if (m_events[i].data.fd == m_listen_http_fd)//如果新监测到一个HTTP用户连接到绑定的HTTP端口,建立新的连接。由于我们新采用了SOCKET连接,所以基本没用。
    {
     OnAcceptHttpEpoll ();
    }
    else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
    {
     OnAcceptSockEpoll ();
    }
    else if (m_events[i].events & EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
    {
     OnReadEpoll (i);
    }

    OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据。
   }
   catch (int)
   {
    PRINTF ("CATCH捕获错误\n");
    continue;
   }
}
m_bOnTimeChecking = TRUE;
OnTimer ();//进行一些定时的操作,主要就是删除一些断线用户等。
}

其实EPOLL的精华,按照我目前的理解,也就是上述的几段短短的代码,看来时代真的不同了,以前如何接受大量用户连接的问题,现在却被如此轻松的搞定,真是让人不得不感叹。

今天搞了一天的epoll,想做一个高并发的代理程序。刚开始真是郁闷,一直搞不通,网上也有几篇介绍epoll的文章。但都不深入,没有将一些注意的地方讲明。以至于走了很多弯路,现将自己的一些理解共享给大家,以少走弯路。

epoll用到的所有函数都是在头文件sys/epoll.h中声明,有什么地方不明白或函数忘记了可以去看一下。
epoll和select相比,最大不同在于:

1epoll返回时已经明确的知道哪个sokcet fd发生了事件,不用再一个个比对。这样就提高了效率。
2select的FD_SETSIZE是有限止的,而epoll是没有限止的只与系统资源有关。

1、epoll_create函数
函数声明:int epoll_create(int size)
该 函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。随你定好了。只要你有空间。可参见上面与select之不同2.

22、epoll_ctl函数
函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:
epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除

fd:关联的文件描述符;
event:指向epoll_event的指针;
如果调用成功返回0,不成功返回-1

用到的数据结构
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};


如:
struct epoll_event ev;
//设置与要处理的事件相关的文件描述符
ev.data.fd=listenfd;
//设置要处理的事件类型
ev.events=EPOLLIN|EPOLLET;
//注册epoll事件
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);


常用的事件类型:
EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:表示对应的文件描述符有事件发生;


3、epoll_wait函数
函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
该函数用于轮询I/O事件的发生;
参数:
epfd:由epoll_create 生成的epoll专用的文件描述符;
epoll_event:用于回传代处理事件的数组;
maxevents:每次能处理的事件数;
timeout:等待I/O事件发生的超时值(单位我也不太清楚);-1相当于阻塞,0相当于非阻塞。一般用-1即可
返回发生事件数。


用法如下:

/*build the epoll enent for recall */
struct epoll_event ev_read[20];
int nfds = 0; //return the events count
nfds=epoll_wait(epoll_fd,ev_read,20, -1);
for(i=0; i
{
if(ev_read[i].data.fd == sock)// the listener port hava data
......

epoll_wait运行的原理是
等侍注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中。
并 且将注册在epfd上的socket fd的事件类型给清空,所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设置socket fd的事件类型。这时不用EPOLL_CTL_ADD,因为socket fd并未清空,只是事件类型清空。这一步非常重要。
俺最开始就是没有加这个,白搞了一个上午。

4单个epoll并不能解决所有问题,特别是你的每个操作都比较费时的时候,因为epoll是串行处理的。
所以你还是有必要建立线程池来发挥更大的效能。

//////////////////////////////////////////////////////////////////////////////
man中给出了epoll的用法,example程序如下:
       for(;;) {
           nfds = epoll_wait(kdpfd, events, maxevents, -1);

           for(n = 0; n < nfds; ++n) {
               if(events[n].data.fd == listener) {
                   client = accept(listener, (struct sockaddr *) &local,
                                   &addrlen);
                   if(client < 0){
                       perror("accept");
                       continue;
                   }
                   setnonblocking(client);
                   ev.events = EPOLLIN | EPOLLET;
                   ev.data.fd = client;
                   if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
                       fprintf(stderr, "epoll set insertion error: fd=%d\n",
                               client);
                       return -1;
                   }
               }
               else
                   do_use_fd(events[n].data.fd);
           }
       }
此时使用的是ET模式,即,边沿触发,类似于电平触发,epoll中的边沿触发的意思是只对新到的数据进行通知,而内核缓冲区中如果是旧数据则不进行通知,所以在do_use_fd函数中应该使用如下循环,才能将内核缓冲区中的数据读完。
        while (1) {
           len = recv(*******);
           if (len == -1) {
             if(errno == EAGAIN)
                break;
             perror("recv");
             break;
           }
           do something with the recved data........
        }

在上面例子中没有说明对于listen socket fd该如何处理,有的时候会使用两个线程,一个用来监听accept另一个用来监听epoll_wait,如果是这样使用的话,则listen socket fd使用默认的阻塞方式就行了,而如果epoll_wait和accept处于一个线程中,即,全部由epoll_wait进行监听,则,需将listen socket fd也设置成非阻塞的,这样,对accept也应该使用while包起来(类似于上面的recv),因为,epoll_wait返回时只是说有连接到来了,并没有说有几个连接,而且在ET模式下epoll_wait不会再因为上一次的连接还没读完而返回,这种情况确实存在,我因为这个问题而耗费了一天多的时间,这里需要说明的是,每调用一次accept将从内核中的已连接队列中的队头读取一个连接,因为在并发访问的环境下,有可能有多个连接“同时”到达,而epoll_wait只返回了一次。

唯一有点麻烦是epoll有2种工作方式:LT和ET。

LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.

ET (edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认。

posted @ 2012-06-26 13:32 tqsheng 阅读(134) | 评论 (0)编辑 收藏

slickedit的系统对话框资源文件在安装目录\macris\sysobjs,e中

_tbcontext_form
slickedit的系统对话框资源文件在安装目录\macris\sysobjs,e中
自定义的对话框在用户配置目录下\vusrobjs.e中

posted @ 2012-06-25 21:11 tqsheng 阅读(266) | 评论 (0)编辑 收藏

Visual Studio 2008 安装的失败与总结

今天系统是刚装的,今儿个也不是第一次装系统,也不是第一次装vs2008了,遇上vs2008安装出错倒是头一回。

先装系统,接着装0ffice2007,接着装ms sqlserver 2005,再装adobe cs4 master套装,一路setup,很是顺利,好就差vs2008了,它一装好,我就可以赚钱了。可结果安装出错的报错,报错的文档如下:

 

代码

 

我就开始看我indows系统的日志,没有任何红色提示,但我始终不相信我的安装文档有问题,因为同事他们也是用的这个版本(vs 2008 team),我更不相信电脑中毒(我很少中毒,够自信了:)),于是去网上查,结果答案有以下说法:

1、 .NET Framework 的版本问题,要什么M$提供的官方工具.NET Framework Setup Cleanup Utility (我里面已有1.0,2.0,3.5都有了)

2、安装office 2007后把MSOCache删除了(我这人洁癖这些个诸如临时文件肯定会删除的,这个我是有删除过。)

3、C:Program Files权限问题(我是用的超级用户,这个问题先排除。)

对于第一种说法我是打算试的,可下载太慢。就跳过去了;对于第二种解决方法网上有三种说法:1、把office2007卸载掉。2、把office2007重安装一遍;这两种都试了无效。第三种凑效了,那我就重点说说第3种吧;

我最后成功安装的方法详细如下:

1、把vs2008镜像文件下的WCUWebDesignerCoreWebDesignerCore.EXE 手动解压到一个地方(注意解压出来的文件夹里面有个Office.zh-cn)。

2、找一个office2007光盘或光盘镜像,找到Office.zh-cn文件夹,把该文件夹复制,然后覆盖到上一步解压中的Office.zh-cn中。

3、在第一步解压出来的文件中有个setup.exe,双击运行,好像是安装vs web 开发什么注意,只要能安装就行了。

4、上一步安装完后再运vs2008的setup.exe.

我的是这样安装完的。

后来我想了一下我以前为什么没出现这种问题,估计是我之前安装的顺序不一样(以前是先安装vs2005,vs2008,mssqlserver2005,office2007.adobe)

posted @ 2012-06-24 13:31 tqsheng 阅读(183) | 评论 (0)编辑 收藏

select 和 epoll

     摘要: select 和 epoll最近有朋友在面试的时候被问了select 和epoll效率差的原因,和一般人一样,大部分都会回答select是轮询、epoll是触发式的,所以效率高。这个答案听上去很完美,大致也说出了二者的主要区别。今天闲来无事,翻看了下内核代码,结合内核代码和大家分享下我的观点。一、连接数我本人也曾经在项目中用过select和epoll,对于select,感触最深的是linux下se...  阅读全文

posted @ 2012-06-20 21:07 tqsheng 阅读(426) | 评论 (0)编辑 收藏

POLL, SELECT & EPOLL 原理比较分析


因为需要了解底层设备访问的原理,所以惯用高层应用语言的我,需要了解一下Linux的设备访问机制,尤其是处理一组非阻塞IO的原理方法,标准的术语好像是叫多路复用。以下文章部分句子有引用之处,恕没有一一指出出处。

 

对于接触过Linux内核或设备驱动开发的读者,一定清楚poll和select系统调用,以及从2.5版本引入的epoll机制(epoll机制包含三个系统调用)。网上关于它们的文章,有说用法的,甚为详细,更有分析源代码的,又比较深入,且枝节颇多。经过几篇文章的阅读,我把觉得比较核心的东西写下来吧。我的用意是尽可能以简单的概念,比对他们三者的异同。

 

几经查找我才确定下来,poll和select应该被归类为这样的系统调用,它们可以阻塞地同时探测一组支持非阻塞的IO设备,是否有事件发生(如可读,可写,有高优先级的错误输出,出现错误等等),直至某一个设备触发了事件或者超过了指定的等待时间——也就是它们的职责不是做IO,而是帮助调用者寻找当前就绪的设备。同类型的产品是Windows的IOCP,它也是处理多路复用,只是把IO和探测封装在了一起了。

 

准备的知识有两点:1、fd;2、op->poll。

在Linux里面,设备都被抽象为文件,一系列的设备文件就有自己独立的虚拟文件系统,所以,设备在系统调用参数中的表示就是file description。fd其实就是一个整数(特别地,标准输入,输出,错误输出分别对应的fd是0,1,2)。与内核打交道的时候,传递整数的fd可以在自己的文件系统中作进一步的检查是否合法,如果只是返回指针就不能这样操作了,毕竟指针是无差别无意义的。

通过fd访问file,通过file可以访问其fileOperator,这里面我们要关心的一个fileOp就是poll。因为系统调用poll和select,就是依靠这个文件操作poll实现的。poll文件操作有两个参数,一个是文件本身,一个可以看做是当设备尚未就绪时调用的回调函数,这个函数是把设备自己特有的等待队列传给内核,让内核把当前的进程挂载到其中(因为当设备就绪时,设备就应该去唤醒在自己特有等待队列中的所有节点,这样当前进程就获取了完成的信号了)。poll文件操作返回的必须是一组标准的掩码,其中的各个位指示当前的不同的就绪状态(全0为没有任何事件触发)。

 

再谈谈早期多路复用的版本poll和select。

本质而言,poll和select的共同点就是,对全部指定设备做一次poll,当然这往往都是还没有就绪的,那就会通过回调函数把当前进程注册到设备的等待队列,如果所有设备返回的掩码都没有显示任何的事件触发,就去掉回调函数的函数指针,进入有限时的睡眠状态,再恢复和不断做poll,再作有限时的睡眠,直到其中一个设备有事件触发为止。只要有事件触发,系统调用返回,回到用户态,用户就可以对相关的fd作进一步的读或者写操作了。当然,这个时候还不是所有的设备都就绪的喔,那就得不断地poll或者select了,而做一次这样的系统调用都得轮询所有的设备,次数是设备数*(睡眠次数-1),也就是时间复杂度是O(n),还得做几次O(n)呢。可见,对于现在普遍的服务器程序,需要同时并发监听数千个连接,并且连接需要重复使用的情况,poll和select就存在这样的性能瓶颈。另外,数千个设备fd在每次调用时,都需要将其从用户空间复制到内核空间,这里的开销不可忽略。

 

poll和select放在一起,是因为其机制一致,而参数和数据结构就略有不同。select一次性传入三组作用于不同信道的设备fd,分别是输入,输出和错误异常。各组的fd期待各组所特有的,由代码指定的一组事件,如输入信道期待输入就绪,输入挂起和错误等事件。 然后,select就挑选调用者关心的fd做poll文件操作,检测返回的掩码,看看是否有fd所属信道感兴趣的事件,比如看看这个属于输出信道的fd有没有输出就绪等一系列的事件发生,一样地,如果有一个fd发生感兴趣事件就返回调用了。select,为了同时处理三组使用不同的事件判断规则的fd,采用了位图的方式表示,一组一个位图,位长度是当中最大的fd值,上限是1024,三组就是3072,而且这还只是传入的位图,还有一样大小的传出的位图。当fd数越来越多时,所需的存储开销比较大。

 

既然,一组fd处理起来比较粗放,那就各个fd自己准备好了。poll()系统调用是System V的多元I/O解决方案。它有三个参数,第一个是pollfd结构的数组指针,也就是指向一组fd及其相关信息的指针,因为这个结构包含的除了fd,还有期待的事件掩码和返回的事件掩码,实质上就是将select的中的fd,传入和传出参数归到一个结构之下,也不再把fd分为三组,也不再硬性规定fd感兴趣的事件,这由调用者自己设定。这样,不使用位图来组织数据,也就不需要位图的全部遍历了。按照一般队列地遍历,每个fd做poll文件操作,检查返回的掩码是否有期待的事件,以及做是否有挂起和错误的必要性检查,如果有事件触发,就可以返回调用了。

 

回到poll和select的共同点,面对高并发多连接的应用情境,它们显现出原来没有考虑到的不足,虽然poll比起select又有所改进了。除了上述的关于每次调用都需要做一次从用户空间到内核空间的拷贝,还有这样的问题,就是当处于这样的应用情境时,poll和select会不得不多次操作,并且每次操作都很有可能需要多次进入睡眠状态,也就是多次全部轮询fd,我们应该怎么处理一些会出现重复而无意义的操作。

 

这些重复而无意义的操作有:1、从用户到内核空间拷贝,既然长期监视这几个fd,甚至连期待的事件也不会改变,那拷贝无疑就是重复而无意义的,我们可以让内核长期保存所有需要监视的fd甚至期待事件,或者可以再需要时对部分期待事件进行修改;2、将当前线程轮流加入到每个fd对应设备的等待队列,这样做无非是哪一个设备就绪时能够通知进程退出调用,聪明的开发者想到,那就找个“代理”的回调函数,代替当前进程加入fd的等待队列好了(这也是我后来才总结出来,Linux的等待队列,实质上是回调函数队列吧,也可以使用宏来将当前进程“加入”等待队列,其实就是将唤醒当前进程的回调函数加入队列)。这样,像poll系统调用一样,做poll文件操作发现尚未就绪时,它就调用传入的一个回调函数,这是epoll指定的回调函数,它不再像以前的poll系统调用指定的回调函数那样,而是就将那个“代理”的回调函数加入设备的等待队列就好了,这个代理的回调函数就自己乖乖地等待设备就绪时将它唤醒,然后它就把这个设备fd放到一个指定的地方,同时唤醒可能在等待的进程,到这个指定的地方取fd就好了。我们把1和2结合起来就可以这样做了,只拷贝一次fd,一旦确定了fd就可以做poll文件操作,如果有事件当然好啦,马上就把fd放到指定的地方,而通常都是没有的,那就给这个fd的等待队列加一个回调函数,有事件就自动把fd放到指定的地方,当前进程不需要再一个个poll和睡眠等待了。

 

epoll机制就是这样改进的了。诚然,fd少的时候,当前进程一个个地等问题不大,可是现在和尚多了,方丈就不好管了。以前设备事件触发时,只负责唤醒当前进程就好了,而当前进程也只能傻傻地在poll里面等待或者循环,再来一次poll,也不知道这个由设备提供的poll性能如何,能不能检查出当前进程已经在等待了就立即返回,当然,我也不明白为什么做了一遍的poll之后,去掉回调函数指针了,还得再做,不是说好了会去唤醒进程的吗?

 

现在就让事件触发回调函数多做一步。本来设备还没就绪就调用一个回调函数了,现在再在这个回调函数里面做一个注册另一个回调函数的操作,目的就是使得设备事件触发多走一步,不仅仅是唤醒当前进程,还要把自己的fd放到指定的地方。就像收本子的班长,以前得一个个学生地去问有没有本子,如果没有,它还得等待一段时间而后又继续问,现在好了,只走一次,如果没有本子,班长就告诉大家去那里交本子,当班长想起要取本子,就去那里看看或者等待一定时间后离开,有本子到了就叫醒他,然后取走。这个道理很简单,就是老师和班干们常说的,大家多做一点工作,我的工作就轻松很多了,尤其是需要管理的东西越来越多时。

 

这种机制或者说模式,我想在Java的FutureTask里面应该也会用到的,一堆在线程池里面跑着的线程(当然这是任务,不是线程,接口是Callable<V>,不是Runnable.run,是Callable.call,它是可以返回结果的),谁先做好就应该先处理呀,可是难道得一个个问吗?干脆就谁好了,谁就按照既定的操作暴露自己,这样FutureTask的get方法就可以马上知道当前最先完成的线程了,就可以取此线程返回结果了。

 

epoll由三个系统调用组成,分别是epoll_create,epoll_ctl和epoll_wait。epoll_create用于创建和初始化一些内部使用的数据结构;epoll_ctl用于添加,删除或者修改指定的fd及其期待的事件,epoll_wait就是用于等待任何先前指定的fd事件。

 

关于epoll内部的数据结构,我就不能详细了解了。

posted @ 2012-06-20 21:06 tqsheng 阅读(152) | 评论 (0)编辑 收藏

Slickedit

主前色为白色,当前行高亮 ,注释的背景色去掉

Four Ways to Use Slick-C®

有个对话框例子

最佳实现的笔记

posted @ 2012-06-19 22:18 tqsheng 阅读(447) | 评论 (0)编辑 收藏

海淘

飞利浦Philips LFH0655/27 4G录音笔(支持关机一键录)$49.95
http://www.dzpyh.com/7816.html

户外自驾游好帮手 膳魔师Thermos Nissan 61盎司1.8L帝王级不锈钢保温壶 $25.16
http://www.dzpyh.com/6886.html
飞利浦Philips 1160XCC电动剃须刀带自动清洁系统$90.99 到手约680
http://www.dzpyh.com/7745.html

Sony ICD-UX523BLK录音笔

ICD-UX523F 
http://www.amazon.com/Thermos-Nissan-Stainless-Bottle-Folding/dp/B000U8D0H2/ref=pd_sbs_hg_17

Havaianas哈瓦那

posted @ 2012-05-30 22:11 tqsheng 阅读(250) | 评论 (0)编辑 收藏

维生素

Triflex速效型维骨力GNC Vitamin A & D 100 Softgel CapsulesGNC Calcium Citrate 1000 180 TabletsGNC Calcimate Complete 120 CapletsGNC Calcimate Complete™ 120 Caplets补脑

http://www.gnc.com/product/index.jsp?productId=2134099&kwCatId=
Memorall
该款产品隶属GNC顶级营养预防系列,是配方最全面的补脑配方,富含多种增强记忆力的营养素,维生素、DHA、银杏和胆碱等,有效补脑,增强记忆力,适合学生,白领脑力工作者和中老年人。
New Chapter Neurozyme ® 天然有机 补脑健忆智力配方

眼睛

 GNC bilberry
http://www.gnc.com/product/index.jsp?productId=2133924#productTabset

va vd
GNC Vitamin A & D 100 Softgel Capsules美国顶级Solgar纯挪威鳕鱼肝油 提供VA+VD

VC
New Chapter Activated C Food Complex 90 tablet sizes


GNC Calcimate Complete™ 120 Caplets
GNC Calcium Citrate 1000 180 Tablets

芦荟
GNC Natural Brand Aloe Vera Gel


Triflex速效型维骨力

whey protein 乳清蛋白粉
GNC葡萄籽精华

GNCHerbal Plus Grape Seed Extract 

GNC葡萄籽精华

GNC顶级护眼配方
ocular formula

DMAE是Dimethylaminoethanol(二甲氨基乙醇)的简称,英文又简称为Deanol。
GNC补脑素DMAE





posted @ 2012-05-30 21:15 tqsheng 阅读(843) | 评论 (5)编辑 收藏

尿酸高

http://wenku.baidu.com/view/5de5a04f2e3f5727a5e962d2.html

posted @ 2012-05-24 23:38 tqsheng 阅读(136) | 评论 (0)编辑 收藏

google.com/ncr

google.com/ncr  不适用国家重定向 也就是不会转到.cn上去 不过某些内容一样会被Block掉 

posted @ 2012-05-13 15:59 tqsheng 阅读(419) | 评论 (1)编辑 收藏

美国人教你这样用Google

美国人教你这样用Google,你真的会变特工!!!这...





第一篇 

在搜索框上输入:“indexof/”inurl:lib 
再按搜索你将进入许多图书馆,并且一定能下载自己喜欢的书籍。 

在搜索框上输入:“indexof/”cnki 
再按搜索你就可以找到许多图书馆的CNKI、VIP、超星等入口! 

在搜索框上输入:“indexof/”ppt 
再按搜索你就可以突破网站入口下载powerpint作品! 

在搜索框上输入:“indexof/”mp3 
再按搜索你就可以突破网站入口下载mp3、rm等影视作品! 

在搜索框上输入:“indexof/”swf 
再按搜索你就可以突破网站入口下载flash作品! 

在搜索框上输入:“indexof/”要下载的软件名 
再按搜索你就可以突破网站入口下载软件! 

注意引号应是英文的! 


第二篇 

用Google看世界!!! 只要你在GOOGLE里输入特殊的关键字,就可以搜到数千个摄象头的IP地址!通过他你就可以看到其所摄的实时影象!! 

在Google里输入 

inurl:"viewerframe?mode=" 

随便打开一个,然后按提示装一个插件,就可以看到了!!! 

第三篇 

三则黑客的Google搜索技巧简介 

大家都知道,Google毫无疑问是当今世界上最强大的搜索引擎。然而,在黑客手中,它也是一个秘密武器,它能搜索到一些你意想不到的信息。赛迪编者把他们进行了简单的总结不是希望您利用他去攻击别人的网站,而是利用这些技巧去在浩如烟海的网络信息中,来个大海捞针,寻找到对您有用的信息。 

如果您是一名普通网民,您可以使用黑客的技巧扩大自己的视野,提高自己的检索效率;如果您是一名网管,请您赶快看看您的网站是否做好了对下面黑客探测手 段的防范措施,如果没有就赶快来个亡羊补牢,毕竟隐患胜于明火,防范胜于救灾;如果您是一名黑客,相信您早以在别的黑客站点上见过类似的方法,这篇文章对您没什么用处,这里的技巧对您是小儿科,菜鸟级!您可以节省宝贵的时间做更有意义的事情,这篇文章您不用看了,到别处去吧! 

基于上面的考虑我编发了这篇文章。 

搜索URL 

比如我们提交这种形式:passwd.txtsite:virtualave.net 

看到了什么?是不是觉得太不可思议了!有很多基于CGI/PHP/ASP类型的留言板存在这种问题。有时我们得到密码甚至还是明码的!管理员或许太不负责了,或许安全防范的意识太差了,如果你是网络管理员,赶快检查一下不要让恶意攻击者捡了便宜。不要太相信DES加密,即使我们的密码经过DES加密的密 码,黑客们还是可以通过许多破解软件来搞定。 

这次我们能得到包含密码的文件。“site:virtualave.net”意思是只搜索virutalave.net的URL。virutalave.net是一个网络服务器提供商。 

同样,我们可以搜索一些顶级域名,比如:.net.org.jp.in.gr 

config.txtsite:.jp 

admin.txtsite:.tw 

搜索首页的目录 

首页是非常有用的,它会提供给你许多有用的信息。 

我们提交如下的形式: 

"Indexof/admin" 

"Indexof/secret" 

"Indexof/cgi-bin"site:.edu 

你可以自己定义搜索的首页字符。这样就可以获得许多信息。 

搜索特定的文件类型 

比如你想指定一种文件的类型,可以提交如下形式: 

filetype:.docsite:.milclassified 

这个就是搜索军方的资料,你可以自定义搜索。 

第四篇 

Google的特殊功能 

1、查询电话号码 

Google的搜索栏中最新加入了电话号码和美国街区地址的查询信息。 

个人如想查找这些列表,只要填写姓名,城市和省份。 

如果该信息为众人所知,你就会在搜索结果页面的最上方看到搜索的电话和街区地址 

你还可以通过以下任何一种方法找到该列表: 

名字(或首位大写字母),姓,电话地区号 

名字(或首位大写字母),姓,邮递区号 

名字(或首位大写字母),姓,城市(可写州) 

名字(或首位大写字母),姓,州 

电话号码,包括区号 

名字,城市,州 

名字,邮递区号 

2、查找PDF文件 

现在GOOGLE的搜索结果中包括了PDF文件。尽管PDF文件不如HTML文件那么多,但他们经常具备一些其他文件不具备的高质量信息 

为了显示一个搜索结果是PDF文件而不是网页,PDF文件的标题开头显示蓝色文本。 

这就是让你知道ACRTOBATREADER程序会启动来阅读文件 

如果你的计算机没装有该程序,计算机会指导你去能免费下载该程序的网页。 

使用PDF文件时,相关的网页快照会由“TEXTVERSION”代替,它是PDF文档的复制文件,该文件除去了所有格式化命令。 

如果你在没有PDF链接的情况下想看一系列搜索结果,只要在搜索栏中打上-inurldf加上你的搜索条件。 

3、股票报价 

用Google查找股票和共有基金信息,只要输入一个或多个NYSE,NASDAQ,AMEX或 

共有基金的股票行情自动收录机的代码,也可以输入在股市开户的公司名字。 

如果Google识别出你查询的是股票或者共有基金,它回复的链接会直接连到高质量的金融信息提供者提供的股票和共有基金信息。 

在你搜索结果的开头显示的是你查询的股市行情自动收录器的代码。如果你要查找一家公司的名字(比如,INTEL),请查看“股票报价”在Google搜索结果的金融栏里会有那个公司的主页的链接(比如, www. INTEL. COM)。 

Google是以质量为基础来选择和决定金融信息提供者的,包括的因素有下载速度,用户界面及其功能。 

4、找找谁和你链接 

有些单词如果带有冒号就会有特殊的意思。比如link:操作员。查询link:siteURL,就会显示所有指向那个URL的网页。举例来说,链接 www. Google. com会向你显示所有指向GOOGLE主页的网页。但这种方法不能与关键字查询联合使用。 

5、查找站点 

单词site后面如果接上冒号就能够将你的搜索限定到某个网站。具体做法是:在c搜索栏中使用site:sampledomain.com这个语法结构。比如,在斯坦福找申请信息,输入: 

admissionsite: www. stanford. edu 

6、查找字典释意 

查找字典释意的方法是在搜索栏中输入你要查询的内容。在我们根据要求找到所有的字典释意都会标有下划线,位于搜索结果的上面,点击链接你会找到字典提供者根据要求给出的相关定义。7、用GOOLGE查找地图 

想用Google查找街区地图,在Google搜索栏中输入美国街区地址,包括邮递区号或城市/州(比如165大学大街PALOALTOCA)。通常情况下,街区地址和城市的名字就足够了。 

当Google识别你的要求是查找地图,它会反馈给你有高质量地图提供者提供的链接,使你直接找到相关地图。我们是以质量为基础选择这些地图提供者。值得注意的是Google和使用的地图信息提供者没有任何关联。 

posted @ 2012-05-13 15:47 tqsheng 阅读(217) | 评论 (0)编辑 收藏

VC中如何实现窗口的隐藏

用MFC做的Dialog based 程序只要在OnInitDialog()函数里面写如下代码就能实现窗口隐藏:  
    
    SetWindowPos(&CWnd::wndNoTopMost,0,0,0,0,SWP_HIDEWINDOW);   
    ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);   

但是在任务管理器中还能看到!

将上述代码写入一个按纽的CLICK事件中即可实现程序的后台运行,且任务管理器中不可见!

下面的方法可以使窗口彻底的不可见:

1. 如何有效地使初始窗口不显示
当我们想让窗口初始时不显示时,通常会用ShowWindow(SW_HIDE) ,但实际上还是在启动是可以看到窗口一闪而过的痕迹。所以,可以使用下面的方法来实现它:
(1.1)先在构造函数中设置布乐变量 visible值为false.

visible = false;
(1.2)重载 WM_WINDOWPOSCHANGING,并添加下面代码:void CTest_deleteDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if(!visible)
lpwndpos->flags &= ~SWP_SHOWWINDOW;

CDialog::OnWindowPosChanging(lpwndpos);
}

(1.3)然后设布尔visible变量值为true,并在要显示窗口时,再用ShowWindow(SW_SHOW)既可。visible = true;
ShowWindow(SW_SHOW);

posted @ 2012-04-27 09:45 tqsheng 阅读(747) | 评论 (0)编辑 收藏

一些电子书链接

软考官方指定教材及同步辅导书下载 | 软考历年真是解析与答案

软考视频 | 考试机构 | 考试时间安排

Java一览无余:Java视频教程 | Java SE | Java EE

.Net技术精品资料下载汇总:ASP.NET篇

.Net技术精品资料下载汇总:C#语言篇

.Net技术精品资料下载汇总:VB.NET篇

撼世出击:C/C++编程语言学习资料尽收眼底 电子书+视频教程

Visual C++(VC/MFC)学习电子书及开发工具下载

Perl/CGI脚本语言编程学习资源下载地址大全

Python语言编程学习资料(电子书+视频教程)下载汇总

最新最全Ruby、Ruby on Rails精品电子书等学习资料下载

数据库管理系统(DBMS)精品学习资源汇总:MySQL篇 | SQL Server篇 | Oracle篇

ActionScript、Flex、 AIR等RIA技术相关资料下载汇总

最强HTML/xHTML、CSS精品学习资料下载汇总

最新JavaScript、Ajax典藏级学习资料下载分类汇总

网络最强PHP开发工具+电子书+视频教程等资料下载汇总

UML学习电子资下载汇总 软件设计与开发人员必备

经典LinuxCBT视频教程系列 Linux快速学习视频教程一帖通

天罗地网:精品Linux学习资料大收集(电子书+视频教程) Linux参考资源大系

Linux系统管理员必备参考资料下载汇总

Linux shell、内核及系统编程精品资料下载汇总

UNIX操作系统精品学习资料<电子书+视频>分类总汇

FreeBSD/OpenBSD/NetBSD精品学习资源索引 含书籍+视频

Solaris/OpenSolaris电子书、视频等精华资料下载索引 

posted @ 2012-04-25 10:51 tqsheng 阅读(173) | 评论 (0)编辑 收藏

dns ipv6

 
毕业设计需要,要在linux下搭建一个支持ipv6的dns服务器。 具体来说很简单,用Bind9搭建一个本机dns服务器,然后把本机dns设置成搭建的dns服务器地址,给dns服务器添加一个域名到ipv6地址的映射,然后当本机访问刚刚设定域名的时候返回对应的ipv6地址。 求详细设置,搭建的步骤,最好自己以前做过的。不吝感谢

问题补充:

提供一个详细的Bind 9.6.1的named.conf配置文件和正反向区域文件即可。我安装的是Fedora的bind-9.6.1-11.P1.fc12.i686.rpm


这事简单啊,好好看看bind手册 http://wenku.baidu.com/view/c3e081c24028915f804dc2df.html IPv6的配置和v4差别不大,在named.conf中只是增加一条listen on ipv6 port的命令。 listen-on-v6 port 53 { 1.1.1.1; }; 正反向区域文件按照IPv4格式配就OK了。一个区别就是IPv4为A记录,IPv6为AAAA记录。 4.9.1 使用AAAA记录查找地址 IPv6的AAAA记录与IPv4的A记录相对应,并且与被废除的A6记录不同,它在一个记录中指定完整的IPv6地址。例如: $ORIGIN example.com. host 3600 IN AAAA 2001:db8::1 不推荐使用IPv6内嵌IPv4映射地址。如果一个主机有一个IPv4地址,使用一个A记录,而不是带有::ffff:192.168.42.1的AAAA记录来作为其地址。 4.9.2 使用半字节格式从地址查名字 在使用半字节格式来查找一个地址时,地址元素只是简单地反转,并且在反转之后的名字后 DOWNLOAD from WWW.AIDNS.CN 面添加ip6.arpa.,就像在IPv4中一样。例如,下面将提供对一个地址为2001:db8::1的主机进行反向名字查找。 $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 14400 IN PTR host.example.com.

posted @ 2012-04-25 10:48 tqsheng 阅读(296) | 评论 (0)编辑 收藏

仅列出标题
共25页: First 9 10 11 12 13 14 15 16 17 Last