用户和kernel空间使用mmap共享内存


原来的程序:
/* 文件操作 */
static struct file_operations xxx_fops = {
    ......
    .mmap        =    _xxxx_mmap,
    ......
};

static int _xxxx_mmap(struct file * file, struct vm_area_struct * vma)
{
    int offset;
    offset = ((int)(__pa(pdata)) >> PAGE_SHIFT);    // pdata是 __get_free_page得到的

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    vma->vm_flags |= VM_RESERVED;

    printk("vma start: 0x%lx, buffer pfn: 0x%lx/n", vma->vm_start, offset);
    if (remap_pfn_range(vma, vma->vm_start,
                offset,
                vma->vm_end - vma->vm_start,
                vma->vm_page_prot))
        return -EAGAIN;

    return 0;
}

ldd3中讲到,对于常规内存,不能用remap_pfn_range,这个限制用来保证系统稳定性。
remap_pfn_range时候做外部io/mem空间映射。
所以上面的例子当然运行错误,改为nopage方式,如下(运行正常):

/* 文件操作 */
static struct file_operations xxx_fops = {
    ......
    .mmap        =    _xxxx_mmap,
    ......
};


static int _xxxx_mmap(struct file * file, struct vm_area_struct * vma)
{
    vma->vm_ops = &scullv_vm_ops;
    vma->vm_flags |= VM_RESERVED;
    return 0;
}


struct page *scullv_vma_nopage(struct vm_area_struct *vma,
                                unsigned long address, int *type)
{
    struct page *page = NOPAGE_SIGBUS;

    if(pdata) {
        page = virt_to_page(pdata);    // get_free_page得到的内存不要用vmalloc_to_page
        get_page(page);
        if(type)
            *type = VM_FAULT_MINOR;
    }

    return page;
}


测试程序:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>

int main(int argc, char *argv[])
{
    int fd;
    int *mp;
    int i = 0;

    if(-1 == (fd = open("/dev/testdev", O_RDWR)))
        return -1;

    mp = (int *)mmap(0, 4096, (PROT_WRITE | PROT_READ), MAP_SHARED, fd, 0);
    if(MAP_FAILED == mp) {
        printf("mmap failed/n");
        close(fd);
        return -2;
    }

    // success, r/w here
    while(1) {
        mp[0] = 4;
        mp[1] = 0x111 + i++;
        mp[2] = 0x222 + i++;
        mp[3] = 0x333 + i++;
        mp[4] = 0x444 + i++;
        sleep(1);
    }
    close(fd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值