字符设备驱动程序之三

7. read和write方法

read和write原型:

ssize_t (*read)( struct file *filp, char __user *buff, size_t count, loff_t *offp);

ssize_t (*write)( struct file *,filp char __user *,buff size_t count, loff_t *offp);

需要注意的是参数buff是用户空间的指针,内核代码不能直接引用其中的内容。原因如下:

1) 随着驱动程序所运行的架构不同或者内核配置不同,在内核模式中运行时,用户空间的指针可能是无效的。

2) 即使该指针在内核空间代表相同的东西,但是用户空间内存是分页的,而在系统调用,涉及到得内存可能不在RAM中。这个将导致页错误。

scddp的read和write代码要做的工作就是在用户地址空间和内核地址空间之间进行整段数据的拷贝。

unsigned long copy_to_user(void __user *to, const void *from,unsigned long count);

unsigned long copy_from_user(void *to, const void __user *from,unsigned long count);

这两个函数的作用并不限于在内核空间和用户空间拷贝数据,它们还检查用户空间的指针是否有效。如果不需要检查用户空间指针,可以使用__ copy_to_user和__ copy_from_user。

注意:访问用户空间的任何函数都必须是可重入的,并且必须能和其它驱动程序函数并发执行,必须处于能够合法休眠的状态。read和write系统调用都会更新*offp所表示的文件位置,而pread和pwrite系统调用是从一个给定的文件偏移开始操作,不会修改文件位置(它们会传入一个指针,该指针指向用户提供的位置,而且丢弃驱动程序所做的任何修改)。出错时,read和write都会返回一个负值。如果在正确传输了部分数据之后发生了错误,则返回值必须是成功传输的字节数,但这个错误只能在下一次函数调用时才会得到报告。

 

7.1. read方法

调用程序对read方法的返回值解释如下:

1)如果返回值等于read系统调用的count参数,则表示所请求的字节数传输成功。

2)如果返回值是正的,但是比count小,则表示只有部分数据成功传送。大部分情况下,程序会重新读数据。例如,如果用fread函数读数据,这个函数会不断地调用系统调用,直到所有数据传输完成。

3)如果返回值是0,则表示已经到达文件尾部

4)负值则表示发生了错误。

 

7.2. write方法

调用程序对write方法的返回值解释如下:

1) 如果返回值等于read系统调用的count参数,则表示所请求的字节数传输成功。

2) 如果返回值是正的,但是比count小,则表示只有部分数据成功传送。程序可能会再次试图写下余下的数据。

4) 如果返回值是0,则表示什么也没有写入

5) 负值则表示发生了错误。

 

8. readv和writev方法

Unix系统很早就支持这两个可选的系统调用:readv和writev。这些向量型函数具有一个结构数组,每个结构包含一个指向缓冲区的指针和长度。readv调用可以用于将指定数量的数据依次读入每个缓冲区。Writev则是把各个缓冲区的内容收集起来,并将它们在一次写入操作中进行输出。

如果驱动程序没有提供用于处理向量的操作方法,readv和writev会通过对read和write方法的多次调用来实现。

ssize_t (*readv)( struct file *filp, const struct iovec *iov, unsigned long count,loff_t *ppos);

ssize_t (*writev)( struct file *filp, const struct iovec *iov, unsigned long count,loff_t *ppos);

其中filp和ppos参数与read和write方法中的相同。iovec结构定义在<linux/uio.h>中:

struct iovec

{

       void __user *iov_base;

       __kernel_size_t iov_len;

};

每个iovec结构都描述了一个用于传输的数据块,这个数据块的起始位置在iov_base(在用户空间),长度为iov_len个字节。参数count指明要操作多少个iovec结构。这些结构由应用程序创建,而内核在调用驱动程序之前会把它们拷贝到内核空间。

向量化操作的最简单实现就是只传递每个iovec结构的地址和长度给驱动程序的read和write函数。而scddp忽略了它们。

 

9. scddp_follow方法

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值