• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

XiaoXiaoli

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

libevent_通过libevent监听有名管道

libevent_IO事件

管道是通过文件描述符读写,我们可以监听文件描述符是否可读,一旦有进程往管道中写数据,另一端就是可读,可以被libevent监听到。libevent监听到后,可以调用函数将数据读取出来。有名管道随便读写,读和写是通过fd,将这个fd添加到集合中,libevent可以监听这个fd,一旦发现这个fd可读,就将数据读出来。

整体流程,分为A和B两个部分,A部分为创建一个读进程,B部分为创建一个写进程。

A :创建一个读管道进程。

1. 创建有名管道。调用函数mkfifo(const char *pathname, mode_t mode)

2. 打开管道。调用函数open(const char *pathname, int flags, mode_t mode)

3. 初始化事件集合。调用函数event_init()

4. 创建一个事件。定义一个结构体变量struct event ev

5. 初始化事件,fd和事件绑定一起。调用函数event_set(&ev, fd, EV_READ, fifo_read, NULL);

6.实现fifo_read函数。

7. 事件添加到集合中。调用函数event_add(&ev, NULL),默认情况下文件描述符只能使用一次。

8. 开始监听。调用函数event_dispatch()

B:创建一个写管道进程。

读管道进程源代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <event.h>

void fifo_read(evutil_socket_t fd, short events, void *arg){
        char buf[200] = {0};
        int ret = 0;
        ret = read(fd, buf, sizeof(buf));
        if(ret == -1){
                printf("readFIFO文件出错\n");
                return -1;
        }
        printf("从fifo管道中读取数据[%s]\n", buf);
}


int main(int argc, char *argv[]){
        int ret = 0;
        ret = mkfifo("/home/xl/FileDemo/mkfifo_1", 00700);
        if(ret == -1){
                printf("mkfifo创建FIFO文件失败\n");
                return 0;
        }

        int fd = 0;
        fd = open("/home/xl/FileDemo/mkfifo_1", O_RDONLY);
        if(fd == -1){
                printf("open 打开文件失败\n");
                return -1;
        }


        struct event ev;
        event_init();
        event_set(&ev, fd, EV_READ|EV_PERSIST, fifo_read, NULL);
        event_add(&ev, NULL);
        event_dispatch();
        return 0;
}

写管道进程源代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[]){

        int ret = 0;
        int w_ret = 0;
        char home_path[200] = {0};
        char file_path[200] = {0};
        char file_name[200] = {0};
        char s_buf[200] = {0};
        strcpy(home_path, getenv("HOME"));
        sprintf(file_path , "%s/%s/%s", home_path, "FileDemo" ,"mkfifo_1");
        strcpy(file_name, file_path);

        printf("file_name = [%s]\n", file_name);
        ret = open(file_name, O_WRONLY);
        if(ret == -1){
                printf("打开文件[%s]失败", file_name);
                return -1;
        }

        while(1){
                scanf("%s", s_buf);
                if(!strcmp(s_buf, "bye")){
                        printf("bye~~~\n");
                        break;
                }

                w_ret = write(ret, s_buf, sizeof(s_buf));
                if(w_ret == -1){
                        printf("写入数据[%s]失败", s_buf);
                        return -1;
                }

                memset(s_buf, 0x00, sizeof(s_buf));

        }
        printf("exit!!!\n");
        return 0;
}

通过简单的代码,学习事件集合是什么? 事件是什么? 事件如何添加到事件集合中?怎么把文件描述符和事件关联起来?

代码中使用到的函数源代码

event_init

struct event_base *event_init(void)
{
    struct event_base *base = event_base_new_with_config(NULL);

    if (base == NULL) {
        event_errx(1, "%s: Unable to construct event_base", __func__);
        return NULL;
    }

    current_base = base; //这里current_base 是一个全局变量。

    return (base);
}

event_set函数原型

/**
  Prepare an event structure to be added.

  @deprecated event_set() is not recommended for new code, because it requires
     a subsequent call to event_base_set() to be safe under most circumstances.
     Use event_assign() or event_new() instead.
 */
EVENT2_EXPORT_SYMBOL
void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *);

 

posted on 2020-12-03 22:15  XiaoXiaoli  阅读(649)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3