正确的read()
从一个虚拟设备里读取数据,我是用read系统调用一次读完,发现反复读取多次后,数据出现了问题。
由于是自己写的虚拟设备,所以先怀疑是kernel module写的有问题,我自己实现了虚拟设备的read方法,难道偏移量的处理有问题?于是拿出万能的printk,调试......咦,怪了,怎么dmesg里打出的消息数不对?喔,dmesg的缓冲区设小了,改个大的,10M:
dmesg -s 10485760
测完,我在把内核数据通过copy_to_user拷给用户态之前还是正常的,拷了就不正常了,这这这,我记得copy_to_user就是判断一下内存空间的有效性,本身不会乱来的呀,好,为了证明,我改成memcpy。
还是不行,似乎只要把数据拷贝一下就不对了,神了......
最后终于发现,和module的代码没关系,是我在read的时候没有对读取的数据做结尾:
read(fd, buffer, BUFFER_SIZE);
// process buffer
正确的做法是:
int res = read(fd, buffer, BUFFER_SIZE);
buffer[res] = 0;
// process buffer
唉,一个简单的代码疏漏耗费半天时间。要是有个代码高手指导指导我就好了。
相关文章
- fedora 9 小集 - 01 05, 2009
- 多线程调试 - 12 17, 2008
- fedora 9 试用 - 12 05, 2008
并非read的问题, 而是你没弄明白什么是C字符串. C字符串是一段以'\0'结尾的字节数组, 在没有保证是以'\0'结尾之前, 你就把字节数组当做字符串, 然后用str*字符串处理函数来处理, 不出问题只是偶然. 另外, 为了表明你要处理的是字符串, 应该是buffer[res] = '\0', 而不是等于0, 虽然两者效果相同, 但能看出你是否明白你在处理的是什么东西.
我当然明白c字符串是什么。原先我是用fgets一行行的读(fgets自己带'\0'),后来改为read一次读,而代码处理文件内容的逻辑没有变,所以出问题了。
难点不在于字符串后面加没加'\0',而在于:系统大了,你无法快速确定问题在哪里。
多谢提醒 :)
有时候就是一个小问题会需要很久时间