Chinaunix

标题: 内存映射mmap [打印本页]

作者: zzappled    时间: 2011-03-29 16:49
标题: 内存映射mmap
本帖最后由 zzappled 于 2011-03-29 16:57 编辑

内核态程序创建1页面的缓存,同时用户程序进行mmap映射,并向其中写入数据,出现错误
segfault at ffffffffffffffff ip 00007ffc307d5782 sp 00007ffff299fb38 error 6 in libc-2.13.so[7ffc306ab000+191000]
不知道是怎么回事,请各位指教
内核态程序
#define PROC_PHYADDR "mem_addr"

unsigned long kernel_addr=0;
unsigned long kernel_start=0;

#define PAGES_ORDER         0
#define PAGES                1

static int proc_mem_addr(char *page, char **start, off_t off, int count,int* eof, void* data)
{
  return sprintf(page, "%lu\n", __pa(kernel_start));
}

static int init_sk_buff(void)
{
  unsigned long page=0;
  char *addr=NULL;
  create_proc_read_entry(PROC_PHYADDR, 0, NULL, proc_mem_addr,NULL);
  kernel_addr=__get_free_pages(GFP_ATOMIC,PAGES_ORDER);
  addr=(char*)kernel_addr;
  kernel_start=kernel_addr;
  memset(addr, 0, PAGE_SIZE << PAGES_ORDER);
  if(addr)
  {
    while(page<=PAGES-1)
    {
      SetPageReserved(virt_to_page(kernel_addr));
      kernel_addr+=PAGE_SIZE;
      page++;
    }
    return 1;
  }
  return 0;
}

static int __init ring_init(void)
{
  if(!init_sk_buff())
    printk("init skb_buff error!");
  return 0;
}

static void __exit ring_exit(void)
{
  int page=0;
  char *addr=NULL;
  kernel_addr=kernel_start;
  addr=(char *)kernel_start;
  if(!addr)
    return;
  printk("The content written by user is: %s\n", addr);
  while(page<=PAGES-1)
  {
    ClearPageReserved(virt_to_page(kernel_addr));
    kernel_addr+=PAGE_SIZE;
    page++;
  }
  free_pages(kernel_start,PAGES_ORDER);
  remove_proc_entry(PROC_PHYADDR, NULL);
  return;
}

module_init(ring_init);
module_exit(ring_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("test");
MODULE_DESCRIPTION("Kernel memory share module.");


用户态程序:
#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>

#define PAGES        1       

int main(int argc, char* argv[])
{
        if(argc != 2)
        {
                printf("Usage: %s string\n", argv[0]);
                return 0;
        }
        
        unsigned long phymem_addr;
        char *map_addr=NULL;
        char s[256];
        int fd;
        
        fd = open("/proc/mem_addr", O_RDONLY);
        if(fd < 0)
        {
                printf("cannot open file /proc/mem_addr\n");
                return 0;
        }
        read(fd, s, sizeof(s));
        sscanf(s, "%lu", &phymem_addr);
        close(fd);

        printf("phymem_addr=%lu\n", phymem_addr);
        /*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, PAGES*4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, phymem_addr);
        strcpy(map_addr, argv[1]);
        munmap(map_addr, PAGES*4*1024);
        close(map_fd);
        return 0;
}
作者: zzappled    时间: 2011-03-30 09:00
结贴,重新编译内核,去掉CONFIG_X86_PAT和CONFIG_STRICT_DEVMEM




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2