0% found this document useful (0 votes)
99 views

Libevent Overview

Synchronous I/O blocks a process until an I/O operation completes, making a program inefficient for handling multiple requests. Asynchronous I/O uses signals or POSIX aio to allow concurrent operations without blocking. I/O multiplexing with select/poll monitors multiple file descriptors but has scaling issues. Alternatives like epoll and kqueue provide more efficient monitoring. Libevent provides a portable way to use the best available option on different platforms.

Uploaded by

XYZ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
99 views

Libevent Overview

Synchronous I/O blocks a process until an I/O operation completes, making a program inefficient for handling multiple requests. Asynchronous I/O uses signals or POSIX aio to allow concurrent operations without blocking. I/O multiplexing with select/poll monitors multiple file descriptors but has scaling issues. Alternatives like epoll and kqueue provide more efficient monitoring. Libevent provides a portable way to use the best available option on different platforms.

Uploaded by

XYZ
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 11

Synchronous I/O

• An I/O call that does not return until it has completed or some
specified time limit has elapsed
• Also called Blocking I/O
• Examples:
• TCP connect()
• read() from a disk file
• recv() from a network socket
• gethostbyname() for DNS resolution
Synchronous I/O
• Synchronous I/O suffices when your program is very simple and has
got nothing else to do
• Keeps the code easy to understand

• Makes the program very inefficient if it needs to handle multiple I/O


requests.
Asynchronous I/O
• Asynchronous I/O can be achieved using:
• Signal driven I/O: using the SIGIO signal, or
• The POSIX aio interface
• The signal driven I/O tells the program when the I/O operation may be
initiated whereas the aio interface tells the program when the I/O
operation has completed.
• Signal driven I/O is also blocking in that sense since the process is blocked while
the data is copied to the user buffers.
• The aio interface is truly non-blocking since it copies the data to the user buffers
and only then notifies the process.
• The POSIX aio interface is not widely supported on different platforms.
Multi-Threading
• Another technique to handle multiple I/O requests is to create one
thread (or process) for every request.
• Each thread can then execute a blocking I/O call without blocking the
entire process.
• The problem with this naïve approach is that it doesn’t scale well
when the number of I/O requests or network connections grows to
tens of thousands.
• A slightly better approach is to have a thread pool wherein threads
are reused across multiple I/O requests.
• This still suffers from the fundamental thread scaling problem.
I/O Multiplexing
• Capability of being notified when any of several I/O conditions are
ready.
• Some typical scenarios where I/O multiplexing is used:
• When a client is handling interactive input and a network socket
• When a server is handling a listening socket and connected sockets
• When a server handles multiple services and/or protocols
• When an application needs to handle several types of events such as network
I/O, disk I/O, timers, signals, etc.
• Normally achieved using the select() or poll() interface
Limitations of select/poll
• Select and poll have performance limitations as the number of
monitored file descriptors grows large
• Aside from events occurring on open file descriptors, an application
may be interested in other kinds of events such as:
• Delivery of a signal
• Changes to a file in the file system
• Exiting of a process
• None of these other event notification mechanisms are efficiently
implemented.
Limitations of select/poll
• Poll and select require an application to pass in the entire list of
descriptors to be monitored for every call.
• This requires two memory copies:
• On call, the kernel copies the requested fd list from user memory to kernel
memory.
• On return, the kernel copies the active fd list from kernel memory to user
memory.
• For large fd lists where only a few of the fds are active at any given
time, most of the memory copies are unnecessary.
Limitations of select/poll
• Multiple passes over the descriptor list required:
• Kernel makes one pass to look for pending events
• If poll/select sleep, then on wakeup, the kernel makes another pass to record the
active descriptors
• User application makes one pass to determine the active descriptors.
• Each pass is an O(N) activity, where N is the number of descriptors – this
doesn't scale well.
• Kernel needs to allocate memory for large lists.
• The central problem is that poll/select are stateless by design, i.e., the
kernel does not remember the set of monitored descriptors between calls.
So what to do?
• Different operating systems have provided different alternatives to
select()
• Linux provides epoll()
• FreeBSD provides kqueue()
• These interfaces provide O(1) performance for adding/removing a file
descriptor or for determining which file descriptor is ready.
• But how do we write a portable application that provides high
performance?
Libevent
• The Libevent C library provides an abstraction that wraps all the
available interfaces and uses the most efficient implementation for a
given platform.
• Supports file descriptors, signals and timers.

You might also like