本文共 2052 字,大约阅读时间需要 6 分钟。
eventfd 主要用于实现线程间通讯,可以用于用户态和内核通讯.主要涉及两个系统调用SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags){ return do_eventfd(count, flags);}SYSCALL_DEFINE1(eventfd, unsigned int, count){ return do_eventfd(count, 0);}当用户通过这两个系统调用创建eventfd后,这个fd 其实际就是内存中的一个文件,这点可以从系统调用的实现do_eventfd来看到static int do_eventfd(unsigned int count, int flags){ struct eventfd_ctx *ctx; int fd; /* Check the EFD_* constants for consistency. */ BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); if (flags & ~EFD_FLAGS_SET) return -EINVAL; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; kref_init(&ctx->kref); init_waitqueue_head(&ctx->wqh); ctx->count = count; ctx->flags = flags;#用户空间得到的就是这个fd,从这里可以看到fd就是内存中的一个问题#这个文件对应的fops是eventfd_fops fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS)); if (fd < 0) eventfd_free_ctx(ctx); return fd;}明白fd是一个内存文件后,就可以通过对这个文件的read和write来通信,其中read和write都是定义在eventfd_fops 中static const struct file_operations eventfd_fops = {#ifdef CONFIG_PROC_FS .show_fdinfo = eventfd_show_fdinfo,#endif .release = eventfd_release, .poll = eventfd_poll, .read = eventfd_read, .write = eventfd_write, .llseek = noop_llseek,};其中read函数如下:static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ struct eventfd_ctx *ctx = file->private_data; ssize_t res; __u64 ucnt = 0; DECLARE_WAITQUEUE(wait, current); if (count < sizeof(ucnt)) return -EINVAL; spin_lock_irq(&ctx->wqh.lock); res = -EAGAIN; if (likely(res > 0)) {#调用eventfd_ctx_do_read来对eventfd_ctx中的成员变量count 减掉cnt eventfd_ctx_do_read(ctx, &ucnt); if (waitqueue_active(&ctx->wqh)) wake_up_locked_poll(&ctx->wqh, EPOLLOUT); } spin_unlock_irq(&ctx->wqh.lock); if (res > 0 && put_user(ucnt, (__u64 __user *)buf)) return -EFAULT; return res;}static void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt){ *cnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count; ctx->count -= *cnt;}可见eventfd就对应内存中的文件,对这个文件read的话,则对计数器加,对这个文件写的话,则对计数器减,以此来最为线程间通讯机制.
转载地址:http://gsnmi.baihongyu.com/