我們常用的程序(執行緒)間通訊機制有管道,訊號,訊息佇列,訊號量,共享記憶體,socket等等,其中主要作為程序(執行緒)間通知/等待的有管道pipe和socketpair。執行緒還有特別的condition。
今天來看乙個liunx較新的系統呼叫,它是從linux 2.6.27版本開始增加的,主要用於程序或者執行緒間的通訊(如通知/等待機制的實現)。
首先來看一下函式原型:
#include int eventfd(unsigned int initval, int flags);
下面是它man手冊中的描述,我照著翻譯了一遍(我英語四級434,你們要是懷疑下文的話,可以直接去man eventfd ^^):
eventfd()建立了乙個"eventfd object",能在使用者態用做事件wait/notify機制,通過核心取喚醒使用者態的事件。這個物件儲存了乙個核心維護的uint64_t型別的整型counter。這個counter初始值被引數initval指定,一般初值設定為0。
它的標記可以有以下屬性:
efd_cloecex,efd_nonblock,efd_semaphore。
在linux直到版本2.6.26,這個flags引數是沒用的,必須指定為0。
它返回了乙個引用eventfd object的描述符。這個描述符可以支援以下操作:
read:如果計數值counter的值不為0,讀取成功,獲得到該值。如果counter的值為0,非阻塞模式,會直接返回失敗,並把errno的值指紋einval。如果為阻塞模式,一直會阻塞到counter為非0位置。
write:會增加8位元組的整數在計數器counter上,如果counter的值達到0xfffffffffffffffe時,就會阻塞。直到counter的值被read。阻塞和非阻塞情況同上面read一樣。
close:這個操作不用說了。
重點是支援這個:
poll(2), select(2) (and similar)
the returned file descriptor supports poll(2) (and analogously epoll(7)) and select(2), as follows:
* the file descriptor is readable (the select(2) readfds argument; the poll(2) pollin flag) if the counter has a
value greater than 0.
* the file descriptor is writable (the select(2) writefds argument; the poll(2) pollout flag) if it is possible to
write a value of at least "1" without blocking.
* if an overflow of the counter value was detected, then select(2) indicates the file descriptor as being both
readable and writable, and poll(2) returns a pollerr event. as noted above, write(2) can never overflow the
counter. however an overflow can occur if 2^64 eventfd "signal posts" were performed by the kaio subsystem (the‐
oretically possible, but practically unlikely). if an overflow has occurred, then read(2) will return that maxi‐
mum uint64_t value (i.e., 0xffffffffffffffff).
the eventfd file descriptor also supports the other file-descriptor multiplexing apis: pselect(2) and ppoll(2).
它的核心**實現是這樣子的:
int eventfd_signal(struct eventfd_ctx *ctx, int n)
本質就是做了一次喚醒,不用read,也不用write,與eventfd_write的區別是不用阻塞。
說了這麼多,我們來看乙個例子,理解理解其中的含義:
#include #include #include #include #include /* definition of uint64_t */
#define handle_error(msg) \
do while (0)
intmain(int argc, char *argv)
efd = eventfd(0, 0);
if (efd == -1)
handle_error("eventfd");
switch (fork())
printf("child completed write loop\n");
exit(exit_success);
default:
sleep(2);
printf("parent about to read\n");
s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
printf("parent read %llu (0x%llx) from efd\n",
(unsigned long long) u, (unsigned long long) u);
exit(exit_success);
case -1:
handle_error("fork");
}}
輸出:
$ ./a.out 1 2 4 7 14
child writing 1 to efd
child writing 2 to efd
child writing 4 to efd
child writing 7 to efd
child writing 14 to efd
child completed write loop
parent about to read
parent read 28 (0x1c) from efd
注意:這裡用了sleep(2)保證子程序迴圈寫入完畢,得到的值就是綜合28。如果不用sleep(2)來保證時序,當子程序寫入乙個值,父程序會立馬從eventfd讀出該值。
程序 執行緒間通訊機制
管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的程序間使用。程序的親緣關係通常是指父子程序。有名管道也是半雙工的通訊方式,但是它允許無親緣關係的程序間通訊。訊號量是乙個計數器,可以用來控制多個程序對共享資源的訪問。它常作為一種鎖機制,防止某程序正在訪問共享資源時,其他程序也訪問...
執行緒間通訊 等待喚醒機制
執行緒間通訊 其實就是多個執行緒在操作同乙個資源,但是操作的動作不同 class res2 class input2 implements runnable public void run catch interruptedexception e if x 0 else x x 1 2 r.flag...
執行緒間的通訊 等待喚醒機制
執行緒間的通訊 同步執行緒必須滿足兩個條件 一 兩個或兩個以上的執行緒 二 都使用同乙個鎖物件 題目描述 首先有乙個資源池 resource 輸入執行緒 input 不斷往資源池內新增內容,輸出執行緒 output 不斷往外輸出內容 並且兩個執行緒需要同步。需要的結果是,輸入執行緒輸入乙個內容,然後...