zoukankan      html  css  js  c++  java
  • kqueue使用

    网上搜了下关于kqueue的使用,感觉都不如意,自己翻译了一下,放在git上。

    英文手册: https://www.freebsd.org/cgi/man.cgi?query=kqueue&apropos=0&sektion=0&manpath=FreeBSD+12.2-RELEASE+and+Ports&arch=default&format=html

    三个接口:

    int kqueue(void);

    kqueue()创建一个新的内核事件队列,返回一个文件描述符。如果有错误,将返回-1,并设置error。

    int kevent(
        int    kq, 
        const struct kevent    *changelist, 
        int nchanges,
        struct    kevent *eventlist, 
        int nevents,
        const struct timespec *timeout
    );

    参数changlist、eventlist都是指向kevent结构的指针,changelist是要监听的事件,如果事件发生,会放在eventlist里。

    函数返回放在eventlist里事件的数量,即放了多少个事件到eventlist。

    其中有个比较重要的设定,如果nevents值是0,那kevent()会立即返回;如果nevents不为0,且timeout指针为空,那么kevent()会永久阻塞,直到事件发生。

    EV_SET(kev, ident, filter, flags, fflags, data, udata);
    
    // kevent结构
    struct kevent {
             uintptr_t    ident;         /*    identifier for this event */
             short     filter;         /*    filter for event */
             u_short   flags;         /*    action flags for kqueue    */
             u_int     fflags;         /*    filter flag value */
             int64_t   data;         /*    filter data value */
             void      *udata;         /*    opaque user data identifier */
             uint64_t  ext[4];         /*    extensions */
     };

     宏EV_SE用来初始化kevent结构体。

    ident:一般是文件描述符,比如socket、文件等。

    filter:不知道怎么翻译,过滤器?

    flags:对这个kevent,对kqueue进行怎样操作,是添加到kqueue队列里监听,还是从kqueue队列里移除,需要指明。

    fflags:filter-flags,不同的filter有不同的fflags定义,得看是用的哪个filter。

    其他的参数用的时候再查。

    手册的kqueue例子

    #include <sys/event.h>
    #include <err.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char **argv) {
         struct    kevent event;     /* Event we want to monitor */
         struct    kevent tevent;     /* Event triggered */
         int kq, fd, ret;
    
         if (argc != 2)
             err(EXIT_FAILURE, "Usage: %s path
    ", argv[0]);
    
         // 打开文件,拿到文件描述符
         fd = open(argv[1], O_RDONLY);
         if (fd    == -1)
             err(EXIT_FAILURE, "Failed to open '%s'", argv[1]);
    
         /* Create kqueue. */
         // 创建kqueue队列,返回描述符
         kq = kqueue();
         if (kq    == -1)
             err(EXIT_FAILURE, "kqueue() failed");
      
      // EV_SET(kev, ident,    filter,    flags, fflags, data, udata);
      /*
         初始化kevent结构体
         ident:为文件描述符
         EVFILE_VNODE: 用这个filter
         EV_ADD:添加到kqueue
         EV_CLEAR:每次事件被取走,状态重置
         NOTE_WRITE:每当ident指向的文件描述符有写入时返回
         不用太纠结为什么要用EVFILE_VNODE这个filter,按照官网来说,这个filter就是要用监听文件变化的。
       */
         EV_SET(&event,    fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE, 0,    NULL);
    /* Attach event to the kqueue. */ // 还记得前面的设定么?nevents为0,立即返回,返回的值是kqueue放到eventlist里的事件数量,这里eventlist为NULL,所以返回的ret是0。 // 所以这个语句的作用是向kqueue注册要监听的事件,仅此而已 ret = kevent(kq, &event, 1, NULL, 0, NULL);
    if (ret == -1) // 注册失败会返回-1 err(EXIT_FAILURE, "kevent register");
    if (event.flags & EV_ERROR) // 有其他错误,会置flags的EV_RROR位为1,错误数据放在data字段 errx(EXIT_FAILURE, "Event error: %s", strerror(event.data)); // 开启循环 for (;;) { /* Sleep until something happens. */ // 这里nevents不为0,eventlist为这NULL,且timeout为空指针,那会永久阻塞,直到有事件产生 ret = kevent(kq, NULL, 0, &tevent, 1, NULL);
    if (ret == -1) { err(EXIT_FAILURE, "kevent wait");
    }
    else if (ret > 0) {
    // 每当有东西写到文件里了,就会触发事件 printf("Something was written in '%s' ", argv[1]); } } }


    保存为test.c文件,编译:
    gcc test.c o test

    新建一个文件:

    touch 1.txt

    执行一下:
    ./test 1.txt

    测试一下往1.txt写点东西:

    echo "ewfwf " > 1.txt 

    会看打印 Something was written in '1.txt'。

     
  • 相关阅读:
    搭建kafka集群
    fluentd 安装、配置、使用介绍
    彻底解决 es 的 unassigned shards 症状
    nginx 反向代理时丢失端口的解决方案
    kubernetes的imagePullSecrets如何生成及使用
    创建MySQL数据库账号
    Linux中查找文件
    Linux快速访问多个目录
    Django查询数据库返回字典dict数据
    linux 将压缩包复制到另外一个文件夹下面
  • 原文地址:https://www.cnblogs.com/cool-fire/p/14690040.html
Copyright © 2011-2022 走看看