A popular understanding of Epoll

Source: Internet
Author: User
Tags epoll

First we define the concept of a stream, a stream can be a kernel object that can be used for I/O operations, such as files, Socket,pipe, and so on. Whether it's a file, a socket, or a pipe, we can think of them as a stream.

Now we'll talk about the I/O operation, and by reading we can read the data from the stream, and by writing we can write the data to the stream. Now suppose a situation, we need to read the data from the stream, but there is no data in the stream, (typically, the client will read the data from the socket, but the server has not yet sent back the data), what to do.

Blocking: What is the concept of blocking? For example, some time you are waiting for the courier, but you do not know when the courier to come over, and you have nothing else to do (or the next thing you have to wait for the courier to do); then you can go to bed because you know that the courier will give you a call when the goods are delivered (assuming that you will be woken).

Non-blocking busy polling: Then the above examples of express, if you use a busy polling method, then you need to know the Courier mobile phone number, and then give him a call every minute: "You have arrived." ”

It is obvious that the general people do not use the second approach, not only significantly no brain, waste of money, but also occupied a large number of courier time.

Most programs do not use the second approach, because the first method is economical and simple, the economy refers to the consumption of very little CPU time, if the thread sleep, it fell out of the system scheduling queue, not to carve up the CPU precious time slice.

To understand how blocking is done, we'll talk about buffers, and kernel buffers, which eventually explain the I/O events. The introduction of buffers is to reduce frequent I/O operations caused by frequent system calls (you know it is very slow), when you operate a stream, more of the buffer as a unit of operation, which is relative to user space. For the kernel, a buffer is also required.

Suppose there is a pipe, process A is the writer of the pipe, B is the readout side of the pipe. The first kernel buffer is empty, B as read out side, blocked. Then first A to the pipe, when the kernel buffer from the empty state to the Non-null state, the kernel will produce an event to tell B to wake up, this event is called "Buffer non-empty." However, after the "buffer is not empty" event notification B, B has not yet read the data; and the kernel promises not to throw the data in the pipeline out of this time, the data written by a will stay in the kernel buffer, and if the kernel is full, B still does not start reading the data, and the final kernel buffer will be filled, which will result in an I /o event, tell process A, you should wait (block), we define this event as "buffer full". Then B finally began to read the data, so the kernel of the buffer empty out, this time the kernel will tell a, the kernel buffer has a vacancy, you can wake up from the rest, continue to write the data, we call this event "buffer is not full." Perhaps the event "buffer is not full" has notified a, but a also has no data to write, while B continues to read the data to know that the kernel buffer is empty. This time the kernel tells B that you need to block. , we set this time as "buffer null".

These four scenarios cover four I/O events, buffer full, buffer null, buffer non-empty, buffer not full (note is the kernel buffer, and these four terms are all sporogenous, only to explain its rationale). These four I/O events are the root of blocking synchronization. (If you don't understand what "sync" is, learn about the operating system's locks, semaphores, condition variables, and other tasks such as synchronization).

Then we say the disadvantage of blocking I/O: in blocking I/O mode, a thread can handle only one stream of I/O events. If you want to process multiple streams simultaneously, either multiple processes (fork), or multithreading (pthread_create), unfortunately both methods are not efficient.

Now that we think about the I/O of non-blocking busy polling, we find that we can handle multiple streams at the same time (switching a stream from blocking mode to non-blocking mode is not discussed):

[Java] view plain copy print? While true {to I in stream[]; {If I has data read until unavailable}}

While true {to
    I in stream[]; {
        If I has data
            read until unavailable
    }
}

We just have to go through all the flow and start from the beginning, so we can handle multiple streams. But this is obviously not good, because if all streams have no data, it will only waste the CPU. To add, in blocking mode, the kernel's handling of I/O events is blocked or awakened, while in non-blocking mode the I/O events are handed over to other objects (the Select and Epoll described later) and even directly ignored.

In order to avoid CPU idling, you can introduce a proxy (at first there is a proxy named Select, and then another agent called poll, but the essence of the two is the same). This agent is more powerful, can observe many streams of I/O events at the same time, in the idle time, the current thread will be blocked, when one or more streams have I/O events, the wake up from the blocking state, so our program will poll all the flow (so we can remove the "busy" word). Code length like this:

[Java] view plain copy print? While true {select (streams[]) to I in streams[] {if I has data read until Unavailab Le}}

While true {
    select (streams[]) to
    I in streams[] {
        If I has data
            read until unavailable
    }
}

As a result, if no I/O events are generated, our program will block at the Select. But there's still a problem, we just know from the select that there is an I/O event happening, but do not know is that several streams (there may be one, many, even all), we can only have no difference polling all the streams, to find the data can be read or written to the stream, to operate on them.

But with SELECT, we have the no differential polling complexity of O (n), and the more streams we handle, the longer each differential polling time is. Again

Said so much, finally can explain Epoll, epoll can be understood as event poll, different from busy polling and no differential polling, Epoll will have which stream what happened I/O events notify us. At this point our operations on these streams are meaningful. (Reduction of Complexity to O (1))

Before we discuss the implementation details of Epoll, we'll list the relevant actions of Epoll:

Epoll_create Create a Epoll object, general EPOLLFD = Epoll_create ()

Epoll_ctl (Epoll_add/epoll_del) to add/Remove an event from a stream to a Epoll object, such as:

Epoll_ctl (EPOLLFD, Epoll_ctl_add, Socket, Epollin).//register buffer not NULL event, that is, there is data inflow

Epoll_ctl (EPOLLFD, Epoll_ctl_del, Socket, epollout)//register buffer is not full event, that is, the stream can be written

Epoll_wait (EPOLLFD,...) Wait until the registered event occurs

(note: When a buffer full or buffer is empty for read/write to a non-blocking stream, Write/read returns-1 and sets Errno=eagain.) The Epoll only cares about buffer non-full and buffer non-empty events.

The code for a epoll pattern might look like this:

[Java] view plain copy print?       While true {active_stream[] = epoll_wait (EPOLLFD) to I in active_stream[] {read or write till }   }

While true {
    active_stream[] = epoll_wait (EPOLLFD) to
    I in active_stream[] {
        read or write till
    }
}

Limited to space, I only say so much to reveal the original rationality of things, as for the use details of Epoll, please refer to man and Google for implementation details, see Linux kernel source.

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.