亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Linux服務器 > 正文

Linux 新的API signalfd、timerfd、eventfd使用說明

2024-09-05 23:02:43
字體:
來源:轉載
供稿:網友

三種新的fd加入linux內核的的版本:

signalfd:2.6.22

timerfd:2.6.25

eventfd:2.6.22

三種fd的意義:

lsignalfd

傳統的處理信號的方式是注冊信號處理函數;由于信號是異步發生的,要解決數據的并發訪問,可重入問題。signalfd可以將信號抽象為一個文件描述符,當有信號發生時可以對其read,這樣可以將信號的監聽放到select、poll、epoll等監聽隊列中。

ltimerfd

可以實現定時器的功能,將定時器抽象為文件描述符,當定時器到期時可以對其read,這樣也可以放到監聽隊列的主循環中。

leventfd

實現了線程之間事件通知的方式,也可以用于用戶態和內核通信。eventfd的緩沖區大小是sizeof(uint64_t);向其write可以遞增這個計數器,read操作可以讀取,并進行清零;eventfd也可以放到監聽隊列中,當計數器不是0時,有可讀事件發生,可以進行讀取。

三種新的fd都可以進行監聽,當有事件觸發時,有可讀事件發生。

signalfd涉及API:

點擊(此處)折疊或打開

#include <sys/signalfd.h> int signalfd(int fd, const sigset_t *mask, int flags);#include <sys/signalfd.h> int signalfd(int fd, const sigset_t *mask, int flags);

參數fd:如果是-1則表示新建一個,如果是一個已經存在的則表示修改signalfd所關聯的信號;

參數mask:信號集合;

參數flag:內核版本2.6.27以后支持SFD_NONBLOCK、SFD_CLOEXEC;

成功返回文件描述符,返回的fd支持以下操作:read、select(poll、epoll)、close

l例子

#include <sys/signalfd.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define handle_error(msg) / do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { sigset_t mask; int sfd; struct signalfd_siginfo fdsi; ssize_t s; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) handle_error("sigprocmask"); sfd = signalfd(-1, &mask, 0); if (sfd == -1) handle_error("signalfd"); for (;;) { s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) handle_error("read"); if (fdsi.ssi_signo == SIGINT) { printf("Got SIGINT/n"); } else if (fdsi.ssi_signo == SIGQUIT) { printf("Got SIGQUIT/n"); exit(EXIT_SUCCESS); } else { printf("Read unexpected signal/n"); } } }#include <sys/signalfd.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define handle_error(msg) / do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { sigset_t mask; int sfd; struct signalfd_siginfo fdsi; ssize_t s; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) handle_error("sigprocmask"); sfd = signalfd(-1, &mask, 0); if (sfd == -1) handle_error("signalfd"); for (;;) { s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) handle_error("read"); if (fdsi.ssi_signo == SIGINT) { printf("Got SIGINT/n"); } else if (fdsi.ssi_signo == SIGQUIT) { printf("Got SIGQUIT/n"); exit(EXIT_SUCCESS); } else { printf("Read unexpected signal/n"); } } }

L17-L21:將感興趣的信號加入到sigset_t中;

L24:調用signalfd,把信號集與fd關聯起來,第一個參數為-1表示新建一個signalfd,不是-1并且是一個合法的signalfd表示向其添加新的信號。

L29:阻塞等待信號的發生并讀取。根據讀取的結果可以知道發生了什么信號。

timerfd涉及的API

#include <sys/timerfd.h> int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new_value,struct itimerspec *old_value); int timerfd_gettime(int fd, struct itimerspec *curr_value);#include <sys/timerfd.h> int timerfd_create(int clockid, int flags); int timerfd_settime(int fd, int flags, const struct itimerspec *new_value,struct itimerspec *old_value); int timerfd_gettime(int fd, struct itimerspec *curr_value);timerfd_create:創建一個timerfd;返回的fd可以進行如下操作:read、select(poll、epoll)、closetimerfd_settime:設置timer的周期,以及起始間隔timerfd_gettime:獲取到期時間。//函數參數中數據結構如下: struct timespec { time_t tv_sec; /* Seconds */ long tv_nsec; /* Nanoseconds */ }; struct itimerspec { struct timespec it_interval; /* Interval for periodic timer */ struct timespec it_value; /* Initial expiration */ };//函數參數中數據結構如下: struct timespec { time_t tv_sec; /* Seconds */ long tv_nsec; /* Nanoseconds */ }; struct itimerspec { struct timespec it_interval; /* Interval for periodic timer */ struct timespec it_value; /* Initial expiration */ };

l例子

#include <sys/timerfd.h> #include <sys/time.h> #include <time.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> /* Definition of uint64_t */ #define handle_error(msg) / do { perror(msg); exit(EXIT_FAILURE); } while (0) void printTime() { struct timeval tv; gettimeofday(&tv, NULL); printf("printTime: current time:%ld.%ld ", tv.tv_sec, tv.tv_usec); } int main(int argc, char *argv[]) { struct timespec now; if (clock_gettime(CLOCK_REALTIME, &now) == -1) handle_error("clock_gettime"); struct itimerspec new_value; new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]); new_value.it_value.tv_nsec = now.tv_nsec; new_value.it_interval.tv_sec = atoi(argv[2]); new_value.it_interval.tv_nsec = 0; int fd = timerfd_create(CLOCK_REALTIME, 0); if (fd == -1) handle_error("timerfd_create"); if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1) handle_error("timerfd_settime"); printTime(); printf("timer started/n"); for (uint64_t tot_exp = 0; tot_exp < atoi(argv[3]);) { uint64_t exp; ssize_t s = read(fd, &exp, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error("read"); tot_exp += exp; printTime(); printf("read: %llu; total=%llu/n",exp, tot_exp); } exit(EXIT_SUCCESS); }#include <sys/timerfd.h> #include <sys/time.h> #include <time.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> /* Definition of uint64_t */ #define handle_error(msg) / do { perror(msg); exit(EXIT_FAILURE); } while (0) void printTime() { struct timeval tv; gettimeofday(&tv, NULL); printf("printTime: current time:%ld.%ld ", tv.tv_sec, tv.tv_usec); } int main(int argc, char *argv[]) { struct timespec now; if (clock_gettime(CLOCK_REALTIME, &now) == -1) handle_error("clock_gettime"); struct itimerspec new_value; new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]); new_value.it_value.tv_nsec = now.tv_nsec; new_value.it_interval.tv_sec = atoi(argv[2]); new_value.it_interval.tv_nsec = 0; int fd = timerfd_create(CLOCK_REALTIME, 0); if (fd == -1) handle_error("timerfd_create"); if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1) handle_error("timerfd_settime"); printTime(); printf("timer started/n"); for (uint64_t tot_exp = 0; tot_exp < atoi(argv[3]);) { uint64_t exp; ssize_t s = read(fd, &exp, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error("read"); tot_exp += exp; printTime(); printf("read: %llu; total=%llu/n",exp, tot_exp); } exit(EXIT_SUCCESS); }

代碼L25-L29:初始化定時器的參數,初始間隔與定時間隔。

L32:創建定時器fd,CLOCK_REALTIME:真實時間類型,修改時鐘會影響定時器;CLOCK_MONOTONIC:相對時間類型,修改時鐘不影響定時器。

L35:設置定時器的值。

L44:阻塞等待定時器到期。返回值是未處理的到期次數。比如定時間隔為2秒,但過了10秒才去讀取,則讀取的值是5。

編譯運行:編譯時要加rt庫(g++ -lrt timerfd.cc -o timerfd)

[root@localhost appTest]# ./timerfd 5 2 10printTime: current time:1357391736.146196 timer startedprintTime: current time:1357391741.153430 read: 1; total=1printTime: current time:1357391743.146550 read: 1; total=2printTime: current time:1357391745.151483 read: 1; total=3printTime: current time:1357391747.161155 read: 1; total=4printTime: current time:1357391749.153934 read: 1; total=5printTime: current time:1357391751.157309 read: 1; total=6printTime: current time:1357391753.158384 read: 1; total=7printTime: current time:1357391755.150470 read: 1; total=8printTime: current time:1357391757.150253 read: 1; total=9printTime: current time:1357391759.149954 read: 1; total=10[root@localhost appTest]#

第一個參數5為第一次定時器到期間隔,第二個參數2為定時器的間隔,第三個參數為定時器到期10次則退出。程序運行(5+2*10)S退出。

詳細信息可以:man timerfd_create

eventfd涉及API:

#include <sys/eventfd.h> int eventfd(unsigned int initval, int flags);#include <sys/eventfd.h> int eventfd(unsigned int initval, int flags);

創建一個eventfd,這是一個計數器相關的fd,計數器不為零是有可讀事件發生,read以后計數器清零,write遞增計數器;返回的fd可以進行如下操作:read、write、select(poll、epoll)、close。

這個函數會創建一個事件對象 (eventfd object), 用來實現,進程(線程)間的等待/通知(wait/notify) 機制. 內核會為這個對象維護一個64位的計數器(uint64_t)。并且使用第一個參數(initval)初始化這個計數器。調用這個函數就會返回一個新的文件描述符(event object)。2.6.27版本開始可以按位設置第二個參數(flags)。有如下的一些宏可以使用:

lEFD_NONBLOCK

功能同open(2)的O_NONBLOCK,設置對象為非阻塞狀態,如果沒有設置這個狀態的話,read(2)讀eventfd,并且計數器的值為0 就一直堵塞在read調用當中,要是設置了這個標志, 就會返回一個 EAGAIN 錯誤(errno = EAGAIN)。效果也如同 額外調用select(2)達到的效果。

lEFD_CLOEXEC

這個標識被設置的話,調用exec后會自動關閉文件描述符,防止泄漏。如果是2.6.26或之前版本的內核,flags 必須設置為0。
創建這個對象后,可以對其做如下操作:

1) write: 將緩沖區寫入的8字節整形值加到內核計數器上。

2) read: 讀取8字節值, 并把計數器重設為0. 如果調用read的時候計數器為0, 要是eventfd是阻塞的, read就一直阻塞在這里,否則就得到 一個EAGAIN錯誤。如果buffer的長度小于8那么read會失敗, 錯誤代碼被設置成 EINVAL。

3) poll select epoll

4) close: 當不需要eventfd的時候可以調用close關閉, 當這個對象的所有句柄都被關閉的時候,內核會釋放資源。 為什么不是close就直接釋放呢, 如果調用fork 創建
進程的時候會復制這個句柄到新的進程,并繼承所有的狀態。

l例子

#include <sys/eventfd.h>#include <unistd.h>#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <errno.h>#define handle_error(msg) /do { perror(msg); exit(1); } while (0)int main( int argc, char **argv ){uint64_t u;ssize_t s;5 int j;if ( argc < 2 ) {fprintf(stderr, "input in command argument");exit(1);}int efd;if ( (efd = eventfd(0, EFD_NONBLOCK)) == -1 )handle_error("eventfd failed");switch (fork()) {case 0:for( j = 1; j < argc; j ++ ) {printf("Child writing %s to efd/n", argv[j] );u = strtoull(argv[j], NULL, 0); /* analogesly atoi */s = write(efd, &u, sizeof(uint64_t));/*append u to counter */if ( s != sizeof(uint64_t) )handle_error("write efd failed");}printf("child completed write loop/n");exit(0);default:sleep (2);printf("parent about to read/n");s = read(efd, &u, sizeof(uint64_t));if ( s != sizeof(uint64_t) ) {if (errno = EAGAIN) {printf("Parent read value %d/n", s);return 1;}handle_error("parent read failed");}printf("parent read %d , %llu (0x%llx) from efd/n",s, (unsigned long long)u, (unsigned long long) u);exit(0);case -1:handle_error("fork ");}return 0;}#include <sys/eventfd.h>#include <unistd.h>#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <errno.h>#define handle_error(msg) /do { perror(msg); exit(1); } while (0)int main( int argc, char **argv ){uint64_t u;ssize_t s;5 int j;if ( argc < 2 ) {fprintf(stderr, "input in command argument");exit(1);}int efd;if ( (efd = eventfd(0, EFD_NONBLOCK)) == -1 )handle_error("eventfd failed");switch (fork()) {case 0:for( j = 1; j < argc; j ++ ) {printf("Child writing %s to efd/n", argv[j] );u = strtoull(argv[j], NULL, 0); /* analogesly atoi */s = write(efd, &u, sizeof(uint64_t));/*append u to counter */if ( s != sizeof(uint64_t) )handle_error("write efd failed");}printf("child completed write loop/n");exit(0);default:sleep (2);printf("parent about to read/n");s = read(efd, &u, sizeof(uint64_t));if ( s != sizeof(uint64_t) ) {if (errno = EAGAIN) {printf("Parent read value %d/n", s);return 1;}handle_error("parent read failed");}printf("parent read %d , %llu (0x%llx) from efd/n",s, (unsigned long long)u, (unsigned long long) u);exit(0);case -1:handle_error("fork ");}return 0;}

以上所述是小編給大家介紹的Linux 新的API signalfd、timerfd、eventfd使用說明,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲人成网在线播放| 欧美在线播放视频| 日韩一区二区久久久| 91精品成人久久| 18一19gay欧美视频网站| 国产一区二区黄| 在线观看日韩www视频免费| 亚洲娇小xxxx欧美娇小| 国产ts人妖一区二区三区| 97久久超碰福利国产精品…| 亚洲福利视频久久| 欧美性猛交丰臀xxxxx网站| 久久久综合免费视频| 亚洲人成在线观看网站高清| 亚洲伊人久久大香线蕉av| 国产一区二区三区18| 狠狠爱在线视频一区| 中文字幕日韩欧美精品在线观看| 国产精品久久久久久一区二区| 国产精品视频中文字幕91| 亚洲综合自拍一区| 亚洲精品成人久久电影| 91在线免费网站| 亚州成人av在线| 久久久精品中文字幕| 91av视频在线播放| 久久久久久国产精品三级玉女聊斋| 奇门遁甲1982国语版免费观看高清| 丰满岳妇乱一区二区三区| 欧美日韩在线免费| 欧美激情一级二级| 国内精品久久久久久中文字幕| 中文日韩在线视频| 国产精品成人aaaaa网站| 亚洲韩国欧洲国产日产av| 久久久久久国产精品| 日韩黄色av网站| 欧美大尺度电影在线观看| 亚洲美女福利视频网站| 亚洲福利影片在线| 日韩美女毛茸茸| 91在线观看免费高清完整版在线观看| 日本免费一区二区三区视频观看| 精品亚洲一区二区三区在线播放| 亚洲国产又黄又爽女人高潮的| 久久久免费电影| 国内精品久久久久影院优| 国产精品成人av在线| 欧美极品美女电影一区| 欧美一级成年大片在线观看| 中文字幕不卡av| 日韩中文字幕不卡视频| 欧美一区二区三区免费视| 国产精品爱啪在线线免费观看| 精品久久久久久久久国产字幕| 午夜精品久久久久久久99黑人| 国产精品永久在线| 日韩精品免费一线在线观看| 亚洲精品国精品久久99热| 国产精品免费视频久久久| 国产在线久久久| 亚洲专区中文字幕| 欧美日韩成人在线视频| 欧美大片va欧美在线播放| 亚洲精品白浆高清久久久久久| 国产成+人+综合+亚洲欧美丁香花| 亚洲免费视频观看| 日韩精品999| 色噜噜狠狠狠综合曰曰曰| 5566成人精品视频免费| 亚洲无av在线中文字幕| 川上优av一区二区线观看| 国产精品电影在线观看| 欧美极品美女电影一区| 中文字幕精品—区二区| 亚洲欧美综合图区| 亚洲毛片在线免费观看| 精品国产欧美一区二区五十路| 国产成人自拍视频在线观看| 国产精品久久久久免费a∨| 97在线视频免费| 日韩精品免费综合视频在线播放| 日韩av黄色在线观看| 欧美日韩xxxxx| 日韩电影网在线| 欧美激情乱人伦一区| 久久久国产精品视频| 日韩欧美在线国产| 国产精品都在这里| 国产成人精品免高潮费视频| 美女福利视频一区| 91wwwcom在线观看| 一区国产精品视频| 538国产精品视频一区二区| 色婷婷av一区二区三区在线观看| 亚洲自拍偷拍网址| 久久久久999| 成人激情视频在线播放| 91亚洲永久免费精品| 亚洲精品www久久久久久广东| 中文字幕欧美日韩精品| 欧美激情乱人伦| 精品一区二区三区电影| 欧美精品久久一区二区| 亚洲精品欧美一区二区三区| 欧美巨乳美女视频| 欧美精品aaa| 最近2019免费中文字幕视频三| 久久久亚洲国产天美传媒修理工| 国产精品色视频| 欧美激情啊啊啊| 国产精品久久久av| 91久久精品视频| 日韩免费精品视频| 亚洲欧美中文日韩v在线观看| 亚洲福利在线观看| 日韩高清免费观看| 亚洲国产精品成人va在线观看| 亚洲精品一区二区网址| 欧美在线免费视频| 日韩国产欧美精品在线| 一区二区三区亚洲| 成人黄色中文字幕| 亚州精品天堂中文字幕| 欧美在线视频一区| 国产日韩精品一区二区| 国产精品白丝jk喷水视频一区| 中国人与牲禽动交精品| 国产精品99久久99久久久二8| 欧美中文字幕精品| 亚洲第一精品福利| 久久久精品美女| 亚洲国产精品久久久久久| 欧美成年人视频网站欧美| 一区二区三区回区在观看免费视频| 97视频在线看| 97视频色精品| 亚洲直播在线一区| 97精品一区二区三区| 久久躁日日躁aaaaxxxx| 国模私拍一区二区三区| 国产一区视频在线播放| 亚洲变态欧美另类捆绑| 欧美亚洲日本网站| 久久精品国产精品亚洲| 久久精品美女视频网站| 97久久伊人激情网| 日韩中文在线观看| 热草久综合在线| 国产精品av网站| 国产91色在线免费| 日本欧美一级片| 国产一区二区在线免费视频| 国产精品999999| 久久久欧美一区二区| 日韩在线观看电影| 亚洲国产欧美自拍| 欧美一级淫片videoshd| 国产精品一区久久| 亚洲国产精品va在线| 亚洲欧美国产精品久久久久久久| 国内自拍欧美激情| 日韩av影视在线| 精品国产乱码久久久久久虫虫漫画|