当前位置:网站首页>Realize data exchange between kernel and userspace through character device virtual file system (passed based on kernel 5.8 test)
Realize data exchange between kernel and userspace through character device virtual file system (passed based on kernel 5.8 test)
2022-08-11 06:15:00 【, as you like】
kernel space代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/io.h> //ioremap()
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h> //kmalloc
#define DEVICE_NAME "icdev"
#define BUF_SIZE (1024)
#define ICT_IOCTL_MAGIC_NUM 'K'
#define ICTIOC_GETDEV_INFO _IOR(ICT_IOCTL_MAGIC_NUM, 0, int)
#define ICTIOC_SETDEV_INFO _IOWR(ICT_IOCTL_MAGIC_NUM, 1, int)
#ifndef NULL
#define NULL (0)
#endif
typedef struct {
unsigned char *rw_buf;
unsigned char *ioctl_buf;
} user_data_type;
static struct cdev *pdev = NULL;
static dev_t dev;
static int major = -1;
static int minor = 2;
static int device_count = 2;
static struct class* led_class;
static struct semaphore sem;
static int icdev_open(struct inode * inode, struct file * file) {
user_data_type* userData = NULL;
printk("%s (pid=%d, comm=%s)\n", __func__, current->pid, current->comm);
userData = (user_data_type*)kmalloc(sizeof(user_data_type), GFP_KERNEL);
if(NULL == userData) {
return -ENOMEM;
}
userData->rw_buf =
(unsigned char *)kmalloc(BUF_SIZE + 1, GFP_KERNEL);
((user_data_type*)userData)->ioctl_buf =
(unsigned char *)kmalloc(BUF_SIZE + 1, GFP_KERNEL);
if(NULL == userData->rw_buf
|| NULL == userData->ioctl_buf) {
return -ENOMEM;
}
userData->rw_buf[0] = (unsigned char)(0xFF & current->pid);
userData->ioctl_buf[0] = (unsigned char)(0xFF & (current->pid >> 0));
file->private_data = (void*)userData;
return 0;
}
static int icdev_release(struct inode *inode, struct file * file)
{
user_data_type* userData = NULL;
printk("%s,%d\n",__func__,__LINE__);
userData = (user_data_type*)(file->private_data);
if(NULL != userData->ioctl_buf) {
kfree(userData->ioctl_buf);
}
if(NULL != userData->rw_buf) {
kfree(userData->rw_buf);
}
kfree(userData);
return 0;
}
static ssize_t icdev_read(struct file * file, char __user * buffer,
size_t size, loff_t * loff) {
int ret = 0;
char * kbuf = ((user_data_type*)(file->private_data))->rw_buf;
do {
if(size > BUF_SIZE) {
ret = -EFAULT;
break;
}
if(down_interruptible(&sem)) {
printk("no semaphore.\n");
ret = -ERESTARTSYS;
}
if(copy_to_user(buffer, kbuf, size)) {
printk("failed to copy_to_user\n");
ret = -EFAULT;
up(&sem);
break;
} else {
ret = size;
}
up(&sem);
} while(0);
printk("read: size=%d,return: %d\n", (int)size, ret);
return ret;
}
static ssize_t icdev_write(struct file * file, const char __user * buffer,
size_t size, loff_t * loff) {
int ret = size;
char * kbuf = ((user_data_type*)(file->private_data))->rw_buf;
do {
if(size > BUF_SIZE) {
ret = -ENOMEM;
}
if(down_interruptible(&sem)) {
ret = -ERESTARTSYS;
}
if(copy_from_user(kbuf,buffer,size)) {
ret = -EFAULT;
up(&sem);
break;
}
up(&sem);
} while (0);
printk("write: size=%d,return: %d\n", (int)size, ret);
return ret;
}
static long icdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
int ret = 0;
void __user *argp = (void __user *)arg;
char * kbuf = ((user_data_type*)filp->private_data)->ioctl_buf;
if(down_interruptible(&sem)) {
ret = -ERESTARTSYS;
}
switch(cmd) {
case ICTIOC_GETDEV_INFO:
put_user(kbuf[0], (int *)arg);
printk(KERN_INFO"copy to user: %c\n", kbuf[0]);
break;
case ICTIOC_SETDEV_INFO:
get_user(kbuf[0], (char __user *)argp);
printk(KERN_INFO"Set as: %c\n", kbuf[0]);
break;
default:
break;
}
up(&sem);
return ret;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = icdev_open,
.release = icdev_release,
.read = icdev_read,
.write = icdev_write,
.unlocked_ioctl = icdev_ioctl,
};
static int __init icdev_init(void) {
int ret = 0;
if(dev) {
ret = register_chrdev_region(dev, device_count, DEVICE_NAME);
} else {
ret = alloc_chrdev_region(&dev, minor, device_count, DEVICE_NAME);
}
if(ret) {
printk("alloc_chrdev_region failed.\n");
goto ERROR_CDEV;
}
pdev = cdev_alloc();
if(NULL == pdev) {
printk("cdev_alloc failed.\n");
return -ENOMEM;
}
cdev_init(pdev,&fops);
ret = cdev_add(pdev, dev, device_count);
if(ret) {
printk("cdev_add failed.\n");
goto ERROR_ADD;
}
led_class = class_create(THIS_MODULE, "module_test3");
if ( NULL == device_create(led_class, NULL, dev, NULL, DEVICE_NAME)) {
printk("device_create failed.\n");
ret = -1;
goto ERROR_DEVICE;
}
sema_init(&sem, 1);
major = MAJOR(dev);
printk("cdev_demo_init ok. MAJOR is %d\n",MAJOR(dev));
return ret;
ERROR_DEVICE:
cdev_del(pdev);
ERROR_ADD:
unregister_chrdev_region(dev, device_count);
ERROR_CDEV:
cdev_del(pdev);
return ret;
}
static void __exit icdev_exit(void) {
printk("%s,%d\n",__func__,__LINE__);
device_destroy(led_class, dev);
class_destroy(led_class);
unregister_chrdev_region(MKDEV(major,minor), device_count);
cdev_del(pdev);
}
module_init(icdev_init);
module_exit(icdev_exit);
MODULE_LICENSE("GPL");用户空间代码
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h> //alarm()
#include<stdlib.h> //exit()
#include <sys/ioctl.h>
#define BUFFER_SIZE (1024)
#define DEVICE_NAME "/dev/icdev"
#define ICT_SUCCESS 0
#define ICT_ERROR_DEV 1
#define ICT_ERROR_PARAM 2
#define ICT_ERROR_IOCTL 3
#define ICT_IOCTL_MAGIC_NUM 'K'
#define ICTIOC_GETDEV_INFO _IOR(ICT_IOCTL_MAGIC_NUM, 0, int)
#define ICTIOC_SETDEV_INFO _IOWR(ICT_IOCTL_MAGIC_NUM, 1, int)
#define ICT_DEV_FILE "/dev/ictdev"
void timer(int sig) {
if(SIGALRM == sig) {
printf("SIGALRM\n");
exit(0);
}
return ;
}
int main(int argc,char* argv[]) {
int ret = -10086;
int devInfo;
signal(SIGALRM, timer);
alarm(10);
int fd = open(DEVICE_NAME, O_RDWR /*| O_NONBLOCK*/);
if(0 > fd) {
perror("open\n");
return -1;
}
printf("open %s ,fd=%d\n",DEVICE_NAME, fd);
char rbuf[BUFFER_SIZE + 1] = {0};
ret = read(fd,rbuf,BUFFER_SIZE);
printf("read ret = %d,errno = %d\n", ret, errno);
char buf[] = "1234567891111111111111111";
ret = write(fd,buf,sizeof(buf));
printf("write ret = %d,errno = %d\n", ret, errno);
// ioctl test
int ict_fd = fd;
if(ioctl(ict_fd, ICTIOC_GETDEV_INFO, &devInfo) < 0) {
printf("Get ICT device info fail.\n");
return ICT_ERROR_IOCTL;
}
printf("ICT device info is: %d\n", devInfo);
devInfo = 99;
if(ioctl(ict_fd, ICTIOC_SETDEV_INFO, &devInfo)) {
printf("Set ICT device info fail.\n");
return ICT_ERROR_IOCTL;
}
if(ioctl(ict_fd, ICTIOC_GETDEV_INFO, &devInfo) < 0) {
printf("Re-get ICT device info fail.\n");
return ICT_ERROR_IOCTL;
}
printf("Re-get ICT after set: %d\n", devInfo);
close(fd);
return 0;
}Compilation of kernel space and user spaceMakefile书写,可以参考我的另外一篇文章:
https://blog.csdn.net/suixin______/article/details/117130033?spm=1001.2014.3001.5501
边栏推荐
- SCNet:Semantic Consistency Networks for 3D Object Detection
- 华为adb wifi调试断线问题解决
- Rethinking LiDAR Object Detection in adverse weather conditions
- 基于uniapp开发的聊天界面
- GBase 8s存储结构简介及空间管理
- 安全帽识别-施工安全的“监管者”
- 微信小程序canvas画图,保存页面为海报
- 梅科尔工作室-DjangoWeb 应用框架+MySQL数据库第四次培训
- CVPR2022——Not All Points Are Equal : IA-SSD
- Redis持久化方案RDB详解
猜你喜欢

CVPR2022——A VERSATILE MULTI-VIEW FRAMEWORK

.Net6 MiNiApi +EFCore6.0高B格操作的WebApi

Joint 3D Instance Segmentation and Object Detection for Autonomous Driving

websocket聊天通讯(全局封装)

CNN-based Point Cloud De-Noising

更新GreenDAO实体类导致的编译错误

order by注入,limit注入,宽字节注入

OSPF综合实验

梅科尔工作室-HarmonyOS应用开发的第二次培训

mysq基础语句+高级操作(学这篇就够了)
随机推荐
mysql 间隙锁(GAP-LOCK)演示
关于安全帽识别系统,你需要知道的选择要点
Nodered系列—使用node-red-node-mysql写入mysql详细步骤
Redis持久化方案RDB详解
lvs的keepalived
《现代密码学》学习笔记——第七章 密钥管理[二]数字证书
emqx安装及mqttx连接使用
HUE部署
梅科尔工作室-DjangoWeb 应用框架+MySQL数据库第二次培训
RIP综合实验
OSPF综合实验
【mysql】查询不区分大小写(用户密码登录不区分大小写)
MPLS 实验
正则(三剑客和文本处理工具)
>>技术应用:*aaS服务定义
Windows64位MySQL配置式安装(绿色版)
GBase 8s 执行计划查询分析
mysql基本概念之事务
梅科尔工作室-HarmonyOS应用开发的第二次培训
centos—docker安装mysql