poll的機制與select類似,與select在本質上沒有多大差别,管理多個描述符也是進行輪詢,根據描述符的狀态進行處理,但是poll沒有最大檔案描述符數量的限制。
poll和select同樣存在一個缺點就是,包含大量檔案描述符的數組被整體複制于使用者态和核心的位址空間之間,而不論這些檔案描述符是否就緒,它的開銷随着檔案描述符數量的增加而線性增大。

函數格式如下所示:
1
2
fds
是一個struct pollfd結構類型的數組,用于存放需要檢測其狀态的socket描述符;每當調用這個函數之後,系統不會清空這個數組,操作起來比較友善;特别是對于socket連接配接比較多的情況下,在一定程度上可以提高處理的效率;這一點與select()函數不同,調用select()函數之後,select()函數會清空它所檢測的socket描述符集合,導緻每次調用select()之前都必須把socket描述符重新加入到待檢測的集合中;是以,select()函數适合于隻檢測一個socket描述符的情況,而poll()函數适合于大量socket描述符的情況;
nfds
nfds_t類型的參數,用于标記數組fds中的結構體元素的總數量;
timeout
是poll函數調用阻塞的時間,機關:毫秒;
和 select 一樣,最後一個參數 timeout 指定 poll() 将在逾時前等待一個事件多長事件。這裡有 3 種情況:
timeout 為 -1
這會造成 poll 永遠等待。poll() 隻有在一個描述符就緒時傳回,或者在調用程序捕捉到信号時傳回(在這裡,poll 傳回 -1),并且設定 errno 值為 eintr 。-1 可以用宏定義常量 inftim 來代替(在 pth.h 中有定義) 。
timeout 等于0
在這種情況下,測試所有的描述符,并且 poll() 立刻傳回。這允許在 poll 中沒有阻塞的情況下找出多個檔案描述符的狀态。
time > 0
這将以毫秒為機關指定 timeout 的逾時周期。poll() 隻有在逾時到期時傳回,除非一個描述符變為就緒,在這種情況下,它立刻傳回。如果逾時周期到齊,poll() 傳回 0。這裡也可能會因為某個信号而中斷該等待。
和 select 一樣,檔案描述符是否阻塞對 poll 是否阻塞沒有任何影響。
成功時,poll()傳回結構體中revents域不為0的檔案描述符個數;如果在逾時前沒有任何事件發生,poll()傳回0;失敗時,poll()傳回-1
>0
數組fds中準備好讀、寫或出錯狀态的那些socket描述符的總數量;
==0
數組fds中沒有任何socket描述符準備好讀、寫,或出錯;此時poll逾時,逾時時間是timeout毫秒;換句話說,如果所檢測的socket描述符上沒有任何事件發生的話,那麼poll()函數會阻塞timeout所指定的毫秒時間長度之後傳回,如果timeout==0,那麼poll() 函數立即傳回而不阻塞,如果timeout==inftim,那麼poll() 函數會一直阻塞下去,直到所檢測的socket描述符上的感興趣的事件發生是才傳回,如果感興趣的事件永遠不發生,那麼poll()就會永遠阻塞下去;
-1
poll函數調用失敗,同時會自動設定全局變量errno為下列值之一
errno
描述
ebadf
一個或多個結構體中指定的檔案描述符無效
efaultfds
指針指向的位址超出程序的位址空間
eintr
請求的事件之前産生一個信号,調用可以重新發起
einvalnfds
參數超出plimit_nofile值
enomem
可用記憶體不足,無法完成請求
3
4
5
6
fd 成員表示感興趣的,且打開了的檔案描述符;
events 成員是位掩碼,用于指定針對這個檔案描述符感興趣的事件;
revents 成員是位掩碼,用于指定當 poll 傳回時,在該檔案描述符上已經發生了哪些事情。
每一個pollfd結構體指定了一個被監視的檔案描述符,可以傳遞多個結構體,訓示poll()監視多個檔案描述符。
在poll傳回時,我們可以檢查revents中的标志,對應于檔案描述符請求的events結構體。如果pollin事件被設定,則檔案描述符可以被讀取而不阻塞。
如果pollout被設定,則檔案描述符可以寫入而不導緻阻塞。這些标志并不是互斥的:它們可能被同時設定,表示這個檔案描述符的讀取和寫入操作都會正常傳回而不阻塞。
timeout參數指定等待的毫秒數,無論i/o是否準備好,poll都會傳回。timeout指定為負數值表示無限逾時,使poll()一直挂起直到一個指定事件發生;timeout為0訓示poll調用立即傳回并列出準備好i/o的檔案描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即傳回。
每個結構體的events域是監視該檔案描述符的事件掩碼,由使用者來設定這個域。
revents域是檔案描述符的操作結果事件掩碼,核心在調用傳回時設定這個域。
events域中請求的任何事件都可能在revents域中傳回。
例如fds[0].events = pollin; /将測試條件設定成普通或優先級帶資料可讀/ 然後 int pollresult = poll(fds,xx,xx); //這樣就可以監聽fds裡面檔案描述符了,當滿足特定條件就傳回,并将結果儲存在revents中。
合法的事件如下:
事件
pollin
有資料可讀
pollrdnorm
有普通資料可讀
pollrdband
有優先資料可讀。
pollpri
有緊迫資料可讀。
pollout
寫資料不會導緻阻塞
pollwrnorm
寫普通資料不會導緻阻塞
pollwrband
寫優先資料不會導緻阻塞
pollmsgsigpoll
消息可用。
此外,revents域中還可能傳回下列事件:
poller
指定的檔案描述符發生錯誤
pollhup
指定的檔案描述符挂起事件
pollnval
指定的檔案描述符非法
這些事件在events域中無意義,因為它們在合适的時候總是會從revents中傳回。
events 中使用該宏常數,能夠在折本檔案的可讀情況下,結束 poll() 函數。相反,revents 上使用該宏常數,在檢查 poll() 函數結束後,可依此判斷裝置檔案是否處于可讀狀态(即使消息長度是 0)。
在 events 域中使用該宏常數,能夠在裝置檔案的高優先級資料讀取狀态下,結束 poll() 函數。相反,revents 上使用該宏常數,在檢查 poll() 函數結束後,可依此判斷裝置檔案是否處于可讀高優先級資料的狀态(即使消息長度是 0)。該宏常數用于處理網絡資訊包(packet) 的資料傳遞。
在 events 域中使用該宏常數,能夠在裝置檔案的寫入狀态下,結束 poll() 函數。相反,revents 域上使用該宏常數,在檢查 poll() 結束後,可依此判斷裝置檔案是否處于可寫狀态。
pollerr
在 events 域中使用該宏常數,能夠在裝置檔案上發生錯誤時,結束 poll() 函數。相反,revents 域上使用該宏函數,在檢查 poll() 函數結束後,可依此判斷裝置檔案是否出錯。
在 events域中使用該宏常數,能夠在裝置檔案中發生 hungup 時,結束 poll() 函數 。相反,在檢查 poll() 結束後,可依此判斷裝置檔案是否發生 hungup 。
在 events 域中使用該宏函數,能夠在檔案描述符的值無效時,結束 poll() 。相反,在 revents 域上使用該宏函數時,在檢查 poll() 函數後,檔案描述符是否有效。可用于處理網絡資訊時,檢查 socket handler 是否已經無效。
使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。
pollin | pollpri等價于select()的讀事件,
pollout |pollwrband等價于select()的寫事件。
pollin等價于pollrdnorm |pollrdband,
而pollout則等價于pollwrnorm。
例如,要同時監視一個檔案描述符是否可讀和可寫,我們可以設定 events為pollin |pollout。
poll的本質是輪訓,就是監聽我們所有的檔案描述符的所注冊的事件,當有事件請求時,poll傳回,然後我們輪詢所有的描述符,找到有時間請求的那個即可
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
轉自:http://blog.csdn.net/gatieme/article/details/50978320