美文网首页
nginx数据读取

nginx数据读取

作者: msrpp | 来源:发表于2018-10-27 18:58 被阅读9次

    上篇说到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的扩展版本先略过。

    • int kqueue(void); 返回一个kqueue文件描述符。

    • int kevent(...) 参数中带指针的是输出参数,其他为输入参数,kevent函数的功能有3个:(1)向kqueue中添加监听事件(2)从kqueue中删除监听事件(3)读取kqueue中的事件。下面解释一下各个参数的含义:

    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保存。

    相关文章

      网友评论

          本文标题:nginx数据读取

          本文链接:https://www.haomeiwen.com/subject/hnzqtqtx.html