LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1141|回复: 0

mmap的问题请教

[复制链接]
发表于 2009-1-3 00:34:24 | 显示全部楼层 |阅读模式
这是一个通过内存映射实现通信的一个例子程序

内核部分
[PHP]#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>

#define PROC_MEMSHARE_DIR "memshare"
#define PROC_MEMSHARE_PHYADDR "phymem_addr"
#define PROC_MEMSHARE_SIZE "phymem_size"

/*alloc one page. 4096 bytes*/
#define PAGE_ORDER                                0
/*this value can get from PAGE_ORDER*/
#define PAGES_NUMBER                                1

struct proc_dir_entry *proc_memshare_dir ;
unsigned long kernel_memaddr = 0;
unsigned long kernel_memsize= 0;

static int proc_read_phymem_addr(char *page, char **start, off_t off, int count){
       return sprintf(page, "%08lx\n", __pa(kernel_memaddr));
}
static int proc_read_phymem_size(char *page, char **start, off_t off, int count){
       return sprintf(page, "%lu\n", kernel_memsize);
}

static int __init init(void)
{
       /*build proc dir "memshare"and two proc files: phymem_addr, phymem_size in the dir*/
       proc_memshare_dir = proc_mkdir(PROC_MEMSHARE_DIR, NULL);
       create_proc_info_entry(PROC_MEMSHARE_PHYADDR, 0, proc_memshare_dir, proc_read_phymem_addr);
       create_proc_info_entry(PROC_MEMSHARE_SIZE, 0, proc_memshare_dir, proc_read_phymem_size);

       /*alloc one page*/
       kernel_memaddr =__get_free_pages(GFP_KERNEL, PAGE_ORDER);
       if(!kernel_memaddr){
            printk("Allocate memory failure!\n");
       }else{
            SetPageReserved(virt_to_page(kernel_memaddr));
            kernel_memsize = PAGES_NUMBER * PAGE_SIZE;
            printk("Allocate memory success!. The phy mem addr=%08lx, size=%lu\n", __pa(kernel_memaddr), kernel_memsize);
       }
       return 0;
}

static void __exit fini(void){
       printk("The content written by user is: %s\n", (unsigned char *) kernel_memaddr);
       ClearPageReserved(virt_to_page(kernel_memaddr));
       free_pages(kernel_memaddr, PAGE_ORDER);
       remove_proc_entry(PROC_MEMSHARE_PHYADDR, proc_memshare_dir);
       remove_proc_entry(PROC_MEMSHARE_SIZE, proc_memshare_dir);
       remove_proc_entry(PROC_MEMSHARE_DIR, NULL);

       return;
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("");
MODULE_DESCRIPTION("Kernel memory share module.");[/PHP]

用户部分
[PHP]#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>

int main(int argc, char* argv[])
{
       if(argc != 2)
       {
            printf("Usage: %s string\n", argv[0]);
            return 0;
       }
      
       unsigned long phymem_addr, phymem_size;
       char *map_addr;
       char s[256];
       int fd;
      
       /*get the physical address of allocated memory in kernel*/
       fd = open("/proc/memshare/phymem_addr", O_RDONLY);
       if(fd < 0)
       {
            printf("cannot open file /proc/memshare/phymem_addr\n");
            return 0;
       }
       read(fd, s, sizeof(s));
       sscanf(s, "%lx", &phymem_addr);
       close(fd);

       /*get the size of allocated memory in kernel*/
       fd = open("/proc/memshare/phymem_size", O_RDONLY);
       if(fd < 0)
       {
            printf("cannot open file /proc/memshare/phymem_size\n");
            return 0;
       }
       read(fd, s, sizeof(s));
       sscanf(s, "%lu", &phymem_size);
       close(fd);
      
       printf("phymem_addr=%lx, phymem_size=%lu\n", phymem_addr, phymem_size);
       /*memory map*/
       int map_fd = open("/dev/mem", O_RDWR);
       if(map_fd < 0)
       {
            printf("cannot open file /dev/mem\n");
            return 0;
       }
      
       map_addr = mmap(0, phymem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, phymem_addr);
           if(map_addr == MAP_FAILED){
                           perror("MMAP");
                        exit(1);
           }
       strcpy(map_addr, argv[1]);
       munmap(map_addr, phymem_size);
       close(map_fd);
       return 0;
      
}[/PHP]

makefile
[PHP]# Makefile2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
# #mymodule-objs := file1.o file2.o
# #obj-m := mymodule.o
obj-m := ukshm_k.o
else
PWD  := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
        $(MAKE) -C $(KDIR) M=$(PWD)
clean:
        rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif[/PHP]

内核部分没有问题,但我在Centos 5.2下面执行用户端程序的时候总是出问题:MMAP:Operation not permitted
是不是对/dev/mem映射有限制呢?
请教高人
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表