天天看點

Linux下套接字詳解(九)---poll模式下的IO多路複用伺服器 poll多路複用 poll程式設計模型 示例

poll的機制與select類似,與select在本質上沒有多大差别,管理多個描述符也是進行輪詢,根據描述符的狀态進行處理,但是poll沒有最大檔案描述符數量的限制。

poll和select同樣存在一個缺點就是,包含大量檔案描述符的數組被整體複制于使用者态和核心的位址空間之間,而不論這些檔案描述符是否就緒,它的開銷随着檔案描述符數量的增加而線性增大。

Linux下套接字詳解(九)---poll模式下的IO多路複用伺服器 poll多路複用 poll程式設計模型 示例

函數格式如下所示:

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

繼續閱讀