字符设备之read和write

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.

   

阅读更多
个人分类: Ldd
想对作者说点什么? 我来说一句

读写配置文件/C++ VC

2008年09月20日 1.65MB 下载

没有更多推荐了,返回首页

不良信息举报

字符设备之read和write

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭