linux进程间通信——eventfd

举报
ZhjDayDayUp 发表于 2022/01/17 21:01:27 2022/01/17
【摘要】 eventfd是linux内核提供的一种系统调用,是一种事件通知创建文件描述符,进程可以通过对这个文件描述符进行read/write操作,从而实现进程间通信。

eventfd是linux内核提供的一种系统调用,是一种事件通知创建文件描述符,进程可以通过对这个文件描述符进行read/write操作,从而实现进程间通信。

eventfd使用

主要接口为:

1、创建eventfd对象

# include<sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
// initval:创建eventfd时它所对应的64位计数器的初始值;
// flags:eventfd文件描述符的标志,可由三种选项组成:EFD_CLOEXEC、EFD_NONBLOCK和EFD_SEMAPHORE
          EFD_CLOEXEC表示返回的eventfd文件描述符在fork后exec其他程序时会自动关闭这个文件描述符;
          EFD_NONBLOCK设置返回的eventfd非阻塞;
          EFD_SEMAPHORE表示将eventfd作为一个信号量来使用

2、读eventfd

使用read函数,需要注意如下几点:

(1)read函数会从eventfd对应的64位计数器中读取一个8字节的整型变量

(2)read函数设置的接收buf的大小不能低于8个字节,否则read函数会出错,errno为EINVAL

(3)read函数返回的值是按小端字节序的

(4)如果eventfd设置了EFD_SEMAPHORE,那么每次read就会返回1,并且让eventfd对应的计数器减1;如果eventfd没有设置EFD_SEMAPHORE,那么每次read就会直接返回计数器中的数值,read之后计数器就会置0。不管是哪一种,当计数器为0时,如果继续read,那么read就会阻塞(如果eventfd没有设置EFD_NONBLOCK)或者返回EAGAIN错误(如果eventfd设置了EFD_NONBLOCK)。

3、写eventfd

使用write函数:

(1)在没有设置EFD_SEMAPHORE的情况下,write函数会将发送buf中的数据写入到eventfd对应的计数器中,最大只能写入0xffffffffffffffff,否则返回EINVAL错误;

(2)在设置了EFD_SEMAPHORE的情况下,write函数相当于是向计数器中进行“添加”,比如说计数器中的值原本是2,如果write了一个3,那么计数器中的值就变成了5。如果某一次write后,计数器中的值超过了0xfffffffffffffffe(64位最大值-1),那么write就会阻塞直到另一个进程/线程从eventfd中进行了read(如果write没有设置EFD_NONBLOCK),或者返回EAGAIN错误(如果write设置了EFD_NONBLOCK)。

实例

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/eventfd.h>
#include <sys/epoll.h>

int efd = -1;

void *read_func(void *)
{
    printf("read_func begin\n");

    uint64_t data;
    int ret = read(efd, &data, sizeof(data));
    if (ret < 0)
    {
        printf("read fail\n");
    }
    else
    {
        printf("success read from efd, read %d bytes, data is %d\n", ret, data);
    }
    return nullptr;
}

int main()
{
    efd = eventfd(0, 0);
    if (efd < 0)
    {
        printf("eventfd fail\n");
        return -1;
    }

    pthread_t pid = 0;
    int ret = pthread_create(&pid, nullptr, read_func, nullptr);
    if (ret < 0)
    {
        printf("pthread_create fail\n");
        close(efd);
        efd = -1;
        return -1;
    }

    uint64_t data = 4;
    ret = write(efd, &data, sizeof(data));
    if (ret < 0)
    {
        printf("write fail\n");
        close(efd);
        efd = -1;

        pthread_join(pid, nullptr);
        pid = 0;

        return -1;
    }

    pthread_join(pid, nullptr);
    close(efd);

    return 0;
}

参考:
https://blog.csdn.net/qq_28114615/article/details/97929524

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。