- 论坛徽章:
- 0
|
我使用mmap将内核空间内存映射到用户空间,然后由用户层的write函数让内核向这块内存写数据,写完之后用户层立即将从这块内存获得的数据与写入的比较。
内核源码如下:- #define MMAP_PAGE_SIZE 4096
- static unsigned char *buffer;
- ssize_t mmap_write(struct file *file, const char __user *buf, size_t len, loff_t *ofs)
- {
- copy_from_user(buffer, buf, len);
-
- printk("data1 is=%x\n",buffer[0]);
- printk("data2 is=%x\n",buffer[1]);
- printk("data3 is=%x\n",buffer[2]);
- printk("data4 is=%x\n",buffer[3]);
- printk("data5 is=%x\n",buffer[4]);
- printk("data6 is=%x\n",buffer[5]);
- printk("data7 is=%x\n",buffer[6]);
- printk("data8 is=%x\n",buffer[7]);
- printk("data9 is=%x\n",buffer[8]);
- printk("dataA is=%x\n",buffer[9]);
- printk("dataB is=%x\n",buffer[10]);
- printk("dataC is=%x\n",buffer[11]);
- printk("dataD is=%x\n",buffer[12]);
- printk("dataE is=%x\n",buffer[13]);
- printk("dataF is=%x\n",buffer[14]);
- printk("\n");
- return len;
- }
- static int mmap_map(struct file *filp, struct vm_area_struct *vma)
- {
- unsigned long page;
- unsigned long start = (unsigned long)vma->vm_start;
- unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
- page = virt_to_phys(buffer);
- vma->vm_flags |= VM_LOCKED | VM_SHARED | VM_IO | VM_RESERVED;;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,vma->vm_page_prot))
- return -1;
-
- return 0;
- }
复制代码 用户源码如下:- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <linux/fb.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
- #define PAGE_SIZE 4096
- unsigned char buf1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
- 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
- unsigned char buf2[] = {0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9,
- 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1};
- int main(int argc , char *argv[])
- {
- int fd;
- int i;
- unsigned char *p_map;
-
- fd = open("/dev/mmap-dev",O_RDWR);
- if(fd < 0)
- {
- printf("open failn");
- exit(1);
- }
-
- p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,fd, 0);
- if(p_map < 0)
- {
- printf("mmap failn");
- goto here;
- }
- while(1)
- {
- for(i=0; i<100; i++)
- {
- write(fd, buf1,15);
- msync(p_map, PAGE_SIZE, MS_SYNC);
- //sleep(1);
- for(i=0; i<15; i++)
- if(buf1[i] != p_map[i]){
- printf("data %x is=%x\n", i+1, p_map[i]);
- printf("mmap error buff1 !!!!!! \n");
- }
- write(fd, buf2,15);
- msync(p_map, PAGE_SIZE, MS_SYNC);
- //sleep(1);
- for(i=0; i<15; i++)
- if(buf2[i] != p_map[i]){
- printf("data %x is=%x\n", i+1, p_map[i]);
- printf("mmap error buff2 !!!!!! \n");
- }
- }
- sleep(1);
- }
- here:
- munmap(p1_map, PAGE_SIZE);
-
- return 0;
- }
复制代码 如果我把mmap_write函数里的printk都注销,出错的概率会非常低,可能几十小时才出一次,但加上printk会立即出现上层读到的数据与写入的不一致,再接着读取,大部分时候就是正确的了。如果在把上层程序的sleep加上,则完全不会出错。从现象来看,好像是用户层读到的数据滞后了内核一点时间,不知道具体是内核写入产生的滞后还是用户读取产生的滞后,或者哪里设置不对,请大神们帮忙!我用的ARM平台 |
|