Linux 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;
};
 
// 创建一个epoll
int epoll_create(int size);
 
// 向epoll中添加、修改、删除事件,监控fd上的event
int 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 {
            ...
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值