内核态与用户态通信之eventfd使用
首先需要确定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到的是若干次的值的和;
另外两种一般不需要,所以并未进行测试。
用户态
#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); }
内核态
#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);
如何使用以上示例
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使用相关推荐
- Linux 内核态与用户态通信 netlink
参考资料: https://blog.csdn.net/zqixiao_09/article/details/77131283 https://www.cnblogs.com/lopnor/p/615 ...
- Linux内核态之间进程通信,内核态和用户态通信(二)--实现
本文主要使用netlink套接字实现中断环境与用户态进程通信. 系统环境:基于linux 2.6.32.27 和 linux 3.16.36 Linux内核态和用户态进程通信方法的提出和实现 用户上下 ...
- linux 用户态 内核态 通信,procfs(从0开始,内核态和用户态通信charpter2)
这篇博文将针对linux内核态与用户态通信方式中的procfs进行详细的学习. /proc主要存放内核的一些控制信息,所以这些信息大部分的逻辑位置位于内核控制的内存,在/proc下使用ls -l你会发 ...
- linux内核态和用户态
参考文章: linux系统内核空间与用户空间通信的实现与分析: http://www.ibm.com/developerworks/cn/linux/l-netlink/ 进程上下文VS中断上下文: ...
- 用户态和内核态:用户态线程和内核态线程有什么区别?
转载 文章来源于 拉钩教育 重学操作系统 林䭽 用户态和内核态:用户态线程和内核态线程有什么区别? 什么是用户态和内核态 Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有 ...
- Linux的init进程(内核态到用户态的变化)
init进程,也就是内核启动3个进程中的进程1: init进程完成了从内核态向用户态的转变: (1)init进程是比较特殊,一个进程两个状态,init刚开始运行时是内核态,他属于内核线程,然后他自己运 ...
- Linux 操作系统原理 — 内核态与用户态
目录 文章目录 目录 Linux 的内核态与用户态 系统调用(System Call) Shell 用户态和内核态的切换 进程的用户空间和内核空间的内存布局 内核空间 用户空间 Linux 的内核态与 ...
- 【Linux 内核】Linux 内核体系架构 ( 硬件层面 | 内核空间 | 用户空间 | 内核态与用户态切换 | 系统调用 | 体系结构抽象层 )
文章目录 一.Linux 内核体系架构 二.内核态与用户态切换 ( 系统调用层 ) 三.体系结构抽象层 一.Linux 内核体系架构 Linux 内核最初的源码不足一万行 , 当前的 Linux 内核 ...
- 内核态与用户态的区别
原文链接:https://www.cnblogs.com/gizing/p/10925286.html 1.操作系统需要两种CPU状态 内核态(Kernel Mode):运行操作系统程序,操作硬件 用 ...
- 内核态和用户态的区别
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态).此时处理器处于特权级最高的(0级)内核代码中执行.当进程处于内核态时,执行的内核代码会使用当前进程的 ...
最新文章
- 大写“惨”?三次改变世界、却被无情出局的程序员大牛!
- LeetCode Multiply Strings(大整数相乘)
- OHSUMED数据集介绍
- Dapr + .NET 实战(八)服务监测
- 20190808面试记录
- 3种重构EF Linq查询的方法而不扼杀性能
- 静态文件之static+url控制系统(萌新笔记)
- ValueStack中的context与ActionContext的区别
- 功夫小子实践开发-游戏设置功能的实现
- ActiveMQ学习三-持久化订阅
- Python搭建SVM
- Java中如何创建一个文件或者文件夹
- diffdock:将扩散模型用于分子对接
- 基于参数化模型(MANO)的手势姿态估计---全面剖析
- 猿创征文|MySQL入门到实战-基础篇
- ubuntu下ecm驱动_Linux 下使用USB 网络
- 毕业论文(二)文章中多次引用同一参考文献的不同内容该如何标注
- 学习之旅16-R数据可视化-图形处理(二)
- 高思教育获华平领投1.4亿美元D轮融资,发力B端全面开启平台化战略...
- Cordova开发流程-H5 JS转Android 和Ios App
热门文章
- 京东店铺托管引流技巧有哪些?
- JavaScript之封装Math函数
- ubuntu分区大小
- Codeforces 819 C. Mister B and Beacons on Field 容斥 数学
- SQLite 免费查看工具
- 微信小程序傻瓜制作_零基础,傻瓜式制作微信小程序,3分钟完成不是问题!...
- 平行空间怎么设置32位_10月微信新花样!微信情侣空间怎么解除 情侣空间取消情侣关系设置方法...
- ADB命令获取手机应用安装包
- GB28181国标平台接入摄像头、NVR录像机通道数位0没有通道的处理方式
- R forcast auto arima用法