epoll总结

来源:互联网 发布:矩阵的幂运算法则 编辑:程序博客网 时间:2024/05/21 09:20

epoll:
http://www.man7.org/linux/man-pages/man7/epoll.7.html

recv/send:http://blog.csdn.net/petershina/article/details/7975798

ET/LT:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&id=4273856&uid=28541347

TCP_DEFER_ACCEPT:http://www.cnblogs.com/KevinT/p/3810824.html

描述符就绪条件(来源于UNPv1 P130):
这里写图片描述

三次握手(来源于深入理解Nginx P342):
这里写图片描述

/* Linux Kernel对于每一个epoll都会创建一个eventpoll结构体   epoll对于每一个事件都会创建一个epitem结构体,epitem是宿主,在epitem中寄宿了一棵红黑树和一个双向链表   红黑树保存了所有添加到epoll中的事件,当一个事件发生时,该事件会被添加到双向链表中 */struct rb_node {    unsigned long  __rb_parent_color;    struct rb_node *rb_right;    struct rb_node *rb_left;} __attribute__((aligned(sizeof(long))));struct rb_root {    struct rb_node *rb_node;};struct list_head {  struct list_head *next, *prev;};struct eventpoll {    spinlock_t lock;    struct mutex mtx;    wait_queue_head_t wq;    wait_queue_head_t poll_wait;    struct list_head rdllist; // rdllist.next指向双向链表    struct rb_root rbr; // rbr.rb_node指向红黑树    struct epitem *ovflist;    struct wakeup_source *ws;    struct user_struct *user;    struct file *file;    int visited;    struct list_head visited_list_link;};struct epitem {    union {        struct rb_node rbn; // 通过rbn组成一个红黑树        struct rcu_head rcu;    };    struct list_head rdllink; // 通过rdllink组成一个双向链表    struct epitem *next;    struct epoll_filefd ffd;    int nwait;    struct list_head pwqlist;    struct eventpoll *ep;    struct list_head fllink;    struct wakeup_source __rcu *ws;    struct epoll_event event; // epitem是事件的内核态表示,epoll_event是事件的用户态表示};typedef union epoll_data {    void *ptr;    int fd;    uint32_t u32;    uint64_t u64;} epoll_data_t;struct epoll_event {    uint32_t events;    epoll_data_t data;};// 创建一个epollint epoll_create(int size);// 向epoll中添加、修改、删除事件,监控fd上的eventint epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);// 收集epoll中已经发生的事件int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
// epoll程序基本框架for (;;) {    nfds = epoll_wait(epfd, events, 100, -1);    for (i = 0; i < nfds; ++i) {        if (events[i].data.fd == listen_sock) { // 监听套接字            conn_sock = accept(listen_sock, (struct sockaddr *) &cliaddr, &addrlen);            ev.events = EPOLLIN | EPOLLET;            ev.data.fd = conn_sock;            epoll_ctl(epfd, EPOLL_CTL_ADD, conn_sock, &ev);        } else if (events[i].events & EPOLLIN) { // 已连接套接字上的读事件            fd = events[i].data.fd;            ...        } else if (events[i].events & EPOLLOUT) { // 已连接套接字上的写事件            fd = events[i].data.fd;        } else {            ...        }    }}
原创粉丝点击