Use of new Linux APIs signalfd, timerfd, and eventfd

Source: Internet
Author: User
Tags epoll

Use of new Linux APIs signalfd, timerfd, and eventfd
Use of new Linux APIs signalfd, timerfd, and eventfd

Three new versions of fd added to Linux kernel:

Signalfd: 2.6.22

Timerfd: 2.6.25

Eventfd: 2.6.22

Three fd meanings:

Lsignalfd

The traditional method of signal processing is to register a signal processing function. Because the signal occurs asynchronously, it is necessary to solve the problem of Concurrent Data Access and re-import. Signalfd can abstract the signal into a file descriptor and read it when a signal occurs. In this way, the signal monitoring can be placed in the select, poll, epoll, and other listening queues.

Ltimerfd

The timer function can be implemented. The timer is abstracted as a file descriptor. When the timer expires, it can be read, which can also be placed in the main loop of the listener queue.

Leventfd

Event Notification between threads can also be used for user-mode and kernel communication. The buffer size of eventfd is sizeof (uint64_t). You can increment the value of this counter by writing to it. The read operation can be read and cleared. The eventfd can also be placed in the listening queue. When the counter is not 0, A readable event can be read.

All three new fd types can be monitored. When an event is triggered, a readable event occurs.

Signalfd involves APIs:

 
 
  1. #include
  2. int signalfd(int fd, const sigset_t *mask, int flags);

Parameter fd: if it is-1, it indicates creating a new one. If it is an existing one, it indicates modifying the signal associated with signalfd;

Parameter mask: Signal Set;

Parameter flag: the kernel version 2.6.27 and later support SFD_NONBLOCK and SFD_CLOEXEC;

The file descriptor is returned successfully. The returned fd supports the following operations: read, select (poll, epoll), close

L example


 
 
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include

  6. #define handle_error(msg) \
  7. do { perror(msg); exit(EXIT_FAILURE); } while (0)

  8. int main(int argc, char *argv[])
  9. {
  10. sigset_t mask;
  11. int sfd;
  12. struct signalfd_siginfo fdsi;
  13. ssize_t s;

  14. sigemptyset(&mask);
  15. sigaddset(&mask, SIGINT);
  16. sigaddset(&mask, SIGQUIT);

  17. if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
  18. handle_error("sigprocmask");

  19. sfd = signalfd(-1, &mask, 0);
  20. if (sfd == -1)
  21. handle_error("signalfd");

  22. for (;;) {
  23. s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
  24. if (s != sizeof(struct signalfd_siginfo))
  25. handle_error("read");

  26. if (fdsi.ssi_signo == SIGINT) {
  27. printf("Got SIGINT\n");
  28. } else if (fdsi.ssi_signo == SIGQUIT) {
  29. printf("Got SIGQUIT\n");
  30. exit(EXIT_SUCCESS);
  31. } else {
  32. printf("Read unexpected signal\n");
  33. }
  34. }
  35. }

L17-L21: Add signals of interest to sigset_t;

L24: Call signalfd to associate the signal set with fd. The first parameter-1 indicates creating a signalfd, not-1, and a valid signalfd indicates adding a new signal to it.

L29: blocks and reads the waiting signal. Based on the read result, you can know what signal has occurred.

Timerfd APIs

 
 
  1. #include
  2. int timerfd_create(int clockid, int flags);
  3. int timerfd_settime(int fd, int flags, const struct itimerspec *new_value,struct itimerspec *old_value);
  4. int timerfd_gettime(int fd, struct itimerspec *curr_value);

Timerfd_create: Create a timerfd. The returned fd can be read, select (poll, epoll), close

Timerfd_settime: set the timer cycle and start Interval

Timerfd_gettime: Get the expiration time.

 
 
  1. // The data structure in function parameters is as follows:
  2. Struct timespec
  3. {
  4. Time_t TV _sec;/* Seconds */
  5. Long TV _nsec;/* Nanoseconds */
  6. };
  7. Struct itimerspec
  8. {
  9. Struct timespec it_interval;/* Interval for periodic timer */
  10. Struct timespec it_value;/* Initial expiration */
  11. };

L example


  1. # Include
  2. # Include
  3. # Include
  4. # Include
  5. # Include
  6. # Include
  7. # Include /* Definition of uint64_t */

  8. # Define handle_error (msg )\
  9. Do {perror (msg); exit (EXIT_FAILURE);} while (0)

  10. Void printTime ()
  11. {
  12. Struct timeval TV;
  13. Gettimeofday (& TV, NULL );
  14. Printf ("printTime: current time: % ld. % ld", TV. TV _sec, TV. TV _usec );
  15. }

  16. Int main (int argc, char * argv [])
  17. {
  18. Struct timespec now;
  19. If (clock_gettime (CLOCK_REALTIME, & now) =-1)
  20. Handle_error ("clock_gettime ");

  21. Struct itimerspec new_value;
  22. New_value.it_value. TV _sec = now. TV _sec + atoi (argv [1]);
  23. New_value.it_value. TV _nsec = now. TV _nsec;
  24. New_value.it_interval. TV _sec = atoi (argv [2]);
  25. New_value.it_interval. TV _nsec = 0;

  26. Int fd = timerfd_create (CLOCK_REALTIME, 0 );
  27. If (fd =-1)
  28. Handle_error ("timerfd_create ");

  29. If (timerfd_settime (fd, TFD_TIMER_ABSTIME, & new_value, NULL) =-1)
  30. Handle_error ("timerfd_settime ");

  31. PrintTime ();
  32. Printf ("timer started \ n ");

  33. For (uint64_t tot_exp = 0; tot_exp <atoi (argv [3]);)
  34. {
  35. Uint64_t exp;
  36. Ssize_t s = read (fd, & exp, sizeof (uint64_t ));
  37. If (s! = Sizeof (uint64_t ))
  38. Handle_error ("read ");

  39. Tot_exp + = exp;
  40. PrintTime ();
  41. Printf ("read: % llu; total = % llu \ n", exp, tot_exp );
  42. }

  43. Exit (EXIT_SUCCESS );
  44. }


Code L25-L29: Initialize the timer parameter, the initial interval and timing interval.

L32: Create a timer fd, CLOCK_REALTIME: Real Time type. Modifying the clock will affect the timer; CLOCK_MONOTONIC: relative time type. Modifying the clock will not affect the timer.

L35: set the timer value.

L44: blocking and waiting for the timer to expire. The returned value is the number of unprocessed expiration times. For example, if the scheduled interval is 2 seconds but the read takes 10 seconds, the read value is 5.

Compile and run: The rt Library (g ++-lrt timerfd. cc-o timerfd) must be added during compilation)

[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] #

The first parameter 5 is the first timer expiration interval, the second parameter 2 is the timer interval, and the third parameter is the timer expiration 10 times, then exit. The program runs (5 + 2*10) S and exits.

For details, refer to man timerfd_create.

Eventfd involves APIs:

 
 
  1. #include
  2. int eventfd(unsigned int initval, int flags);

Create an eventfd, which is a counter-related fd. If the counter is not zero, a readable event occurs. After reading, the counter is cleared and the write counter is incremented. The returned fd can be operated as follows: read, write, select (poll, epoll), close.

This function creates an event object to implement the wait/notify mechanism between processes (threads. the kernel will maintain a 64-bit counter (uint64_t) for this object ). And use the first parameter (initval) to initialize the counter. When this function is called, a new file descriptor (event object) is returned ). Starting from 2.6.27, you can set the second parameter (flags) by bit ). You can use the following macros:

LEFD_NONBLOCK

The function is the same as O_NONBLOCK of open (2). The object is set to non-blocking. If this status is not set, read (2) read eventfd, when the counter value is 0, it is always blocked in the read call. If this flag is set, an EAGAIN error (errno = EAGAIN) is returned ). The effect is similar to the effect achieved by calling select (2.

LEFD_CLOEXEC

If this identifier is set, the file descriptor is automatically closed after exec is called to prevent leakage. For kernel 2.6.26 or earlier versions, flags must be set to 0.
After creating this object, you can perform the following operations on it:

1) write: add the 8-byte integer value written by the buffer to the kernel counter.

2) read: read the 8-byte value and reset the counter to 0. if the counter is 0 when read is called, if eventfd is blocked, read will always be blocked here; otherwise, an EAGAIN error will be returned. If the buffer length is less than 8, the read operation fails and the error code is set to EINVAL.

3) poll select epoll

4) close: You can call close when eventfd is not required. When all the handles of this object are closed, the kernel releases resources. Why is it released directly if it is not close? If you call fork to create
The process will copy the handle to the new process and inherit all States.

L example

 
 
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #define handle_error(msg) \
  8. do { perror(msg); exit(1); } while (0)
  9. int main( int argc, char **argv ){
  10. uint64_t u;
  11. ssize_t s;5 int j;
  12. if ( argc < 2 ) {
  13. fprintf(stderr, "input in command argument");
  14. exit(1);
  15. }

  16. int efd;
  17. if ( (efd = eventfd(0, EFD_NONBLOCK)) == -1 )
  18. handle_error("eventfd failed");


  19. switch (fork()) {
  20. case 0:
  21. for( j = 1; j < argc; j ++ ) {
  22. printf("Child writing %s to efd\n", argv[j] );

  23. u = strtoull(argv[j], NULL, 0); /* analogesly atoi */
  24. s = write(efd, &u, sizeof(uint64_t));/*append u to counter */
  25. if ( s != sizeof(uint64_t) )
  26. handle_error("write efd failed");

  27. }
  28. printf("child completed write loop\n");

  29. exit(0);
  30. default:
  31. sleep (2);

  32. printf("parent about to read\n");
  33. s = read(efd, &u, sizeof(uint64_t));
  34. if ( s != sizeof(uint64_t) ) {
  35. if (errno = EAGAIN) {
  36. printf("Parent read value %d\n", s);
  37. return 1;
  38. }
  39. handle_error("parent read failed");
  40. }
  41. printf("parent read %d , %llu (0x%llx) from efd\n",
  42. s, (unsigned long long)u, (unsigned long long) u);
  43. exit(0);

  44. case -1:
  45. handle_error("fork ");
  46. }
  47. return 0;
  48. }

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.