Chinaunix首页 | 论坛 | 博客
  • 博客访问: 641684
  • 博文数量: 227
  • 博客积分: 8017
  • 博客等级: 中将
  • 技术积分: 2069
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-08 22:50
文章分类

全部博文(227)

文章存档

2011年(10)

2010年(55)

2009年(28)

2008年(134)

我的朋友

分类: C/C++

2010-09-12 16:27:57

Libevent 是一个轻量级的开源高性能网络库,用C语言编写。
其特点有:
  • 事件驱动(event-driven),高性能;
  • 轻量级,专注于网络,不如 ACE 那么臃肿庞大;
  • 源代码相当精炼、易读;跨平台,支持 Windows、Linux、*BSD 和 Mac Os;
  • 支持多种 I/O 多路复用技术, epoll、poll、dev/poll、select 和 kqueue 等;
  • 支持 I/O,定时器和信号等事件;
  • 注册事件优先级;
一. 安装:
sudo yum install libevent
或者去~provos/libevent/下载原代码:
./configure --prefix=/usr
make && make install进行安装

二. 下面是三个简单的使用实例,参照 libevent/samples目录下的实例来的。
1. 最简单的timer事件:


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <event.h>

//compile: gcc -o etimer etimer.c -Wall -g -levent -lrt

void on_timer(int fd, short type, void *args)
{
    struct event *timer_event = (struct event *)args;
    printf("on_timer function...\n");
    printf("timer handles ... \n");
    struct timeval tv;
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    
    event_add(timer_event, &tv);
    
    return ;
}
int main()
{
    struct event_base *base = event_init();
    struct event timer_event;
    struct timeval tv;
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    int fd = -1;
    int type = 0;

    evtimer_set(&timer_event, on_timer, &timer_event);
    //event_set(&timer_event, fd, type, on_timer, &timer_event);
    event_add(&timer_event, &tv);
    //event_base_dispatch(base);
    event_dispatch();
    
    return 0;
}


2. signal信号处理(以SIGINT为例,键盘Ctrl-C即可产生INTERRUPT信号)


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <event.h>

void signal_cb(int fd, short type, void *arg)
{
    struct event *signal_event = (struct event *)arg;
    static int count = 0;
    printf("in function signal_cb...\n");
    printf("handle signal: %d\n", EVENT_SIGNAL(signal_event));
    if (count >= 3)
        event_del(signal_event);
    count ++;
}

int main()
{
    struct event signal_event;
    event_init();
    event_set(&signal_event, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, &signal_event);
    event_add(&signal_event, NULL);
    event_dispatch();
    
    return 0;
}


3. IO事件处理

/*
 * Compile with:
 * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <event.h>

void fifo_read(int fd, short event, void *arg)
{
    char buf[255];
    int len;
    struct event *ev = arg;

    /* Reschedule this event */
    event_add(ev, NULL);

    fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
        fd, event, arg);

    len = read(fd, buf, sizeof(buf) - 1);

    if (len == -1) {
        perror("read");
        return;
    } else if (len == 0) {
        fprintf(stderr, "Connection closed\n");
        return;
    }

    buf[len] = '\0';
    fprintf(stdout, "Read: %s\n", buf);
}

int
main (int argc, char **argv)
{
    struct event evfifo;
    struct stat st;
    char *fifo = "event.fifo";
    int socket;
 
    if (lstat (fifo, &st) == 0) {
        if (S_ISREG(st.st_mode)){
            errno = EEXIST;
            perror("lstat");
            exit (1);
        }
    }

    unlink (fifo);
    if (mkfifo (fifo, 0600) == -1) {
        perror("mkfifo");
        exit (1);
    }

    /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
    socket = open (fifo, O_RDWR | O_NONBLOCK, 0);

    if (socket == -1) {
        perror("open");
        exit (1);
    }

    fprintf(stderr, "Write data to %s\n", fifo);
    /* Initalize the event library */
    event_init();
    /* Initalize one event */
    event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);
    /* Add it to the active events, without a timeout */
    event_add(&evfifo, NULL);
    
    event_dispatch();
    return (0);
}
//运行时需要在另一个shell中向fifo写入数据: echo "aaa" > event.fifo


附加: 测试另一种持久的IO事件: EV_PERSIST

/*
 * Compile with:
 * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
 */


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <event.h>

void fifo_read(int fd, short event, void *arg)
{
    char buf[255];
    int len;
    struct event *ev = arg;
    static int count = 0;

    fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
        fd, event, arg);
    if (++count == 20){    
        len = read(fd, buf, sizeof(buf) - 1);
        if (len == -1) {
            perror("read");
            return;
        } else if (len == 0) {
            fprintf(stderr, "Connection closed\n");
            return;
        }
        buf[len] = '\0';
        fprintf(stdout, "Read: %s\n", buf);
    }
    printf("over...\n");
}


int main (int argc, char **argv)
{
    struct event evfifo;
    struct stat st;
    char *fifo = "event.fifo";
    int socket;
 
    if (lstat (fifo, &st) == 0) {
        if (S_ISREG(st.st_mode)){
            errno = EEXIST;
            perror("lstat");
            exit (1);
        }
    }

    unlink (fifo);
    if (mkfifo (fifo, 0600) == -1) {
        perror("mkfifo");
        exit (1);
    }
    /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
    socket = open (fifo, O_RDWR | O_NONBLOCK, 0);

    if (socket == -1) {
        perror("open");
        exit (1);
    }

    fprintf(stderr, "Write data to %s\n", fifo);

    /* Initalize the event library */
    event_init();

    /* Initalize one event */
    event_set(&evfifo, socket, EV_READ | EV_PERSIST, fifo_read, &evfifo);
    /* Add it to the active events, without a timeout */
    event_add(&evfifo, NULL);
    
    event_dispatch();
    return (0);
}

//设置持久事件后,只要用echo "a">event.fifo 哪怕只写入一个Byte, 程序也会进入读事件循环,直到数据被读出!所以这个测试程序可以会一致打印20个over后再停止。memcached的状态机(drive_machine)就是利用这个EV_PERSIST来实现的。



注意: 如不加-lrt会出现链接错误:

gcc -o event-test event-test.c -Wall -g -levent
/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../libevent.a(event.o): In function `gettime':
(.text+0x2a7): undefined reference to `clock_gettime'

/usr/lib/gcc/i686-redhat-linux/4.4.4/../../../libevent.a(event.o): In function `event_base_new':
(.text+0x58a): undefined reference to `clock_gettime'

collect2: ld 返回 1


还有,安装到/usr目录下就不要用-I和-L了

阅读(1682) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~