linux scatterlist阅读三

sg_copy_buffer

函数定义:

c 复制代码
/**
 * sg_copy_buffer - Copy data between a linear buffer and an SG list
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buf:		 Where to copy from
 * @buflen:		 The number of bytes to copy
 * @skip:		 Number of bytes to skip before copying
 * @to_buffer:		 transfer direction (true == from an sg list to a
 *			 buffer, false == from a buffer to an sg list
 *
 * Returns the number of copied bytes.
 *
 **/
size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen, off_t skip, bool to_buffer)
{
	unsigned int offset = 0;
	struct sg_mapping_iter miter;
	unsigned int sg_flags = SG_MITER_ATOMIC;

	if (to_buffer)
		sg_flags |= SG_MITER_FROM_SG;
	else
		sg_flags |= SG_MITER_TO_SG;

	sg_miter_start(&miter, sgl, nents, sg_flags);

	if (!sg_miter_skip(&miter, skip))
		return false;

	while ((offset < buflen) && sg_miter_next(&miter)) {
		unsigned int len;

		len = min(miter.length, buflen - offset);

		if (to_buffer)
			memcpy(buf + offset, miter.addr, len);
		else
			memcpy(miter.addr, buf + offset, len);

		offset += len;
	}

	sg_miter_stop(&miter);

	return offset;
}
EXPORT_SYMBOL(sg_copy_buffer);

函数实现比较复杂,还涉及了struct sg_mapping_iter 结构体,这里比较重要的是skip参数,是指拷贝时跳过的字节数。

sg_copy_from_buffer

函数定义:

c 复制代码
/**
 * sg_copy_from_buffer - Copy from a linear buffer to an SG list
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buf:		 Where to copy from
 * @buflen:		 The number of bytes to copy
 * Returns the number of copied bytes.
 **/
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,const void *buf, size_t buflen)
{
	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, 0, false);
}
EXPORT_SYMBOL(sg_copy_from_buffer);

从buf缓冲区里拷贝buflen长度的数据到sgl表里,返回值是成功拷贝到字节数

sg_copy_to_buffer

c 复制代码
/**
 * sg_copy_to_buffer - Copy from an SG list to a linear buffer
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buf:		 Where to copy to
 * @buflen:		 The number of bytes to copy
 *
 * Returns the number of copied bytes.
 *
 **/
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
			 void *buf, size_t buflen)
{
	return sg_copy_buffer(sgl, nents, buf, buflen, 0, true);
}
EXPORT_SYMBOL(sg_copy_to_buffer);

sg_pcopy_from_buffer

c 复制代码
/**
 * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buf:		 Where to copy from
 * @buflen:		 The number of bytes to copy
 * @skip:		 Number of bytes to skip before copying
 *
 * Returns the number of copied bytes.
 *
 **/
size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents, const void *buf, size_t buflen, off_t skip)
{
	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, skip, false);
}
EXPORT_SYMBOL(sg_pcopy_from_buffer);

sg_pcopy_to_buffer

c 复制代码
/**
 * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buf:		 Where to copy to
 * @buflen:		 The number of bytes to copy
 * @skip:		 Number of bytes to skip before copying
 *
 * Returns the number of copied bytes.
 *
 **/
size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,void *buf, size_t buflen, off_t skip)
{
	return sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
}
EXPORT_SYMBOL(sg_pcopy_to_buffer);

sg_zero_buffer

把skip后面的数据清0,比如sgl里面的数据是"abcde",skip等于2,调用函数以后,sgl里面的数据是"ab"

c 复制代码
/**
 * sg_zero_buffer - Zero-out a part of a SG list
 * @sgl:		 The SG list
 * @nents:		 Number of SG entries
 * @buflen:		 The number of bytes to zero out
 * @skip:		 Number of bytes to skip before zeroing
 *
 * Returns the number of bytes zeroed.
 **/
size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents,
		       size_t buflen, off_t skip)
{
	unsigned int offset = 0;
	struct sg_mapping_iter miter;
	unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;

	sg_miter_start(&miter, sgl, nents, sg_flags);

	if (!sg_miter_skip(&miter, skip))
		return false;

	while (offset < buflen && sg_miter_next(&miter)) {
		unsigned int len;

		len = min(miter.length, buflen - offset);
		memset(miter.addr, 0, len);

		offset += len;
	}

	sg_miter_stop(&miter);
	return offset;
}
EXPORT_SYMBOL(sg_zero_buffer);

最后来个demo,看看怎么使用。

c 复制代码
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/hdreg.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>

//struct sg_table sgt;

struct scatterlist *sgl;
void *buf;

/* 驱动出口函数 */
static int __init ramdisk_init(void)
{
	int i;
	void *buffer;
	struct scatterlist *sg;
	printk("sg init\n");

	sgl = (struct scatterlist *)kmalloc(sizeof(struct scatterlist) * 1, GFP_KERNEL);
	if(!sgl)
		return -1;

	buf = kmalloc(1000, GFP_KERNEL);
	if(!buf)
		return -1;

	buffer = kmalloc(100, GFP_KERNEL);
	if(!buffer)
		return -1;

	memset(buffer, 0, 100);
	memcpy(buffer, "hello world", 12);

	void *p;
	sg_init_one(sgl, buf, 1000);
	for_each_sg(sgl, sg, 1, i) {
		//sg_pcopy_from_buffer(sg, 1, buffer, 100, 5);
		sg_copy_from_buffer(sg, 1, buffer, 100);
		p = sg_virt(sg);
		//p = p + 5;
		
		printk("p = %s\n", (char *)p);

		memset(buffer, 0, 100);
		sg_pcopy_to_buffer(sg, 1, buffer, 100, 6);
		printk("buffer = %s\n", (char *)buffer);
	}

	kfree(buffer);

	return 0;
}

/* 驱动出口函数 */
static void __exit ramdisk_exit(void)
{
	printk("sg exit\n");
	kfree(buf);
	kfree(sgl);
}

module_init(ramdisk_init);
module_exit(ramdisk_exit);
相关推荐
韩楚风2 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学2 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO2 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu72 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我2 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、2 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程2 小时前
Linux中环境变量
linux
挥剑决浮云 -3 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
小O_好好学4 小时前
CentOS 7文件系统
linux·运维·centos
x晕x5 小时前
Linux dlsym符号查找疑惑分析
linux·运维·服务器