Linux new API Signalfd, TIMERFD, eventfd usage Instructions _linux

Source: Internet
Author: User
Tags data structures epoll readable

Three new versions of FD added to the Linux kernel:

signalfd:2.6.22

timerfd:2.6.25

eventfd:2.6.22

The significance of three kinds of FD:

Lsignalfd

The traditional way of processing signals is to register the signal processing function, because the signal is asynchronous, to solve the data concurrent access, you can back into the problem. SIGNALFD can abstract a signal into a file descriptor that can be read when a signal occurs, so that the listener can be placed in a listening queue such as SELECT, poll, Epoll, and so on.

Ltimerfd

Timer can be implemented, the timer is abstracted as a file descriptor, when the timer expires can be read, it can also be placed in the main loop of the listening queue.

Leventfd

Implements event notification between threads, and can also be used for user state and kernel communication. The buffer size of the EVENTFD is sizeof (uint64_t), and the write can increment this counter, read operation readable, and clear 0, EVENTFD can also be placed in the listening queue, when the counter is not 0 o'clock, there are readable events occur, you can read.

Three new fd can be monitored, and when events are triggered, readable events occur.

SIGNALFD involves APIs:

Click (here) to collapse or open

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

Parameter FD: If-1 means the new one, and if it is an existing one, it means modifying the signal associated with the SIGNALFD;

Parameter mask: signal set;

Parameter flag: Kernel version 2.6.27 later support Sfd_nonblock, sfd_cloexec;

Successfully returns the file descriptor, the returned FD supports the following actions: Read, select (poll, Epoll), close

L Examples

#include <sys/signalfd.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #includ  E <stdio.h> #define HANDLE_ERROR (msg) \ Do {perror (msg); exit (exit_failure); a 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: Add the signal of interest to the sigset_t;

L24: Call SIGNALFD, associate the signal set with FD, the first argument is-1 to create a new SIGNALFD, not-1 and is a legitimate signalfd to add a new signal to it.

L29: Blocks the wait signal from occurring and reads. According to the results of the reading can know what the signal occurred.

TIMERFD the API involved

#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: Create a timerfd; The returned FD can do the following: Read, select (poll, Epoll), close timerfd_settime: Set timer cycle, and start interval timerfd
_gettime: Gets the expiration time. 
The data structures in the function parameters are as follows: 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 */}; 
The data structures in the function parameters are as follows: 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 Example

#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 (&AMP;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> #includ E <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 (&AMP;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); }

Code l25-l29: Initializes the timer's parameters, the initial interval and the timing interval.

L32: Create timer Fd,clock_realtime: Real time type, change clock will affect timer; Clock_monotonic: Relative time type, change clock does not affect timer.

L35: Sets the value of the timer.

L44: Blocking wait timer expires. The return value is the unhandled expiration number. For example, the timer interval is 2 seconds, but after 10 seconds to read, the read value is 5.

Compile run: Add RT Library at compile time (g++-lrt timerfd.cc-o timerfd)

[Root@localhost apptest]#./TIMERFD 5 2
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]#

The first parameter 5 is the first timer expiration interval, the second parameter 2 is the interval of the timer, and the third parameter is the timer expires 10 times to exit. Program run (5+2*10) s exits.

More information can be: Man timerfd_create

EVENTFD involves APIs:

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

Create a eventfd, this is a counter-related FD, the counter is not zero is a readable event occurs, read after the counter clear zero, write increment counter; The returned FD can do the following: Read, write, select (poll, Epoll), Close

This function creates an event object (Eventfd object) to implement the Wait/notify (wait/notify) mechanism between processes (threads). The kernel maintains a 64-bit counter (uint64_t) for this object. And initializes the counter with the first argument (Initval). Calling this function returns a new file descriptor (event object). The 2.6.27 version begins with a bitwise setting of the second parameter (flags). Some of the following macros can be used:

Lefd_nonblock

function with open (2) O_nonblock, set the object is non-blocking, if not set this state, read (2) reading EVENTFD, and the counter value of 0 has been blocked in the read call, if you set this flag, you will return a eagain error (errno = Eagain). The effect is also the same as an extra call to select (2).

Lefd_cloexec

When this identity is set, calling exec automatically closes the file descriptor to prevent leaks. If it is a 2.6.26 or previous version of the kernel, the flags must be set to 0.
After you create this object, you can do the following:

1 Write: Add the 8-byte shaping value of the buffer to the kernel counter.

2 read: Reads 8 byte value, and resets the counter to 0. If you call read when the counter is 0, if the EVENTFD is blocked, read blocks here, otherwise you get a eagain error. If the buffer length is less than 8 then read will fail with the error code set to Einval.

3) Poll Select Epoll

4 Close: When you do not need to EVENTFD, you can call closing, when all the handles of this object are closed, the kernel releases resources. Why not close and just release it if you call fork to create
The process copies the handle to the new process and inherits all the states.

L Examples

#include <sys/eventfd.h> #include <unistd.h> #include <stdio.h> #include <stdint.h> #include & lt;stdlib.h> #include <errno.h> #define HANDLE_ERROR (msg) \ Do {perror (msg); exit (1); a 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"); Exi
T (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 (ar GV[J], NULL, 0); /* analogesly atoi/s = Write (EFD, &u, sizeof (uint64_t))/*append u to counter */if (s!= sizeof (uint64_t)) Handl
E_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 & lt;stdlib.h> #include <errno.h> #define HANDLE_ERROR (msg) \ Do {perror (msg); exit (1); a 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"); Exi
T (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 (ar GV[J], NULL, 0); /* analogesly atoi/s = Write (EFD, &u, sizeof (uint64_t))/*append u to counter */if (s!= sizeof (uint64_t)) Handl
E_error ("Write EFD failed");
printf ("Child completed write loop\n");
Exit (0);
DefaultSleep (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; }

The above is a small set to introduce the new Linux API Signalfd, TIMERFD, eventfd use instructions, hope to help everyone, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.