eventfd是linux 2.6.22後系統提供的一個輕量級的進程間通訊的系統調用,eventfd經過一個進程間共享的64位計數器完成進程間通訊,這個計數器由在linux內核空間維護,用戶能夠經過調用write方法向內核空間寫入一個64位的值,也能夠調用read方法讀取這個值。linux
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
複製代碼
建立的時候能夠傳入一個計數器的初始值initval。 第二個參數flags在linux 2.6.26以前的版本是沒有使用的,必須初始化爲0,在2.6.27以後的版本flag才被使用。ios
EFD_CLOEXEC(2.6.27~):c++
A copy of the file descriptor created by eventfd() is inherited by the child produced by fork(2). The duplicate file descriptor is associated with the same eventfd object. File descriptors created by eventfd() are preserved across execve(2), unless the close-on-exec flag has been set.bash
eventfd()會返回一個文件描述符,若是該進程被fork的時候,這個文件描述符也會複製過去,這時候就會有多個的文件描述符指向同一個eventfd對象,若是設置了EFD_CLOEXEC標誌,在子進程執行exec的時候,會清除掉父進程的文件描述符less
EFD_NONBLOCK(2.6.27~): 就如它字面上的意思,若是沒有設置了這個標誌位,那read操做將會阻塞直到計數器中有值。若是沒有設置這個標誌位,計數器沒有值的時候也會當即返回-1;ui
EFD_SEMAPHORE(2.6.30~): 這個標誌位會影響read操做,具體能夠看read方法中的解釋spa
read: 讀取計數器中的值code
write: 向計數器中寫入值對象
close: 關閉文件描述符進程
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_t count;
eventfd_read(efd, &count);
std::cout << count << std::endl;
close(efd);
}
複製代碼
上面的程序中咱們建立了一個eventfd,並將它的文件描述符保存在efd中,而後調用eventfd_write向計數器中寫入數字2,而後調用eventfd_read讀取計數器中的值並打印處理,最後關閉eventfd。 運行結果:
count=2
複製代碼
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_write(efd, 3);
eventfd_write(efd, 4);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
複製代碼
運行結果:
read_result=0
count=9
read_result=-1
count=9
複製代碼
從運行結果咱們能夠看出當屢次調用eventfd_write的時候,計數器一直在累加,可是eventfd_read只需調用一次就能夠將計數器中的數取出來,若是再次調用eventfd_read將會返回失敗。
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_write(efd, 3);
eventfd_write(efd, 4);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
複製代碼
運行結果:
read_result=0
count=9
複製代碼
和前一個運行結果直接返回-1相比,若是去掉EFD_NONBLOCK標誌位,程序會在計數器沒有值的狀況下一直阻塞在eventfd_read方法。
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE);
eventfd_write(efd, 2);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
複製代碼
運行結果:
read_result=0
count=1
read_result=0
count=1
read_result=-1
count=1
複製代碼
能夠看到設置了EFD_SEMAPHORE後,每次讀取到的值都是1,且read後計數器也遞減1。