nginx数据读取

2018-10-27  本文已影响9人  msrpp

上篇说到nginx会分裂出若干个子进程来接受客户端请求。每个进程是竞争关系,谁抢到了连接事件谁来处理。网络模型和之前分析redis的实现是一样的,mac下是kqueue。当时没有仔细记录,现在记录一下kqueue的情况。

kqueue参数说明

kqueue 一共有如下三个函数:


int     kqueue(void);
int     kevent(int kq, 
           const struct kevent *changelist, int nchanges,
           struct kevent *eventlist, int nevents,
           const struct timespec *timeout);
int     kevent64(int kq,
         const struct kevent64_s *changelist, int nchanges,
         struct kevent64_s *eventlist, int nevents,
         unsigned int flags, 
         const struct timespec *timeout);

kevent64函数redis和nginx中都没有涉及,应该是event的扩展版本先略过。

1.kq 即kqueue函数返回的文件描述符。

2.需要变更的event事件,我们看一下这个kevent结构体,参数含义为 ident:socket文件描述符, filter:代表了对应什么事件被触发了,socket编程中我们通常取值 EVFILT_READ和EVFILT_WRIT,flags增删事件时使用,取值为EV_ADD/EV_DELETE/EV_ENABLE/EV_DISABLE,前两个已经可以满足我们使用需要. fflagsdata,用的不多,填0和null;udata,用户数据。


struct kevent {
    uintptr_t   ident;      /* identifier for this event */
    int16_t     filter;     /* filter for event */
    uint16_t    flags;      /* general flags */
    uint32_t    fflags;     /* filter-specific flags */
    intptr_t    data;       /* filter-specific data */
    void        *udata;     /* opaque user data identifier */
};

3.nchanges changelist的个数。

4.eventlist 读取kqueue中事件时使用,返回事件数组。

5.nevents 最大读取数量。

6.timeout 等待时间,如果填null则是无限时间。

7.返回值 读取到的事件数量。

kqueue使用举例伪代码

int kq = kqueue();

int fd = newServerSocket();

kevent ke;

ke.ident=fd;
ke.filter=EVFILT_WRIT&EVFILT_READ;
ke.flags=EV_ADD;
kevent(kq,&ke,1,null,0,null);//添加到kq中。
...
kevent* lst;
int event_num = kevent(kq,null,0,lst,max_recv_num=512,0);
for(kevent ke:lst){
    Onevent(event.fd);//doAccept or doRead ...
}

每个socket发生的事件,我们可以在外部维护一个socket文件描述符到处理read和write事件函数的映射关系,比如redis。 我们也可以采取nginx的处理方式,将处理函数放到udata中由kqueue保存。

上一篇下一篇

猜你喜欢

热点阅读