生活随笔
收集整理的這篇文章主要介紹了
Linux 新api eventfd(转)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉自http://www.cppblog.com/peija/archive/2010/10/07/128941.html
eventfd 在內核版本,2.6.22以后有效。查看內核版本可以用命令 uname -r 。
1 #include <sys/eventfd.h>
2 int eventfd(unsigned
int initval,
int flags);
這個函數(shù)會創(chuàng)建一個 事件對象 (eventfd object), 用來實現(xiàn),進程(線程)間 的 等待/通知(wait/notify) 機制. 內核會為這個對象維護一個64位的計數(shù)器(uint64_t)。
?并且使用第一個參數(shù)(initval)初始化這個計數(shù)器。調用這個函數(shù)就會返回一個新的文件描述符(event object)。2.6.27版本開始可以按位設置第二個參數(shù)(flags)。
有如下的一些宏可以使用:
EFD_NONBLOCK , 功能同open(2) 的O_NONBLOCK,設置對象為非阻塞狀態(tài),如果沒有設置這個狀態(tài)的話,read(2)讀eventfd,并且計數(shù)器的值為0 就一直堵塞在read調用當中,要是設置了這個標志, 就會返回一個 EAGAIN 錯誤(errno = EAGAIN)。效果也如同 額外調用select(2)達到的效果。
EFD_CLOEXEC 我的理解是,這個標識被設置的話,調用exec后會自動關閉文件描述符,防止泄漏。
如果是2.6.26或之前版本的內核,flags 必須設置為0。
創(chuàng)建這個對象后,可以對其做如下操作。
write 將緩沖區(qū)寫入的8字節(jié)整形值加到內核計數(shù)器上。
read 讀取8字節(jié)值, 并把計數(shù)器重設為0. 如果調用read的時候計數(shù)器為0, 要是eventfd是阻塞的, read就一直阻塞在這里,否則就得到 一個EAGAIN錯誤。
如果buffer的長度小于8那么read會失敗, 錯誤代碼被設置成 EINVAL。
poll select epoll
close 當不需要eventfd的時候可以調用close關閉, 當這個對象的所有句柄都被關閉的時候,內核會釋放資源。 為什么不是close就直接釋放呢, 如果調用fork 創(chuàng)建
進程的時候會復制這個句柄到新的進程,并繼承所有的狀態(tài)。?
下面是一個例子
1 #include <sys/eventfd.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <errno.h>
7
8 #define handle_error(msg) \
9 do { perror(msg); exit(
1); }
while (
0)
10
11 int main(
int argc,
char **
argv )
12 {
13 uint64_t u;
14 ssize_t s;
15 int j;
16 if ( argc <
2 ) {
17 fprintf(stderr,
"input <num> in command argument");
18 exit(
1);
19 }
20
21 int efd;
22 if ( (efd = eventfd(
0, EFD_NONBLOCK)) == -
1 )
23 handle_error(
"eventfd failed");
24
25
26 switch (fork()) {
27 case 0:
28 for( j =
1; j < argc; j ++
) {
29 printf(
"Child writing %s to efd\n", argv[j] );
30
31 u = strtoull(argv[j], NULL,
0);
/* analogesly atoi */
32 s = write(efd, &u,
sizeof(uint64_t));
/* append u to counter */
33 if ( s !=
sizeof(uint64_t) )
34 handle_error(
"write efd failed");
35
36 }
37 printf(
"child completed write loop\n");
38
39 exit(
0);
40 default:
41 sleep (
2);
42
43 printf(
"parent about to read\n");
44 s = read(efd, &u,
sizeof(uint64_t));
45 if ( s !=
sizeof(uint64_t) ) {
46 if (errno =
EAGAIN) {
47 printf(
"Parent read value %d\n", s);
48 return 1;
49 }
50 handle_error(
"parent read failed");
51 }
52 printf(
"parent read %d , %llu (0x%llx) from efd\n",
53 s, (unsigned
long long)u, (unsigned
long long) u);
54 exit(
0);
55
56 case -
1:
57 handle_error(
"fork ");
58 }
59 return 0;
60 }
這個API還是很有用的, 當你想要編寫并發(fā)型服務器的時候,aventfd 可以完美取代 pipe去通知(喚醒)其他的進程(線程)。比如經典的異步IO reactor/selector?
應用場景,去喚醒select的調用。他的緩沖區(qū)處理非常方便, 規(guī)定只有8字節(jié)。
?
轉載于:https://www.cnblogs.com/minuse/p/7472795.html
總結
以上是生活随笔為你收集整理的Linux 新api eventfd(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。