libevent笔记1:安装及DEMO

本篇简单记录了libevent的安装过程及基础的先进先出管道Demo,其中demo来自这篇博客,安装过程在这篇博客

实验环境

  • 系统:Ubuntu 18.04.3
  • libevent版本:libevent-2.1.11-stable

libevent安装

  • libevent官网下载压缩包并解压;
  • 进入libevent目录,依次执行:
sunminming@sunminming:~/libevent-2.1.11-stable$ ./configure
sunminming@sunminming:~/libevent-2.1.11-stable$ make
sunminming@sunminming:~/libevent-2.1.11-stable$ sudo make install

    这之后应该能在/usr/local/lib目录下找到libevent相关的动态库;

  • 将动态库链接到/usr/lib/目录下:
sunminming@sunminming:/usr/local/lib$ ln -s libevent-2.1.so.7 /usr/lib/libevent-2.1.so.7
  • 最后执行ldconfig命令。

先进先出管道Demo

FIFO Demo由两个进程(write和read)组成,具体的代码如下:

  • read_fifo.c
//read_fifo.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<fcntl.h>
#include<event2/event.h>
//read callback function
void read_callback(evutil_socket_t fd, short what, void* arg)
{
    //read the fifo pipe
    char buf[1024] = {0};
    int len = read(fd, buf, sizeof(buf));
    printf("data len = %d, buf = %s\n", len, buf);
    printf("read event: %s\n", what & EV_READ?"Y":"N");
}
int main(int argc, const char* argv[])
{
    //construct and open a fifo pipe
    unlink("myfifo");
    mkfifo("myfifo", 0664);
    int fd = open("myfifo", O_RDONLY|O_NONBLOCK);
    if(fd == -1)
    {
    perror("open error");
    exit(1);
    }
    //read from pipr
    struct event_base* base = NULL;
    base = event_base_new();
    //construct a event
    struct event* ev = NULL;
    ev = event_new(base, fd, EV_READ, read_callback, NULL);
    //add event
    event_add(ev, NULL);
    //event loop
    event_base_dispatch(base);
    //free resource
    event_free(ev);
    event_base_free(base);
    close(fd);
    return 0;
    }
  • write_fifo.c
    //write_fifo.c
    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<string.h>
    #include<fcntl.h>
    #include<event2/event.h>
    //callback function
    void write_callback(evutil_socket_t fd, short what, void *arg)
    {
        //write into pipe
        char buf[1024] = {0};
        static int num = 666;
        sprintf(buf, "hello, world == %d\n", num);
        write(fd, buf, strlen(buf)+1);
    }
    int main(int argc, const char* argv[])
    {
        //open the fifo file
        int fd = open("myfifo", O_WRONLY|O_NONBLOCK);
        if(fd == -1)
        {
            perror("open error");
            exit(1);
        }
        //construct a event_base
        struct event_base* base = NULL;
        base = event_base_new();
        //construct a event
        struct event* ev = NULL;
        ev = event_new(base, fd, EV_WRITE, write_callback, NULL);
        //add event
        event_add(ev, NULL);
        //event loop
        event_base_dispatch(base);
        //free resource
        event_free(ev);
        event_base_free(base);
        close(fd);
        return 0;
    }
  • 分别编译writer.c 及 read.c:
    sunminming@sunminming:~/libevent/fifo$ gcc write_fifo.c -o write -levent
    sunminming@sunminming:~/libevent/fifo$ gcc read_fifo.c -o read -levent
  • 先运行read,在运行write,结果应如下:
    sunminming@sunminming:~/libevent/fifo$ ./read 
    data len = 21, buf = hello, world == 666
    read event: Y

libevent相关函数

本节简单介绍上一节中几个libevet函数的抽象功能,不涉及函数源码。

  • struct event_base* event_base_new(void):
    这个函数是适用libevent库最先需要调用的,返回一个event_base结构体。event_base结构体是整个libevent的基石,负责跟踪每个事件的状态,哪个事件处于挂起状态(pending)等待唤醒,哪个事件处于活动状态(active)。

  • struct event* event_new(struct event_base* base,
                evutil_socket_t fd,
                short events,
                event_callback_fn callback,
                void* callback_arg):
    当程序需要对某个文件描述符进行监控时,首先需要调用event_new()函数来创造一个event结构体。在libevent的官网中特别强调,event结构体是定义在堆中的,这是由于需要在任何函数中都能监控每个事件。参数列表如下:

    • struct event_base* base 这个事件属于(官网上的用词是"attached")event_base结构体;
    • evutil_socket_t fd 被监视的文件描述符或者信号等;
    • short events 需要监控的具体事件,如上文中的EV_WRITE表示文件描述符可写时,EV_READ表示文件描述符可读时,触发该事件;
    • event_callback_fn callback 当事件触发时调用的回调函数;
    • callback_arg 传递给回调函数callbakck的参数,值得注意的是,传递给callback函数的参数一共三个:事件描述符fd、触发的具体事件events及该参数callback_arg
  • int event_add(struct event* ev, const struct timeval *timeout):
    创建event结构体之后,调用event_add()来将event对象加入挂起事件列表。之后调用该函数之后,参数列表中的ev才能在事件发生时被触发。参数列表如下:

    • struct event* ev 监控的事件;
    • const struct timeval *timeout:对于加入的事件的最大等待时间,若为NULL则一直等待。
      返回0表示调用成功,-1表示失败。
  • int event_base_dispatch(struct event_base* base):
    最后开始等待事件被触发,一直会持续到没有任何事件属于base或等待时间结束(默认情况下,一个事件只会被触发一次)。参数列表如下:

    • struct event_base* base 开始等待的base结构体,其中属于其的事件会处于挂起状态等待被触发到活动状态。
posted @ 2019-11-07 20:37  孙敏铭  阅读(590)  评论(0编辑  收藏  举报