linux环形缓冲区kfifo实践1

news2024/10/6 14:32:53

本次实验使用的kfifo相关宏

struct __kfifo {
	unsigned int	in;
	unsigned int	out;
	unsigned int	mask;
	unsigned int	esize;
	void		*data;

	
};
/*
 * define compatibility "struct kfifo" for dynamic allocated fifos
 */
struct kfifo __STRUCT_KFIFO_PTR(unsigned char, 0, void);

判空:kfifo_is_empty

/**
 * kfifo_is_empty - returns true if the fifo is empty
 * @fifo: address of the fifo to be used
 */
#define	kfifo_is_empty(fifo) \
({ \
	typeof((fifo) + 1) __tmpq = (fifo); \
	__tmpq->kfifo.in == __tmpq->kfifo.out; \
})

 判满:kfifo_is_full

/**
 * kfifo_is_full - returns true if the fifo is full
 * @fifo: address of the fifo to be used
 */
#define	kfifo_is_full(fifo) \
({ \
	typeof((fifo) + 1) __tmpq = (fifo); \
	kfifo_len(__tmpq) > __tmpq->kfifo.mask; \
})

判断fifo可用空间大小 kfifo_avail

/**
 * kfifo_avail - returns the number of unused elements in the fifo
 * @fifo: address of the fifo to be used
 */
#define	kfifo_avail(fifo) \
__kfifo_uint_must_check_helper( \
({ \
	typeof((fifo) + 1) __tmpq = (fifo); \
	const size_t __recsize = sizeof(*__tmpq->rectype); \
	unsigned int __avail = kfifo_size(__tmpq) - kfifo_len(__tmpq); \
	(__recsize) ? ((__avail <= __recsize) ? 0 : \
	__kfifo_max_r(__avail - __recsize, __recsize)) : \
	__avail; \
}) \
)

 为kfifo分配空间kfifo_alloc 

和kfifo_free成对使用。

/**
 * kfifo_alloc - dynamically allocates a new fifo buffer
 * @fifo: pointer to the fifo
 * @size: the number of elements in the fifo, this must be a power of 2
 * @gfp_mask: get_free_pages mask, passed to kmalloc()
 *
 * This macro dynamically allocates a new fifo buffer.
 *
 * The numer of elements will be rounded-up to a power of 2.
 * The fifo will be release with kfifo_free().
 * Return 0 if no error, otherwise an error code.
 */
#define kfifo_alloc(fifo, size, gfp_mask) \
__kfifo_int_must_check_helper( \
({ \
	typeof((fifo) + 1) __tmp = (fifo); \
	struct __kfifo *__kfifo = &__tmp->kfifo; \
	__is_kfifo_ptr(__tmp) ? \
	__kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \
	-EINVAL; \
}) \
)

释放为kfifo分配的空间kfifo_free

/**
 * kfifo_free - frees the fifo
 * @fifo: the fifo to be freed
 */
#define kfifo_free(fifo) \
({ \
	typeof((fifo) + 1) __tmp = (fifo); \
	struct __kfifo *__kfifo = &__tmp->kfifo; \
	if (__is_kfifo_ptr(__tmp)) \
		__kfifo_free(__kfifo); \
})

 kfifo_from_user:复制用户空间的数据到kfifo

kfifo_from_user()宏用来将用户空间的数据写入环形缓冲区中,其中参数fifo表示使用哪个环形缓冲区;from 表示用户空间缓冲区的起始地址;len 表示要复制多少个元素;copied保存了成功复制元素的数量,通常用作返回值。

/**
 * kfifo_from_user - puts some data from user space into the fifo
 * @fifo: address of the fifo to be used
 * @from: pointer to the data to be added
 * @len: the length of the data to be added
 * @copied: pointer to output variable to store the number of copied bytes
 *
 * This macro copies at most @len bytes from the @from into the
 * fifo, depending of the available space and returns -EFAULT/0.
 *
 * Note that with only one concurrent reader and one concurrent
 * writer, you don't need extra locking to use these macro.
 */
#define	kfifo_from_user(fifo, from, len, copied) \
__kfifo_uint_must_check_helper( \
({ \
	typeof((fifo) + 1) __tmp = (fifo); \
	const void __user *__from = (from); \
	unsigned int __len = (len); \
	unsigned int *__copied = (copied); \
	const size_t __recsize = sizeof(*__tmp->rectype); \
	struct __kfifo *__kfifo = &__tmp->kfifo; \
	(__recsize) ? \
	__kfifo_from_user_r(__kfifo, __from, __len,  __copied, __recsize) : \
	__kfifo_from_user(__kfifo, __from, __len, __copied); \
}) \
)

 kfifo_to_user:复制kfifo中的数据到用户空间

kfifo_to_user()宏用来读出环形缓冲区的数据并且复制到用户空间中,其中参数fifo表示使用哪个环形缓冲区;to表示用户空间缓冲区的起始地址;len 表示要复制多少个元素;copied保存了成功复制元素的数量,通常用作返回值。

/**
 * kfifo_to_user - copies data from the fifo into user space
 * @fifo: address of the fifo to be used
 * @to: where the data must be copied
 * @len: the size of the destination buffer
 * @copied: pointer to output variable to store the number of copied bytes
 *
 * This macro copies at most @len bytes from the fifo into the
 * @to buffer and returns -EFAULT/0.
 *
 * Note that with only one concurrent reader and one concurrent
 * writer, you don't need extra locking to use these macro.
 */
#define	kfifo_to_user(fifo, to, len, copied) \
__kfifo_uint_must_check_helper( \
({ \
	typeof((fifo) + 1) __tmp = (fifo); \
	void __user *__to = (to); \
	unsigned int __len = (len); \
	unsigned int *__copied = (copied); \
	const size_t __recsize = sizeof(*__tmp->rectype); \
	struct __kfifo *__kfifo = &__tmp->kfifo; \
	(__recsize) ? \
	__kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize) : \
	__kfifo_to_user(__kfifo, __to, __len, __copied); \
}) \
)

 实验代码:

驱动代码:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/kfifo.h>

#define DEBUG_INFO(format, ...) printk("%s:%d -- "format"\n",\
__func__,__LINE__,##__VA_ARGS__)

struct ch5_kfifo_struct{
    struct miscdevice misc;
    struct file_operations fops;
    // struct __kfifo fifo;
    // DECLARE_KFIFO(fifo, char, 64);
    struct kfifo fifo;
    char buf[64];
};

static int ch5_open (struct inode *inode, struct file *file){
    struct ch5_kfifo_struct *p = (struct ch5_kfifo_struct *)container_of(file->f_op,struct ch5_kfifo_struct,fops);
    file->private_data = p;
    DEBUG_INFO("major = %d, minor = %d\n",MAJOR(inode->i_rdev),MINOR(inode->i_rdev));
    DEBUG_INFO("name = %s",p->misc.name);
    return 0;
}
static int ch5_release (struct inode *inode, struct file *file){
    DEBUG_INFO("close");
    return 0;
}

static ssize_t ch5_read (struct file *file, char __user *buf, size_t size, loff_t *pos){
    struct ch5_kfifo_struct *p __attribute__((unused)) = (struct ch5_kfifo_struct *)file->private_data;
    int ret;
    int actual_readed = 0;
    if(kfifo_is_empty(&p->fifo)){
        DEBUG_INFO("kfifo is null");
        return 0;
    }
    ret = kfifo_to_user(&p->fifo, buf, size, &actual_readed);
    if (ret){
        DEBUG_INFO("kfifo_to_user error");
		return -EIO;
    }
    
    DEBUG_INFO("size = %d,actual_readed = %d\n",size,actual_readed);

    memset(p->buf,0,sizeof(p->buf));
    ret = copy_from_user(p->buf, buf, actual_readed);
    
    if(ret != 0){
        DEBUG_INFO("copy_from_user error ret = %d\n",ret);
    }else{
        DEBUG_INFO("p->buf = %s\n",p->buf);
    }
    return 0;
}
static ssize_t ch5_write (struct file *file, const char __user *buf, size_t size, loff_t* pos){
    struct ch5_kfifo_struct *p __attribute__((unused)) = (struct ch5_kfifo_struct *)file->private_data;
    int actual_writed = 0;
    int ret;
    ret = kfifo_from_user(&p->fifo, buf, size, &actual_writed);
    if (ret){
        DEBUG_INFO("kfifo_from_user error");
		return -EIO;
    }
    DEBUG_INFO("actual_writed = %d\n",actual_writed);

    if(*pos == 0){
        *pos = size;
        return size;
    }
    *pos = *pos + size;
    return size;
}

struct ch5_kfifo_struct ch5_kfifo = {
    .misc = { 
        .name = "ch5-03-kfifo",
        .minor = MISC_DYNAMIC_MINOR,
    },
    .fops = {
        .owner = THIS_MODULE,
        .read = ch5_read,
        .write = ch5_write,
        .open = ch5_open,
        .release = ch5_release,
    },
};

static int __init ch5_init(void){
    int ret = 0;
    DEBUG_INFO("start init\n");
    ch5_kfifo.misc.fops = &ch5_kfifo.fops;
    ret = kfifo_alloc(&ch5_kfifo.fifo,
				64,
				GFP_KERNEL);
    if (ret) {
        DEBUG_INFO("kfifo_alloc error: %d\n", ret);
        ret = -ENOMEM;
        return ret;
    }
    DEBUG_INFO("kfifo_alloc ok");

    ret = misc_register(&ch5_kfifo.misc);
    if(ret < 0){
        DEBUG_INFO("misc_register error: %d\n", ret);
        return ret;
    }
    DEBUG_INFO("misc_register ok");
    return 0;
}

static void __exit ch5_exit(void){
    DEBUG_INFO("exit\n");
    misc_deregister(&ch5_kfifo.misc);
    kfifo_free(&ch5_kfifo.fifo);
}

module_init(ch5_init);
module_exit(ch5_exit);

MODULE_LICENSE("GPL");

应用代码

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- "format"\n",\
__func__,__LINE__,##__VA_ARGS__)

int main(int argc, char**argv){
    int fd;
    char buf[1024];
    char *filename = NULL;
    if(argc < 2){
        filename = "/dev/ch5-03-kfifo";
    }else{
        filename = argv[1];
    }

    fd = open(argv[1], O_WRONLY);
    if(fd < 0){
        perror("open");
        return -1;
    }
    write(fd, filename, strlen(filename));
    memset(buf, 0, sizeof(buf));
    close(fd);

    fd = open(argv[1], O_RDONLY);
    if(fd < 0){
        perror("open");
        return -1;
    }
    memset(buf, 0, sizeof(buf));
    read(fd, buf, sizeof(buf));
    DEBUG_INFO("buf = %s",buf);
    close(fd);

    return 0;
}

makefile

modname:=ch5-03-kfifo
obj-m:=$(modname).o
PWD :=$(shell pwd)
MAKE :=make
KERNELDIR = /home/lkmao/running_github/runninglinuxkernel_4.0
CROSS_COMPILE=arm-linux-gnueabi-
ARCH=arm
all:
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules
	cp $(modname).ko /home/lkmao/running_github/runninglinuxkernel_4.0/kmodules
	arm-linux-gnueabi-gcc -o app app.c --static
	cp app /home/lkmao/running_github/runninglinuxkernel_4.0/kmodules

clean:
	rm -rf $(modname).ko *.o *mod* \.*cmd *odule* .tmp_versions *.ko
.PHONY: all clean

测试结果:

 小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/857265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.Eclipse的Ctrl+F快捷键搜索面板全功能详解

Eclipse的CtrlF快捷键详解 1.搜索/替换方向 Forward&#xff1a;向前 Backward&#xff1a;向后 2.范围&#xff1a;Scope All&#xff1a;全部&#xff08;当前文件&#xff09; Selected lines&#xff1a;选中的几行 3.选项&#xff1a;Options Case sensiti…

护眼灯作用大吗?2023这样的护眼台灯对孩子眼睛好

可以肯定的是&#xff0c;护眼灯一般可以达到护眼的效果。 看书和写字时&#xff0c;光线应适度&#xff0c;不宜过强或过暗&#xff0c;护眼灯光线较柔和&#xff0c;通常并不刺眼&#xff0c;眼球容易适应&#xff0c;可以防止光线过强或过暗导致的用眼疲劳。如果平时生活中…

嵌入式Linux驱动开发系列六:Makefile

Makefile是什么? gcc hello.c -o hello gcc aa.c bb.c cc.c dd.c ... make工具和Makefile make和Makefile是什么关系&#xff1f; make工具:找出修改过的文件&#xff0c;根据依赖关系&#xff0c;找出受影响的相关文件&#xff0c;最后按照规则单独编译这些文件。 Make…

SpringBoot + Vue 简单前后端分离项目的增删改查

SpringBoot 是提供一种快速整合的方式 文章目录 前期准备新建数据库新建项目config 配置包application.yml 后端业务开发po 类mapper 接口service 接口service 实现类controller 类 测试增加数据测试删除数据测试修改数据测试查新数据测试 前端页面开发查询页面删除功能添加页面…

2023年国内低代码平台盘点:TOP 10活跃领军者,助力企业智能应用快速构建

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

实战实例 | 郑航无人驾驶航空器系统工程专业综合实验平台建设项目

郑州航空工业管理学院 无人驾驶航空器系统工程专业综合实验平台建设项目 关键词&#xff1a;飞控开发、仿真训练、组装调试、无人机集群 解决方案&#xff1a;多智能体协同创新实验室解决方案 | 项目背景 无人机行业是当前发展迅速、技术综合性强和应用前景好的朝阳行业。基…

CCLINK IE FIELD BASIC转MODBUS-TCP网关cclink与以太网的区别

协议的不同&#xff0c;数据读取困难&#xff0c;这是很多生产管理系统的难题。但是现在&#xff0c;捷米JM-CCLKIE-TCP通讯网关&#xff0c;让这个问题变得非常简单。这款通讯网关可以将各种MODBUS-TCP设备接入到CCLINK IE FIELD BASIC网络中&#xff0c;连接到MODBUS-TCP总线…

echo用法、linxu课堂练习题、作业题

一、课堂练习 练习一&#xff1a; 4、普通用户修改密码&#xff1a; root修改密码&#xff1a; 5、修改主机名&#xff1a;hostnamectl hostname 主机名 查看&#xff1a;hostnamectl或者cat etc/hostname 练习二&#xff1a; 1、 mkdir /root/html touch /root/html/index.…

基于摄影测量的数字孪生建设

在这篇博文中&#xff0c;我们将了解如何使用无人机拍摄的照片在数字孪生中创建现实世界环境的 3D 模型。 数字孪生是物理系统的虚拟表示&#xff0c;定期更新数据以模仿其所表示的资产的结构、状态和行为。 数字孪生可以通过在单一管理平台中连接多个数据源并提供可行的见解来…

十一、结合数字孪生与时间技术进行多维分析设计与实施

大数据可视化中心以主题为分析对象,选择业务分类下的某个主题,可以在数据面板中展示其二维图表,在地图中标记其空间分布,并叠加其相应的二维或三维图层。 1、界面设计 其主界面设计详上图,各部分功能介绍如下: 1.1、主题与图层面板,从上到下,从左到右分别是: ①折…

Linux--core dump打开的情况下,运行下面的代码,会发生什么?

代码&#xff1a; #include <iostream> #include <signal.h> #include <unistd.h>using namespace std;void catchSig(int signum) {cout<< "进程捕捉到了一个信号&#xff0c;正在处理中&#xff1a; "<< signum << " p…

基于Spring Boot的招聘网站的设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的招聘网站的设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java springboot框…

Linux 进程间通信, 管道

文章目录 前言一、常见的进程间通信方式二、如何实现管道通信三、示例代码解析四、管道的读写行为总结 前言 在多进程编程中&#xff0c;进程间通信&#xff08;Inter-Process Communication&#xff0c;IPC&#xff09;是一种重要的技术手段&#xff0c;它使得不同进程可以安…

函数的声明和定义

1、函数声明 //告诉编译器有一个函数叫什么&#xff0c;参数是什么&#xff0c;返回类型是什么。但是具体是不是存在&#xff0c;函数声明决定不了。 //函数的声明一般出现在函数的使用之前。要满足先声明后使用。 //函数的声明一般要放在头文件中的。 2、函数的定义 //函数…

Linux(进程间通信详解)

进程间通信&#xff0c;顾名思义&#xff0c;就是进程与进程之间互通信交流&#xff0c;OS保证了各进程之间相互独立&#xff0c;但这不意味着进程与进程之间就互相隔离开&#xff0c;在不少的情况下&#xff0c;进程之间需要相互配合共同完成某项6任务&#xff0c;这就要求各进…

8月9日算法刷题【6道题】

8月9日算法刷题 一、排序1. 成绩排序&#xff08;清华大学考研机试题&#xff09;考点&#xff1a;结构体排序在结构体中定义排序使用比较器定义排序 注意问题&#xff1a;需要处理 值相等时 先后顺序 2. 成绩排序2( 清华大学考研机试题 )1. 从尾到头打印链表本题考点栈 2. 在O…

hgdbdevelop弹窗无法使用

瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Microsoft Windows (64-bit) 10 版本&#xff1a;4.5 文档用途 解决双击exe程序出现弹窗&#xff0c;点击Disable Modules and Continue没反应 详细信息 1.打开管理工具exe程序&#xff0c;出现弹窗如下图&…

【运维小能手】交换机二层环路问题如何处理

1 网络业务故障&#xff0c;如何确认存在环路&#xff1f; 网络业务故障后&#xff0c;如发生二层环路&#xff0c;通常会存端口流量数据风暴和反复大量的MAC漂移现象。因此&#xff0c;在骨干链路所在的节点&#xff0c;通过如下三步操作&#xff1a; 图1&#xff1a;环…

向量检索在大模型应用场景的技术和实践

一、向量检索应用简介 向量是多维数学空间里的一个点&#xff0c;在各维度上的坐标的一串数字。这个点就是来源于真实世界的物体进行数字化之后在数学空间的投影。那么不同点之间有一个数学关系&#xff0c;就是距离&#xff0c;距离远近就代表两个物体的相似程度。 非结构化数…

Semantic and Syntactic Enhanced Aspect Sentiment Triplet Extraction

创新点 图-序列双重表示: 通过将句子中的语义和句法关系表示为图&#xff0c;并使用图神经网络&#xff08;GNNs&#xff09;进行编码&#xff0c;同时保留原始句子的顺序信息&#xff0c;S3E2能够更精确地捕捉三元组元素之间的复杂关系。许多传统方法可能只依赖于线性或浅层表…