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);