select()
和poll()
系統呼叫的本質一樣,前者在
bsd unix
中引入的,後者在
system v
中引入的。
一、select
應用程式中最廣泛用到的是
bsd unix
中引入的
select()
系統呼叫,其原型如下:
int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
select
的第乙個引數
maxfdp
是檔案描述符集中要被檢測的數目,這個值必須至少比待檢測的最大檔案描述符大1;
引數readfds
指定了需要被讀監測的檔案描述符集;引數
writefds
指定了需要被寫監測的檔案描述符集;而引數
errorfds
指定了可能出現異常情況的檔案描述符集。
timeout
引數是乙個指向
struct timeval
型別的指標,它可以使
select()
在等待timeout
時間後若沒有檔案描述符準備好則返回。
struct timeval
資料結構的定義如下:
struct timeval
;timeout
取不同的值,該呼叫就表現不同的性質: 1
.timeout為0
,呼叫立即返回; 2
.timeout
為null
,select()
呼叫就阻塞,直到知道有檔案描述符就緒;
(當有檔案描述符就緒時,會向這個函式傳送訊號,以喚醒此函式。)
3.timeout
為正整數,就是一般的定時器。
select
的返回值有如下情況: 1
.正常情況下返回就緒的檔案描述符個數; 2
.經過了
timeout
時長後仍無裝置準備好,返回值為0;
3.如果select
被某個訊號中斷,它將返回
-1並設定
errno
為eintr。
4.如果出錯,返回
-1並設定相應的
errno
。select()
函式的介面主要是建立在一種叫
fd_set
結構體的基礎上。這個結構體是一組檔案描述符(
fd)的集合。因為
fd_set
型別的長度在不同平台上是不同的,此應該用一組標準的巨集定義來處理這個類變數。
我們來了解
fd_set
這個結構的定義:
typedef struct __kernel_fd_set;
#define __nfdbits (8 * sizeof(unsigned long)) //32
#define __fd_setsize 1024//
每個程序能開啟的檔案描述符的上限,可以更改
#define __fdset_longs (__fd_setsize/__nfdbits)// 32
typedef __kernel_fd_set fd_set;
對用fd_set
定義的readfds
、writefds
、errorfds
操作集進行操作最好使用封裝的通用巨集來處理:
fd_zero(fd_set *set);//
將檔案描述符集
fd_set
中的值置
0,如此以來對應所有位都被設定為0;
fd_set(int fd,fd_set *set);//
將乙個檔案描述符加入檔案描述集中;
fd_clr(int fd,fd_set *set)//
將乙個檔案描述符從檔案描述符集中清除;
fd_isset(int fd,fd_set *set)//
判斷檔案描述符是否被置位。
下面是乙個典型的程式片段:
fd_zero(&readset);
fd_set(fd,&readset);
select(fd+1,&readset,null,null,null);
if(fd_isset(fd,readset)
需要注意的是每次呼叫
select
之前都需要重新設定
fd_set
集合。二、
poll
函式原型
#include
int poll(struct pollfd * fdarray, unsigned long nfds, int timeout);
返回值說明:
>0
準備好描述字的個數;
=0超時;
= -1
表示出錯。
第乙個引數是乙個
pollfd
結構體陣列,其中包括了你想測試的檔案描述符和事件
, 事件由結構中事件域
events
來確定,呼叫後實際發生的時間將被填寫在結構體的
revents
域。struct pollfd ;
等待事件的掩碼:
pollin
普通或優先順序帶資料可讀
pollrdnorm
普通資料可讀
pollrdband
優先順序帶資料可讀
pollpri
高優先順序資料可讀
pollout
普通或優先順序帶資料可寫
pollwrnorm
普通資料可寫
pollwrband
優先順序帶資料可寫
pollerr
發生錯誤
pollhup
發生掛起
pollval
描述字不是乙個開啟的檔案
第一部分為處理輸入的四個常值,第二部分是處理輸出的三個常值,第三部分是處理錯誤的三個常值。
poll
處理三個級別的資料,普通
normal
,優先順序帶
priority band
,高優先順序
high priority
,這些都是出於流的實現。
第二個引數
nfds
用來指定第乙個引數陣列元素個數。
第三個引數指定
poll
函式在返回前等待多長時間,單位為毫秒。當等待時間為0時,
poll()
函式立即返回,為
-1則使
poll()
一直阻塞直到乙個指定事件發生。
如果沒有事件發生,
revents
會被清空,所以你不必多此一舉。
例子如下:
int poll_two_normal(int fd1,int fd2)
if(((poll_list[0].revents&pollhup) == pollhup) ||
((poll_list[0].revents&pollerr) == pollerr) ||
((poll_list[0].revents&pollnval) == pollnval) ||
((poll_list[1].revents&pollhup) == pollhup) ||
((poll_list[1].revents&pollerr) == pollerr) ||
((poll_list[1].revents&pollnval) == pollnval))
return 0;
if((poll_list[0].revents&pollin) == pollin)
handle(poll_list[0].fd,normal_data);
if((poll_list[0].revents&pollpri) == pollpri)
handle(poll_list[0].fd,hipri_data);
if((poll_list[1].revents&pollin) == pollin)
handle(poll_list[1].fd,normal_data);
if((poll_list[1].revents&pollpri) == pollpri)
handle(poll_list[1].fd,hipri_data);}}
參考文件:
在tomcat web應用程式
在tomcat web應用程式 某人曰 在沒其他工具的情況下不會手動新增web應用的程式設計師是乙個菜鳥 軍哥曰 乙個不會使用好的ide開發工具的程式設計師絕對不是乙個好的程式設計師 開發web應用時,不同型別的檔案有嚴格的存放規則,否則不僅可能會使web應用無法訪問,還會導致web伺服器啟動報錯。...
在應用程式之間傳遞引數
在程式設計中經常會遇到在應用程式間傳遞引數的問題 我總結了兩種方法 一。在用shellexcute啟動另外乙個應用程式的同時將引數傳遞過去.函式shellexcute的原型 hinstance shellexecute hwnd hwnd,父視窗的視窗控制代碼 lpctstr lpoperation...
在應用程式中宿主MEF
在應用程式中宿主mef其實非常簡單,只需要建立乙個組合容器物件 compositioncontainer 的例項,然後將需要組合的部件 parts 和當前宿主程式新增到容器中即可。首先需要新增mef框架的引用,既system.componentmodel.composition.dll,詳細如下 塊...