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);
相关推荐
大G哥1 小时前
python 数据类型----可变数据类型
linux·服务器·开发语言·前端·python
BillKu1 小时前
Linux设置Nginx开机启动
linux·运维·nginx
baidu_375528812 小时前
光感传感器 芯片stk3171 linux驱动程序
linux·运维·服务器
飞腾开发者2 小时前
飞腾平台Arm NN软件栈安装使用指南
linux·运维·人工智能·机器学习·计算机视觉
夜暝2 小时前
Iotop使用
linux
鸠摩智首席音效师2 小时前
.NET Core 应用程序如何在 Linux 中创建 Systemd 服务 ?
linux·运维·.netcore
不是三毛没有半3 小时前
Centos 7 安装wget
linux
叫我龙翔3 小时前
【计网】实现reactor反应堆模型 --- 多线程方案优化 ,OTOL方案
linux·运维·网络
mit6.8243 小时前
[Docker#9] 存储卷 | Volume、Bind、Tmpfs | -v/mount | MySQL 灾难恢复 | 问题
linux·运维·docker·容器·架构
WangYaolove13144 小时前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python