- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Linux 新的API signalfd、timerfd、eventfd使用说明由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
三种新的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:
点击(此处)折叠或打开 。
1
2
3
4
|
#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例子 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#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 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#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)、close
timerfd_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例子 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#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) 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[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]
#
|
第一个参数5为第一次定时器到期间隔,第二个参数2为定时器的间隔,第三个参数为定时器到期10次则退出。程序运行(5+2*10)S退出.
详细信息可以:man timerfd_create 。
eventfd涉及API:
1
2
3
4
|
#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例子 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#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使用说明,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
最后此篇关于Linux 新的API signalfd、timerfd、eventfd使用说明的文章就讲到这里了,如果你想了解更多关于Linux 新的API signalfd、timerfd、eventfd使用说明的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我已经设置了 Azure API 管理服务,并在自定义域上配置了它。在 Azure 门户中 API 管理服务的配置部分下,我设置了以下内容: 因为这是一个客户端系统,我必须屏蔽细节,但以下是基础知识:
我是一名习惯 React Native 的新程序员。我最近开始学习 Fetch API 及其工作原理。我的问题是,我找不到人们使用 API key 在他们的获取语句中访问信息的示例(我很难清楚地表达有
这里有很多关于 API 是什么的东西,但是我找不到我需要的关于插件 API 和类库 API 之间的区别。反正我不明白。 在 Documenting APIs 一书中,我读到:插件 API 和类库 AP
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我正在尝试找出设计以下场景的最佳方法。 假设我已经有了一个 REST API 实现,它将从不同的供应商那里获取书籍并将它们返回给我自己的客户端。 每个供应商都提供单独的 API 来向其消费者提供图书。
请有人向我解释如何使用 api key 以及它有什么用处。 我对此进行了很多搜索,但得到了不同且相互矛盾的答案。有人说 API key 是保密的,它从不作为通信的一部分发送,而其他人则将它发送给客户端
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 4年前关闭。 Improve this
谁能告诉我为什么 WSo2 API 管理器不进行身份验证?我已经设置了两个 WSo2 API Manager 1.8.0 实例并创建了一个 api。它作为原型(prototype) api 工作正常。
我在学习 DSL 的过程中遇到了 Fluent API。 我在流利的 API 上搜索了很多……我可以得出的基本结论是,流利的 API 使用方法链来使代码流利。 但我无法理解——在面向对象的语言中,我们
基本上,我感兴趣的是在多个区域设置 WSO2 API 管理器;例如亚洲、美国和欧洲。一些 API 将部署在每个区域的数据中心内,而其他 API 将仅部署在特定区域内。 理想情况下,我想要的是一个单一的
我正在构建自己的 API,供以下用户使用: 1) 安卓应用 2) 桌面应用 我的网址之一是:http://api.chatapp.info/order_api/files/getbeers.php我的
我需要向所有用户显示我的站点的分析,但使用 OAuth 它显示为登录用户配置的站点的分析。如何使用嵌入 API 实现仪表板但仅显示我的网站分析? 我能想到的最好的可能性是使用 API key 而不是客
我正在研究大公司如何管理其公共(public) API。我想到的是拥有成熟 API 的公司,例如 Google、Facebook、Twitter 和 Amazon。 这些公司向公众公开了许多不同的 A
在定义客户可访问的 API 时,以下是首选的行业惯例: a) 定义一组显式 API 方法,每个方法都有非常狭窄和特定的目的,例如: SetUserName SetUserAge Se
这在本地 deserver 和部署时都会发生。我成功地能够通过留言簿教程使用 API 资源管理器,但现在我已经创建了自己的项目并尝试访问我编写的第一个 API,它从未出现过。搜索栏旁边的黄色“正在加载
我正在尝试使用 http://ip-api.com/ api通过我的ip地址获取经度和纬度。当我访问 http://ip-api.com/json从我的浏览器或使用 curl,它以 json 格式返回
这里的典型示例是 Twitter 的 API。我从概念上理解 REST API 的工作原理,本质上它只是针对您的特定请求向他们的服务器查询,然后您会在其中收到响应(JSON、XML 等),很棒。 但是
我能想到的最好的标题,但要澄清的是,情况是这样的: 我正在开发一种类似短 url 的服务,该服务允许用户使用他们的 Twitter 帐户“登录”并发布内容。现在这项服务可以包含在 Tweetdeck
我正在设计用于管理评论和讨论线程的 API 方案。我想有一个点 /discussions/:discussionId 当您GET 时,它会返回一组评论和一些元数据。评论也许可以单独访问 /discus
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭去年。 Improve this quest
我是一名优秀的程序员,十分优秀!