关闭

字符设备之read和write

891人阅读 评论(0) 收藏 举报
分类:

1.内核空间的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,const char __user *buff,size_t count,loff_t *offp);
    各参数的意义如下:

filp:文件指针,由open()产生;
buff:用户空间的指针;
count:请求传输的数量长度,以字节为单位;
offp:用户在文件中进行存取操作的偏移量.因此,我们可以通过指定这个参数并配合count参数读取某文件或buf的指定数据段;
   

    1-1.read()的返回值:

返回值为count则说明数据全部传输完成;
返回值为正(标志为len)但是比count小,表明实际传输了(count - len)字节,这时候需要重新读取数据;
返回值为0,则表示到了文件尾;
返回值为负表示出错.

    1-2.write()的返回值:

返回值为count,则说明完成了所请求的数目的字节数据长度;
返回值为正(标志为len)并小于count,则只传输了(count - len)个字节,这时候需要重新传输数据;
返回值为0,意味着什么也没写入;
返回值为负表示出错.

2.copy_to_user()和copy_from_user():

    read()和write()只是对应于用户空间的系统调用,并不产生实质的数据交互.并且这里注意一点,上述的指针参数buff对内核空间而言极有可能是无效的,不作任何处理地引用这个参数指针,有可能引发oops.因此,当用户空间和内核空间产生数据交互的时候,还需要借用内核提供的API来实现:copy_to_user()和copy_from_user().其原型如下:

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);
    两个函数的第一个参数均为目标地址;第二个参数均为源地址;第三个参数为数据长度.

    这两个函数若无错误产生,则返回0.

    使用这两个内核API时,需要注意以下两点:

1).可能会引起睡眠;
2).返回值是还需要拷贝的内存数据长度.

    2-1.__copy_to_user()和__copy_from_user():

    在用户指针对内核的合法性有保障的情况下,可以使用__copy_to_user()和__copy_from_user()两个函数来取代上述的copy_to_user()和copy_from_user()两个函数.


3.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 *opps);
    这里的比较明著的参数是iov.其原型如下:

struct iovec
{
    void __user *iov_base;
    __kernel_size_t iov_len;
}
    iovec描述了一个数据块,此数据块的起始位置在iov_base,长度为iov_len.其中参数count表示要操作多少个这样的iovec.

   

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:133070次
    • 积分:2691
    • 等级:
    • 排名:第13460名
    • 原创:131篇
    • 转载:71篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论