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);
相关推荐
chlk1231 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑1 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件1 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号1 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash2 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI2 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行3 天前
Linux和window共享文件夹
linux
木心月转码ing3 天前
WSL+Cpp开发环境配置
linux
崔小汤呀4 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应4 天前
vi编辑器使用
linux·后端·操作系统