首先需要确定eventfd已经被编译进内核,其次还要确定所使用的交叉编译器支持eventfd。

函数原型:

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

说明:initval的范围是0~0xfffffffffffffffe;flags的值可以是如下枚举值:

enum
{EFD_SEMAPHORE = 00000001,//since Linux 2.6.30
#define EFD_SEMAPHORE EFD_SEMAPHOREEFD_CLOEXEC = 02000000,//since Linux 2.6.27
#define EFD_CLOEXEC EFD_CLOEXECEFD_NONBLOCK = 00004000//since Linux 2.6.27
#define EFD_NONBLOCK EFD_NONBLOCK
};

如果设置了EFD_SEMAPHORE,则不会出现粘包的情况,即write多少次,就需要read多少次;

如果设置了0(内核2.6.27版本之前必须设置为0),则会出现粘包的可能,write多次,可能read到的是若干次的值的和;

另外两种一般不需要,所以并未进行测试。

  1. 用户态

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdint.h>     //Definition of uint64_t
    #include <sys/eventfd.h>
    int efd; //Eventfd file descriptor
    uint64_t eftd_ctr;
    int retval;     //for select()
    fd_set rfds;        //for select()
    int s;
    int main() {//Create eventfdefd = eventfd(0,0);if (efd == -1){printf("\nUnable to create eventfd! Exiting...\n");exit(EXIT_FAILURE);}printf("\nefd=%d pid=%d",efd,getpid());//Watch efdFD_ZERO(&rfds);FD_SET(efd, &rfds);printf("\nNow waiting on select()...");fflush(stdout);retval = select(efd+1, &rfds, NULL, NULL, NULL);if (retval == -1){printf("\nselect() error. Exiting...");exit(EXIT_FAILURE);} else if (retval > 0) {printf("\nselect() says data is available now. Exiting...");printf("\nreturned from select(), now executing read()...");s = read(efd, &eftd_ctr, sizeof(uint64_t));if (s != sizeof(uint64_t)){printf("\neventfd read error. Exiting...");} else {printf("\nReturned from read(), value read = %lld",eftd_ctr);}} else if (retval == 0) {printf("\nselect() says that no data was available");}printf("\nClosing eventfd. Exiting...");close(efd);printf("\n");exit(EXIT_SUCCESS);
    }
    
  2. 内核态

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/pid.h>
    #include <linux/sched.h>
    #include <linux/fdtable.h>
    #include <linux/rcupdate.h>
    #include <linux/eventfd.h>
    //Received from userspace. Process ID and eventfd's File descriptor are enough to uniquely identify an eventfd object.
    int pid;
    int efd;
    //Resolved references...
    struct task_struct * userspace_task = NULL; //...to userspace program's task struct
    struct file * efd_file = NULL;          //...to eventfd's file struct
    struct eventfd_ctx * efd_ctx = NULL;        //...and finally to eventfd context
    //Increment Counter by 1
    static uint64_t plus_one = 1;
    int init_module(void) {printk(KERN_ALERT "~~~Received from userspace: pid=%d efd=%d\n",pid,efd);userspace_task = pid_task(find_vpid(pid), PIDTYPE_PID);printk(KERN_ALERT "~~~Resolved pointer to the userspace program's task struct: %p\n",userspace_task);printk(KERN_ALERT "~~~Resolved pointer to the userspace program's files struct: %p\n",userspace_task->files);rcu_read_lock();efd_file = fcheck_files(userspace_task->files, efd);rcu_read_unlock();printk(KERN_ALERT "~~~Resolved pointer to the userspace program's eventfd's file struct: %p\n",efd_file);efd_ctx = eventfd_ctx_fileget(efd_file);if (!efd_ctx) {printk(KERN_ALERT "~~~eventfd_ctx_fileget() Jhol, Bye.\n");return -1;}printk(KERN_ALERT "~~~Resolved pointer to the userspace program's eventfd's context: %p\n",efd_ctx);eventfd_signal(efd_ctx, plus_one);printk(KERN_ALERT "~~~Incremented userspace program's eventfd's counter by 1\n");eventfd_ctx_put(efd_ctx);return 0;
    }
    void cleanup_module(void) {printk(KERN_ALERT "~~~Module Exiting...\n");
    }
    MODULE_LICENSE("GPL");
    module_param(pid, int, 0);
    module_param(efd, int, 0);
    
  3. 如何使用以上示例

Compile the userspace program (efd_us.out) and the kernel module (efd_lkm.ko)
Run the userspace program (./efd_us.out) and note the pid and efd values that it print. (for eg. “pid=2803 efd=3”. The userspace program will wait endlessly on select()
Open a new terminal window and insert the kernel module passing the pid and efd as params: sudo insmod efd_lkm.ko pid=2803 efd=3
Switch back to the userspace program window and you will see that the userspace program hasbroken out of select and exited.

内核态与用户态通信之eventfd使用相关推荐

  1. Linux 内核态与用户态通信 netlink

    参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...

  2. Linux内核态之间进程通信,内核态和用户态通信(二)--实现

    本文主要使用netlink套接字实现中断环境与用户态进程通信. 系统环境:基于linux 2.6.32.27 和 linux 3.16.36 Linux内核态和用户态进程通信方法的提出和实现 用户上下 ...

  3. linux 用户态 内核态 通信,procfs(从0开始,内核态和用户态通信charpter2)

    这篇博文将针对linux内核态与用户态通信方式中的procfs进行详细的学习. /proc主要存放内核的一些控制信息,所以这些信息大部分的逻辑位置位于内核控制的内存,在/proc下使用ls -l你会发 ...

  4. linux内核态和用户态

    参考文章: linux系统内核空间与用户空间通信的实现与分析: http://www.ibm.com/developerworks/cn/linux/l-netlink/ 进程上下文VS中断上下文: ...

  5. 用户态和内核态:用户态线程和内核态线程有什么区别?

    转载 文章来源于 拉钩教育 重学操作系统 林䭽 用户态和内核态:用户态线程和内核态线程有什么区别? 什么是用户态和内核态 Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有 ...

  6. Linux的init进程(内核态到用户态的变化)

    init进程,也就是内核启动3个进程中的进程1: init进程完成了从内核态向用户态的转变: (1)init进程是比较特殊,一个进程两个状态,init刚开始运行时是内核态,他属于内核线程,然后他自己运 ...

  7. Linux 操作系统原理 — 内核态与用户态

    目录 文章目录 目录 Linux 的内核态与用户态 系统调用(System Call) Shell 用户态和内核态的切换 进程的用户空间和内核空间的内存布局 内核空间 用户空间 Linux 的内核态与 ...

  8. 【Linux 内核】Linux 内核体系架构 ( 硬件层面 | 内核空间 | 用户空间 | 内核态与用户态切换 | 系统调用 | 体系结构抽象层 )

    文章目录 一.Linux 内核体系架构 二.内核态与用户态切换 ( 系统调用层 ) 三.体系结构抽象层 一.Linux 内核体系架构 Linux 内核最初的源码不足一万行 , 当前的 Linux 内核 ...

  9. 内核态与用户态的区别

    原文链接:https://www.cnblogs.com/gizing/p/10925286.html 1.操作系统需要两种CPU状态 内核态(Kernel Mode):运行操作系统程序,操作硬件 用 ...

  10. 内核态和用户态的区别

    当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态).此时处理器处于特权级最高的(0级)内核代码中执行.当进程处于内核态时,执行的内核代码会使用当前进程的 ...

最新文章

  1. 大写“惨”?三次改变世界、却被无情出局的程序员大牛!
  2. LeetCode Multiply Strings(大整数相乘)
  3. OHSUMED数据集介绍
  4. Dapr + .NET 实战(八)服务监测
  5. 20190808面试记录
  6. 3种重构EF Linq查询的方法而不扼杀性能
  7. 静态文件之static+url控制系统(萌新笔记)
  8. ValueStack中的context与ActionContext的区别
  9. 功夫小子实践开发-游戏设置功能的实现
  10. ActiveMQ学习三-持久化订阅
  11. Python搭建SVM
  12. Java中如何创建一个文件或者文件夹
  13. diffdock:将扩散模型用于分子对接
  14. 基于参数化模型(MANO)的手势姿态估计---全面剖析
  15. 猿创征文|MySQL入门到实战-基础篇
  16. ubuntu下ecm驱动_Linux 下使用USB 网络
  17. 毕业论文(二)文章中多次引用同一参考文献的不同内容该如何标注
  18. 学习之旅16-R数据可视化-图形处理(二)
  19. 高思教育获华平领投1.4亿美元D轮融资,发力B端全面开启平台化战略...
  20. Cordova开发流程-H5 JS转Android 和Ios App

热门文章

  1. 京东店铺托管引流技巧有哪些?
  2. JavaScript之封装Math函数
  3. ubuntu分区大小
  4. Codeforces 819 C. Mister B and Beacons on Field 容斥 数学
  5. SQLite 免费查看工具
  6. 微信小程序傻瓜制作_零基础,傻瓜式制作微信小程序,3分钟完成不是问题!...
  7. 平行空间怎么设置32位_10月微信新花样!微信情侣空间怎么解除 情侣空间取消情侣关系设置方法...
  8. ADB命令获取手机应用安装包
  9. GB28181国标平台接入摄像头、NVR录像机通道数位0没有通道的处理方式
  10. R forcast auto arima用法