eventfd(一)

函数原型: 创建的时候可以传入一个计数器的初始值initval。 第二个参数flags在linux 2.6.26之前的版本是没有使用的,必须初始化为0,在2.6.27之后的版本flag才被使用。

#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);

分析:

flags 可以是以下值的 OR 运算结果,用以改变 eventfd 的行为。

  • EFD_CLOEXEC (since Linux 2.6.27) 文件被设置成 O_CLOEXEC,创建子进程 (fork) 时不继承父进程的文件描述符。
  • EFD_NONBLOCK (since Linux 2.6.27) 文件被设置成 O_NONBLOCK,执行 read / write 操作时,不会阻塞。
  • EFD_SEMAPHORE (since Linux 2.6.30) 提供类似信号量语义的 read 操作,简单说就是计数值 count 递减 1。

在 Linux 2.6.26 版本之前,没有使用参数 flags,必须指定为 0。

操作方法

read: 读取计数器中的值

  • 如果计数器中的值大于0
    1. 设置了EFD_SEMAPHORE标志位,则返回1,且计数器中的值也减去1。
    2. 没有设置EFD_SEMAPHORE标志位,则返回计数器中的值,且计数器置0。
  • 如果计数器中的值为0
    1. 设置了EFD_NONBLOCK标志位就直接返回-1。
    2. 没有设置EFD_NONBLOCK标志位就会一直阻塞直到计数器中的值大于0。

write: 向计数器中写入值

  • 如果写入值的和小于0xFFFFFFFFFFFFFFFE,则写入成功
  • 如果写入值的和大于0xFFFFFFFFFFFFFFFE
    1. 设置了EFD_NONBLOCK标志位就直接返回-1。
    2. 如果没有设置EFD_NONBLOCK标志位,则会一直阻塞直到read操作执行

close: 关闭文件描述符,eventfd 对象引用计数减 1,若减为 0,则释放 eventfd 对象资源。

测试代码:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char* argv[])
{
    int efd, j;
    uint64_t u;
    ssize_t s;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    efd = eventfd(0, 0);
    if (efd == -1)
        handle_error("eventfd");

    switch (fork())
    {
    case 0:
        for (j = 1; j < argc; j++)
        {
            printf("Child writing %s to efd\n", argv[j]);
            u = atoi(argv[j]);
            s = write(efd, &u, sizeof(uint64_t));
            if (s != sizeof(uint64_t))
            {
                handle_error("write");
            }

        }
        printf("Child completed write loop\n");

        exit(EXIT_SUCCESS);

    default:
        sleep(2);

        printf("Parent about to read\n");

        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
            handle_error("read");
        }

        printf("Parent read %llu (0x%llx) from efd\n",
            (unsigned long long) u, (unsigned long long) u);

        exit(EXIT_SUCCESS);

    case -1:
        handle_error("fork");
    }
}

输出结果:

 

 2. 测试代码:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char* argv[])
{
    int efd, j;
    uint64_t u;
    ssize_t s;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    efd = eventfd(0, EFD_NONBLOCK);
    if (efd == -1)
        handle_error("eventfd");

    switch (fork())
    {
    case 0:
        for (j = 1; j < argc; j++)
        {
            printf("Child writing %s to efd\n", argv[j]);
        }
        printf("Child completed write loop\n");

        exit(EXIT_SUCCESS);

    default:
        sleep(2);

        printf("Parent about to read\n");

        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
            handle_error("read");
        }

        printf("Parent read %llu (0x%llx) from efd\n",
            (unsigned long long) u, (unsigned long long) u);

        exit(EXIT_SUCCESS);

    case -1:
        handle_error("fork");
    }
}

输出结果:

 

3. 

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char* argv[])
{
    int efd, j;
    uint64_t u;
    ssize_t s;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    efd = eventfd(0, EFD_SEMAPHORE);
    if (efd == -1)
        handle_error("eventfd");

    switch (fork())
    {
    case 0:
        for (j = 1; j < argc; j++)
        {
            printf("Child writing %s to efd\n", argv[j]);
            u = atoi(argv[j]);
            s = write(efd, &u, sizeof(uint64_t));
            if (s != sizeof(uint64_t))
            {
                handle_error("write");
            }

        }
        printf("Child completed write loop\n");

        exit(EXIT_SUCCESS);

    default:
        sleep(2);

        printf("Parent about to read\n");

        s = read(efd, &u, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
        {
            handle_error("read");
        }

        printf("Parent read %llu (0x%llx) from efd\n",
            (unsigned long long) u, (unsigned long long) u);

        exit(EXIT_SUCCESS);

    case -1:
        handle_error("fork");
    }
}

输出结果:

参考资料:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值