欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2016年10月25日 10:18:38   投稿:mrr  
這篇文章主要介紹了Linux 新的API signalfd、timerfd、eventfd使用說明的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下

三種新的fd加入linux內(nèi)核的的版本:

signalfd:2.6.22

timerfd:2.6.25

eventfd:2.6.22

三種fd的意義:

lsignalfd

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

ltimerfd

可以實現(xiàn)定時器的功能,將定時器抽象為文件描述符,當(dāng)定時器到期時可以對其read,這樣也可以放到監(jiān)聽隊列的主循環(huán)中。

leventfd

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

三種新的fd都可以進行監(jiān)聽,當(dāng)有事件觸發(fā)時,有可讀事件發(fā)生。

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);

參數(shù)fd:如果是-1則表示新建一個,如果是一個已經(jīng)存在的則表示修改signalfd所關(guān)聯(lián)的信號;

參數(shù)mask:信號集合;

參數(shù)flag:內(nèi)核版本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:調(diào)用signalfd,把信號集與fd關(guān)聯(lián)起來,第一個參數(shù)為-1表示新建一個signalfd,不是-1并且是一個合法的signalfd表示向其添加新的信號。

L29:阻塞等待信號的發(fā)生并讀取。根據(jù)讀取的結(jié)果可以知道發(fā)生了什么信號。

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:創(chuàng)建一個timerfd;返回的fd可以進行如下操作:read、select(poll、epoll)、close
timerfd_settime:設(shè)置timer的周期,以及起始間隔
timerfd_gettime:獲取到期時間。
//函數(shù)參數(shù)中數(shù)據(jù)結(jié)構(gòu)如下: 
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 */ 
};
//函數(shù)參數(shù)中數(shù)據(jù)結(jié)構(gòu)如下: 
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:初始化定時器的參數(shù),初始間隔與定時間隔。

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

L35:設(shè)置定時器的值。

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

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

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

第一個參數(shù)5為第一次定時器到期間隔,第二個參數(shù)2為定時器的間隔,第三個參數(shù)為定時器到期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);

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

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

lEFD_NONBLOCK

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

lEFD_CLOEXEC

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

1) write: 將緩沖區(qū)寫入的8字節(jié)整形值加到內(nèi)核計數(shù)器上。

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

3) poll select epoll

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

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使用說明,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 詳解linux系統(tǒng)下pid的取值范圍

    詳解linux系統(tǒng)下pid的取值范圍

    這篇文章主要介紹了詳解linux系統(tǒng)下pid的取值范圍的相關(guān)資料,需要的朋友可以參考下
    2018-07-07
  • 利用lynis如何進行l(wèi)inux漏洞掃描詳解

    利用lynis如何進行l(wèi)inux漏洞掃描詳解

    這篇文章主要給大家介紹了關(guān)于利用lynis如何進行l(wèi)inux漏洞掃描的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • linux下安裝php擴展memcache的方法

    linux下安裝php擴展memcache的方法

    這篇文章主要介紹了linux下安裝php擴展memcache的方法,需要了解的朋友可以參考下
    2015-07-07
  • Centos 7系統(tǒng)虛擬機橋接模式詳解

    Centos 7系統(tǒng)虛擬機橋接模式詳解

    這篇文章主要給大家介紹了關(guān)于Centos 7系統(tǒng)虛擬機橋接模式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • CentOS7掛載新數(shù)據(jù)盤的完整步驟

    CentOS7掛載新數(shù)據(jù)盤的完整步驟

    這篇文章主要給大家介紹了關(guān)于CentOS7掛載新數(shù)據(jù)盤的完整步驟,文中通過示例代碼將實現(xiàn)的步驟介紹的非常詳細,對大家學(xué)習(xí)或者使用CentOS7具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 詳解Ubuntu16.04啟動器圖標異常解決方法

    詳解Ubuntu16.04啟動器圖標異常解決方法

    本篇文章主要介紹了詳解Ubuntu16.04啟動器圖標異常解決方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 讓Apache支持cgi、SSI、shtml的配置方法

    讓Apache支持cgi、SSI、shtml的配置方法

    配置Apache支持cgi、SSI、shtml,供大家學(xué)習(xí)參考
    2013-02-02
  • CentOS 6.5 web服務(wù)器apache的安裝與基本設(shè)置

    CentOS 6.5 web服務(wù)器apache的安裝與基本設(shè)置

    這篇文章主要介紹了CentOS 6.5 web服務(wù)器apache的安裝與基本設(shè)置,需要的朋友可以參考下
    2017-09-09
  • Linux文件刪除后空間未釋放問題詳解

    Linux文件刪除后空間未釋放問題詳解

    這篇文章主要給大家介紹了關(guān)于Linux文件刪除后空間未釋放問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Linux具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Linux中文本處理工具之sort命令詳解

    Linux中文本處理工具之sort命令詳解

    sort命令的功能是對文件中的各行進行排序。sort命令有許多非常實用的選項,這些選項最初是用來對數(shù)據(jù)庫格式的文件內(nèi)容進行各種排序操作的。下面這篇文章主要給大家介紹了Linux中文本處理工具之sort命令的相關(guān)資料,需要的朋友可以參考下。
    2017-03-03

最新評論