内核实验(七):使用内核KFIFO环形缓冲区机制

news/2024/11/6 17:23:34/

一、篇头

继续使用qemu调试内核的实验。

二、系列文章

略……

三、实验环境

  • 编译服务器+NFS:ubuntu 22.04
  • Qemu 虚拟机:Linux version 5.15.102 + Buysbox 1.3.36 + ARM_32bit

Qemu 启动命令:qemu-system-arm -nographic -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage -initrd …/busybox/rootfs.ext4.img.gz -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb

四、源码

4.1 KFIFO介绍

Linux内核实现了一个称为KFIFO的环形缓冲区的机制,它可以在一个读者线程和一个写者线程并发执行的场景下,无须使用额外的加锁来保证环形缓冲区的数据安全。同时由此机制来管理了缓冲区的使用情况,省去许多是,特别方便。

KFIFO提供的接口函数定义在include/linux/kfifo.h文件中。

4.1.1 声明及定义:DEFINE_KFIFO(fifo, type, size)

/*** DEFINE_KFIFO - macro to define and initialize a fifo* @fifo: name of the declared fifo datatype* @type: type of the fifo elements* @size: the number of elements in the fifo, this must be a power of 2** Note: the macro can be used for global and local fifo data type variables.*/
#define DEFINE_KFIFO(fifo, type, size) \DECLARE_KFIFO(fifo, type, size) = \(typeof(fifo)) { \{ \{ \.in	= 0, \.out	= 0, \.mask	= __is_kfifo_ptr(&(fifo)) ? \0 : \ARRAY_SIZE((fifo).buf) - 1, \.esize	= sizeof(*(fifo).buf), \.data	= __is_kfifo_ptr(&(fifo)) ? \NULL : \(fifo).buf, \} \} \}

4.1.2 用户写: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); \
}) \
)

4.1.3 用户读: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_int_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); \
}) \
)

4.2 驱动源码

  • 文件名:linux-stable\my_kmodules\test_5.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/kfifo.h>#define MY_DEV_NAME "my_dev"DEFINE_KFIFO(my_kfifo, char, 128);
static char kbuf[128];static int test_5_open(struct inode *inode, struct file *file)
{int major = MAJOR(inode->i_rdev);int minor = MINOR(inode->i_rdev);pr_info("%s: major=%d, minor=%d\n", __func__, major, minor);return 0;
}static int test_5_release(struct inode *inode, struct file *file)
{pr_info("%s \n", __func__);return 0;
}static ssize_t test_5_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{int ret;unsigned int copied_count=0;pr_info("%s \n", __func__);ret = kfifo_to_user(&my_kfifo, buf,  count, &copied_count);if(ret != 0) {return -EIO;}pr_info("%s :%s, count=%d, copied_count=%d\n", __func__, my_kfifo.buf,  count, copied_count);return copied_count;
}static ssize_t test_5_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{int ret;unsigned int copied_count=0;pr_info("%s \n", __func__);ret = kfifo_from_user(&my_kfifo, buf, count, &copied_count);if(ret != 0) {return -EIO;}pr_info("%s , my_kfifo.buf=%s\n", __func__, my_kfifo.buf);//注意:使用用户空间的buf,需要先copy_from_userret = copy_from_user(kbuf, buf, copied_count);pr_info("%s :%s, count=%d, copied_count=%d, ret=%d\n", __func__, kbuf,  count, copied_count, ret);return copied_count;
}static const struct file_operations test_fops = {.owner = THIS_MODULE,.open = test_5_open,.release = test_5_release,.read = test_5_read,.write = test_5_write
};static struct miscdevice test_5_misc_device ={.minor = MISC_DYNAMIC_MINOR,.name = MY_DEV_NAME,.fops = &test_fops,
};static int __init test_5_init(void)
{int ret;pr_info("test_5_init\n");ret = misc_register(&test_5_misc_device);if (ret != 0 ) {pr_err("failed to misc_register");return ret;}pr_err("Minor number = %d\n", test_5_misc_device.minor);return 0;
}static void __exit test_5_exit(void)
{pr_info("test_5_exit\n");misc_deregister(&test_5_misc_device);
}module_init(test_5_init);
module_exit(test_5_exit);MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("szhou <66176468@qq.com>");
MODULE_DESCRIPTION("test_5, 使用misc、KFIFO开发设备驱动");

4.3 APP源码

本次实验,直接使用 echo /cat 负责设备的写/读。

4.4 Makefile

  • 文件名:linux-stable\my_kmodules\Makefile
KDIR := /home/szhou/works/qemu_linux/linux-stableobj-m := test_1.o test_2.o test_3.o test_4.o  test_5.o
all :$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) cleanrm -f *.ko

五、编译及部署

1)执行驱动KO编译
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ make 
make -C /home/szhou/works/qemu_linux/linux-stable M=/home/szhou/works/qemu_linux/linux-stable/my_kmodules modules
make[1]: Entering directory '/home/szhou/works/qemu_linux/linux-stable'CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_5.oMODPOST /home/szhou/works/qemu_linux/linux-stable/my_kmodules/Module.symversLD [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_5.ko
make[1]: Leaving directory '/home/szhou/works/qemu_linux/linux-stable'
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ cp test_5.ko ~/works/nfs_share/
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ (2)将KO和APP存放到NFS共享目录
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ cp test_5.ko ~/works/nfs_share/

六、运行及测试

1)启动之前编译组建的QEMU虚拟机
----------------------------------------
Welcome to szhou's tiny Linux
----------------------------------------Please press Enter to activate this console.2)挂载NFS共享目录
~ #  mount -t nfs -o nolock 192.168.3.67:/home/szhou/works/nfs_share /mnt(3) 加载ko
~ # cd /mnt/
/mnt # insmod test_5.ko 
test_5: loading out-of-tree module taints kernel.
test_5_init
Minor number = 125
/mnt # 
/mnt # mdev  -s
/mnt # (4)写入字符串 
/mnt # echo "hellow kfifo" >  /dev/my_dev 
test_5_open: major=10, minor=125
test_5_write 
test_5_write , my_kfifo.buf=hellow kfifotest_5_write :hellow kfifo
, count=13, copied_count=13, ret=0
test_5_release 
/mnt # (5)读取字符串 
/mnt # cat /dev/my_dev 
test_5_open: major=10, minor=125
test_5_read 
test_5_read :hellow kfifo
, count=4096, copied_count=13
hellow kfifo
test_5_read 
test_5_read :hellow kfifo
, count=4096, copied_count=0
test_5_release 
/mnt # 

操作画面如下图:

在这里插入图片描述


http://www.ppmy.cn/news/358990.html

相关文章

layui vue 在一起用的坑 select

问题是这样的&#xff0c; <div class"layui-btn-group"><button class"layui-btn " click"businessChange(bc01)":class"businessbc01?layui-btn-normal:layui-btn-primary">1</button><button class"lay…

Tas1020bv1p1开发板,隆重推出!

文章来自,http://www.dsp-mcu.com 原文地址 http://blue-culture.org/comsenz/bbs/viewthread.php?tid224&extra Tas1020bv1p1开发板&#xff0c;隆重推出&#xff01; Tas1020bv1p1开发板 Tas1020B 开发版,v1p1版本终于隆重推出了!Tas1020B BC01开发板&#xff0c;具备…

VMIX如何RTMP推流给灵派编码器

本文链接&#xff1a;https://blog.csdn.net/weixin_45326556/article/details/131181058 第三方设备&#xff08;例如vMix&#xff0c;OBS&#xff09;如何RTMP推流给灵派编码器 1. 灵派编码器内置RTMP-SERVER2. 其他设备RTMP推流给灵派编码器方法3. 如何使用第三方推上来的RT…

【详解】NLP之常用数据集详解

GLUE数据集合的介绍: 自然语言处理&#xff08;NLP&#xff09;主要自然语言理解&#xff08;NLU&#xff09;和自然语言生成&#xff08;NLG&#xff09;。GLUE&#xff08;General Language Understanding Evaluation&#xff09;由纽约大学, 华盛顿大学, Google联合推出, 涵…

内核实验(六):使用misc框架,实现简单字符设备驱动

内核实验&#xff08;六&#xff09;&#xff1a;使用misc框架&#xff0c;实现简单字符设备驱动 一、篇头 使用自行组建的Qemu Linux虚拟机&#xff0c;提升效率&#xff0c;继续内核实验。本文将学习使用misc框架来创建设备驱动。 在linux系统中&#xff0c;主设备号&#…

内核实验(五):传统简单字符设备驱动

文章目录 一、篇头二、源码2.1 驱动关键部分2.2 APP&#xff1a;test\_3\_app.c2.3 驱动完整源码2.4 Makefile 三、编译3.1 编译ko3.2 编译app 四、测试4.1 部署4.2 测试4.2.1 启动qemu虚拟机4.2.2 运行测试文件4.2.3 查看设备情况 五、篇尾 一、篇头 目标是把内核相关部分的实…

内核实验(八):实现O-NONBLOCK非阻塞读写

一、篇头 继续使用qemu调试内核的实验。本章复习阻塞与非阻塞IO的概念和机制&#xff0c;然后对之前实验&#xff08;七&#xff09;的代码做少许修改&#xff0c;来实现非阻塞的IO读写。 二、系列文章 略…… 三、实验环境 编译服务器NFS&#xff1a;ubuntu 22.04Qemu 虚…

BCB6

很久没有摸c builder了&#xff0c;因同事需求需要修改东西&#xff0c;再次搭建环境&#xff0c;碰到些问题&#xff0c;以此做为记录便于以后翻看。 视频会议控制台的项目&#xff0c;使用了第三方组件AlphaControls&#xff0c;需要配置Project->Options->Directories…