WiFiDog Source Analysis Lighttpd1.4.20 Source Code Analysis Fdevent System (1)---fdevents structure and fdevent system external interface

Source: Internet
Author: User

In front of the LIGHTTPD plug-in system, this article will take a look at the lighttpd in the fdevent system. Fdevent system mainly handles various IO events, in the Web server, the main is to write data to the socket and read data from the socket. Typically, a Web server is an IO-intensive program, which requires that the Web server be able to perform well on the data read and write, and that it will not cause the other sockets to be blocked because of the blocking of one socket, otherwise the performance of the server can be greatly reduced. As a result, most Web servers use non-blocking IO to read and write data. LIGHTTPD uses an object-oriented approach like OO to encapsulate the processing of IO events through the fdevent system, providing a unified interface for different IO systems.
The LIGHTTPD uses the so-called reactor mode, which is non-blocking IO plus multiplexing (non-blocking io + io multiplexing). On multiplexing, lighttpd encapsulates a variety of implementations through fdevent. The LIGHTTPD uses several of the following multi-channel IO:

The following is a look at the fdevents structure in Fdevent.h, which is equivalent to a virtual base class, where the function pointer is a pure virtual function. For each implementation, it is equivalent to inheriting the base class and implementing the pure virtual function, i.e. assigning a function address value to the function pointer. Here's the code:

typedefstructfdevents{fdevent_handler_t type;//multi-Channel IO typeFdnode **fdarray;//file Descriptor Arraysize_t Maxfds;//Maximum number of file descriptors#ifdef Use_linux_sigiointIn_sigio; intSignum;    sigset_t Sigset;    siginfo_t Siginfo; Bitset*Sigbset;#endif#ifdef Use_linux_epollintepoll_fd; structEpoll_event *epoll_events;#endif#ifdef Use_pollstructPOLLFD *pollfds;//struct-body array of descriptors and their statessize_t size;//the number of data in the arraysize_t used;//the size of the array//used to store the location used in the Pollfds. //due to possible deletions, there is an empty file in the Pollfds, which//index exists in unused, making it easy to use these slots directly for the next insert Operation//reduce the waste of space. Buffer_int unused; #endif#ifdef Use_select//three set of file descriptorsFd_set Select_read;//readable, corresponds to fdevent_inFd_set Select_write;//Writable , corresponds to Fdevent_outFd_set Select_error;//in exceptional condition, corresponding to Fdevent_err//because the Select function modifies the above three sets,//Therefore, an initial copy is saved here. Fd_set Select_set_read;    Fd_set Select_set_write;    Fd_set Select_set_error; intSELECT_MAX_FD;//the maximum number of file descriptors.  #endif#ifdef Use_solaris_devpollintdevpoll_fd; structPOLLFD *Devpollfds;#endif#ifdef Use_freebsd_kqueueintkq_fd; structKevent *Kq_results; Bitset*kq_bevents;#endif#ifdef Use_solaris_portintport_fd;#endif    //A unified operating interface that corresponds to a subsequent function declaration.      int(*reset) (structFdevents *ev); void(* Free) (structFdevents *ev); int(*event_add) (structfdevents * EV,intFde_ndx,intFdintevents); int(*event_del) (structfdevents * EV,intFde_ndx,intFD); int(*event_get_revent) (structFdevents *ev, size_t ndx); int(*EVENT_GET_FD) (structFdevents *ev, size_t ndx); int(*EVENT_NEXT_FDNDX) (structfdevents * EV,intndx); int(*poll) (structfdevents * EV,intTimeout_ms); int(*fcntl_set) (structfdevents * EV,intFD);} fdevents;

You can see that there are a lot of macros in this struct, this is to get rid of the unused variables at compile time, and customize the structure according to the multi-channel IO system currently in use.
The first member of the struct is an enumeration type fdevent_handler_t, which is defined as follows:

typedefenum{fdevent_handler_unset,//Not definedFdevent_handler_select,//SelectFdevent_handler_poll,//PollFdevent_handler_linux_rtsig,//RtsigFdevent_handler_linux_sysepoll,//SysepollFdevent_handler_solaris_devpoll,//DevpollFdevent_handler_freebsd_kqueue,//KqueueFdevent_handler_solaris_port//Port} fdevent_handler_t;

This enumeration type marks all possible multi-channel IO systems.
The second member of the struct, Fdnode **fdarray, is an array of fdnode type variables. Fdnode is defined as follows:

struct _fdnode{    // handle function pointer    void *ctx;                // Context of the file descriptor    int fd;                  // File Descriptor    struct // Pointer } Fdnode;

Fdevent_handler handler is a function pointer used to store the address of this descriptor handler function. For this address, the following article will be described in detail, which is defined as TypeDef handler_t (*fdevent_handler) (void *srv, void *ctx, int revents);. As can be seen from the last two variables, this should be a node of a linked list, but the structure is stored as an array, that is, the Fdarray variable in fdevents, which can improve the efficiency of the query.
The variables that are later wrapped by macros are variables defined for each of the different multi-channel IO systems. Let's take a look at the variables used by Epoll under Linux:

#ifdef use_linux_epoll      int // Epoll_create The returned descriptor     struct epoll_event *epoll_events; // save FD and corresponding events #endif

Here is a description of the variable Buffer_init unused used by poll. The type of this variable is defined as follows:

struct {    int *ptr;         // an array of positional indexes.     size_t used;     // the number of data in the array.     size_t size;     // The array length. } buffer_int;

is actually an int array, just encapsulated a bit, adding two properties. The unused array holds the subscript value of the Pollfds. In the following implementation we can see that Pollfds is an array of struct POLLFD types, note that it is not an array of pointers of this type. The size of this array is determined by the value of the Maxfds in Fdevents, and the space of the array is allocated once during initialization. Because the POLLFDS array has operations to delete elements, it leaves "holes" in the array, and UNUNSD is the subscript value that stores the "holes", so that you can quickly find the position when inserting the element. This is a useful technique for improving the efficiency of the data by repeatedly deleting the insert element operation. In most cases, the stack list is used to store the subscript for these available spaces, and the top of the stack points to the list header.
The rest of the variable readers can analyze themselves.
Next look at these function pointers. These function pointers correspond to a series of function declarations following the definition of the struct body. The correspondence can be easily seen from the name.

/** Reset and release the Fdevent system. */intFdevent_reset (Fdevents *ev);voidFdevent_free (Fdevents *ev);/** Add FD to the FD event system. Events is the event to be monitored for FD. * Fde_ndx is a pointer to the subscript value of FD corresponding to the Fdnode in Ev->fdarray. * If fde_ndx==null, it means adding FD to the FD event system. If it is not NULL, it means that the FD is already present in the system, and the function becomes the event that will listen to the FD. */intFdevent_event_add (fdevents * ev,int*fde_ndx,intFdintevents);/** Remove FD from the FD event system. The content of the FDE_NDX is consistent with the above. */intFdevent_event_del (fdevents * ev,int*fde_ndx,intFD);/** Returns the event that occurs with the ndx corresponding to FD. * The NDX here is different from the fde_ndx above, and this ndx is the subscript of the epoll_event structure in ev->epoll_events. * When first called, usually Ndx is-1. * This ndx is not related to its corresponding FD. and fde_ndx equals its corresponding FD. */intFdevent_event_get_revent (Fdevents *ev, size_t ndx);/** Returns the FD corresponding to the NDX. */intFDEVENT_EVENT_GET_FD (Fdevents *ev, size_t ndx);/** Returns the next occurrence of the IO event in FD. */intFDEVENT_EVENT_NEXT_FDNDX (fdevents * ev,intndx);/** Start waiting for IO event. Timeout_ms is a timeout limit. */intFdevent_poll (fdevents * ev,intTimeout_ms);/** * Set the state of FD, usually set to run exec in child process shutdown and non-blocking. */intFdevent_fcntl_set (fdevents * ev,intFD);

In the fdevent.c file, the implementation of these functions is basically a simple call to the corresponding function pointer in the fdevents struct. For LIGHTTPD, the processing of IO events is accomplished by invoking these functions above, and LIGHTTPD does not know or care about the exact person who handled the events.
The remaining function declarations:

/** Returns the address of the event handler corresponding to the FD. That is, the value of handler in Fdnode. */Fdevent_handler Fdevent_get_handler (fdevents* EV,intFD);/** Returns the corresponding environment for FD. That is the value of CTX in Fdnode. */void*fdevent_get_context (fdevents * ev,intFD);/** Registration and cancellation of FD. * is to generate a fdnode and then save it in Ev->fdarray. or delete it. */intFdevent_register (fdevents * ev,intFD, Fdevent_handler handler,void*ctx);intFdevent_unregister (fdevents * ev,intFD);/** * Initialize various multi-channel IO. */intFdevent_select_init (Fdevents *ev);intFdevent_poll_init (Fdevents *ev);intFdevent_linux_rtsig_init (Fdevents *ev);intFdevent_linux_sysepoll_init (Fdevents *ev);intFdevent_solaris_devpoll_init (Fdevents *ev);intFdevent_freebsd_kqueue_init (fdevents * ev);

Here's a summary:
A series of functions declared in the file fdevent.h is the external interface of the fdevent system, which is equivalent to the public function of the class. LIGHTTPD implements the processing of IO events by invoking these functions. The concrete implementation of these functions simply calls the function pointers in the fdevents struct. The function pointers are defined in the. c file that begins with Fdevent_. The corresponding IO system can be seen from the names of these files. In these files, the function is mostly static, which is the function of the class and private functions to hide the effect of the concrete implementation. We will specifically analyze the use of a multi-channel IO system in the following questions.
The lighttpd author is very good at fdevent system encapsulation, which is very helpful for understanding the object-oriented approach to programming in C.
In the next section, we will take a look at the initialization and use of the fdevent system.

This article by http://www.wifidog.pro/2015/04/20/wifidog%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90lighttpd%E5%AF%B9%E5%A4%96%E6 %8e%a5%e5%8f%a3.html compilation, reprint please indicate the source



WiFiDog Source Analysis Lighttpd1.4.20 Source Code Analysis Fdevent System (1)---fdevents structure and fdevent system external interface

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.