对mmap()和munmap()的封装 -- 经得住拷机测试

来源:互联网 发布:英伦历史类影视知乎 编辑:程序博客网 时间:2024/05/08 20:01

http://hi.baidu.com/zengzhaonong/item/69bddc325170d4c01b969683

#include <stdio.h>               // NULL
#include <fcntl.h>               // O_RDWR
#include <sys/mman.h>            // PROT_READ

/* 最大映射次数 */
#define MAP_MAX    32

/* addr_map()的调用次数 */
static ulong map_cnt = 0;

typedef struct
{
   /* 用户需要映射的物理地址 */
   ulong p_addr;
   /* 用户需要映射的空间大小 */
   ulong buf_size;
   /* 实际映射出来的虚拟地址 */
   void *v_addr;
   /* 实际映射的空间大小 */
   ulong size;
} map_struct;

map_struct map_array[MAP_MAX];

/*****************************************************
* 函数名: addr_map
* 作者:    linglong
* 日期:    2010-12-01
* 功能:   将物理地址映射成虚拟地址
* 参数说明:
*        p_addr     用户需要映射的物理地址
*        buf_size   用户需要映射空间大小
* 返回值:    
*         类型(ulong)
*         如果映射成功,则返回物理地址对应的虚拟地址
*         如果失败,则返回0
* 修改记录:
******************************************************/
ulong addr_map (ulong p_addr, ulong buf_size)
{
   int map_fd     = 0;
   ulong low_addr = 0;
   ulong size     = 0;
   ulong i        = 0;
   void *v_addr   = NULL;

   if (MAP_MAX == map_cnt)
   {
       printf ("map max = %d\n", MAP_MAX);
       return 0;
   }

   for (i = 0; i < MAP_MAX; i++)
   {
       if (map_array[i].p_addr == p_addr
           && map_array[i].buf_size == buf_size)
       {
           printf ("Physical addr 0x%x has been mapped\n",
               p_addr);
           return 0;
       }
   }

   /* 打开内存文件 */
   map_fd = open ("/dev/mem", O_RDWR | O_SYNC);
   if (-1 == map_fd)
   {
       perror ("open");
       return 0;
   }

   /*
   * 对p_addr地址进行4K对齐
   * low_addr保存,非4K对齐的部分
   */
   low_addr = p_addr & 0xfff;

   /* 实际映射的空间大小 */
   size = buf_size + low_addr;

   /* 将输入的物理地址转换成虚拟空间 */
   v_addr = mmap (NULL, size, PROT_READ | PROT_WRITE,
       MAP_SHARED, map_fd, p_addr & ~0x00000fff);
   if (MAP_FAILED == v_addr)
   {
       perror ("mmap");
       close (map_fd);
       return 0;
   }

   map_array[map_cnt].p_addr = p_addr;
   map_array[map_cnt].buf_size = buf_size;
   map_array[map_cnt].v_addr = v_addr;
   map_array[map_cnt].size = size;
   map_cnt++;

#if 0
   printf ("low_addr = 0x%x\n", low_addr);
   printf ("v_addr   = 0x%x\n", v_addr);
#endif

    close (map_fd);
   /* 将用户传入的物理地址p_addr所对应的虚拟地址返回给用户 */
   return (ulong) (v_addr + low_addr);
}

void addr_unmap (ulong p_addr, ulong buf_size)
{
   int i = 0;
   ulong size = 0;
   void *v_addr = NULL;

   for (i = 0; i < MAP_MAX; i++)
   {
       if (map_array[i].p_addr == p_addr
           && map_array[i].buf_size == buf_size)
       {
           v_addr = map_array[i].v_addr;
           size   = map_array[i].size;
           munmap ((void *) v_addr, size);
           map_array[i].p_addr   = 0;
           map_array[i].buf_size = 0;
           map_cnt--;
           return;
       }
   }
   printf ("Physical addr 0x%x does not map\n", p_addr);
   return;
}

int main ()
{
   ulong p_addr   = 0;
   ulong buf_size = 0;
   ulong v_addr   = -1;
   ulong i        = 10;

   p_addr   = 0x1234;
   buf_size = 64;

   //for (i = 0; i < MAP_MAX + 5; i++)
   for (;;)
   {
       p_addr += i;
       v_addr = addr_map (p_addr, buf_size);
       if (-1 != v_addr)
       {
           //printf("v_addr   = 0x%x\n", v_addr);
           #if 0
           printf ("*(ulong *)v_addr = 0x%x\n",
               *(ulong *) v_addr);
           #endif
       }
       addr_unmap (p_addr, buf_size);
   }
}








 

 

 

 

 

 

 

 

 

---------------------------------------------------------------

#include <stdio.h>                // NULL
#include <fcntl.h>                // O_RDWR
#include <sys/mman.h>            // PROT_READ

/*****************************************************
* 函数名:  addr_map
* 作者:    linglong
* 日期:    2010-12-01
* 功能:    将物理地址映射成虚拟地址
* 参数说明:
*     p_addr     用户需要映射的物理地址
*     buf_size   用户需要映射空间大小
*     *v_addr    用来保存实际映射的虚拟地址
* 返回值:    
*     类型(ulong)
*     如果映射成功,则返回物理地址对应的虚拟地址
*     如果失败,则返回0
* 修改记录:
******************************************************/
ulong addr_map (ulong p_addr, ulong buf_size,
    ulong * actual_v_addr, ulong * actual_size)
{
    int map_fd = 0;
    ulong low_addr = 0;
    ulong size = 0;
    ulong i = 0;
    void *v_addr = NULL;

    /* 打开内存文件 */
    map_fd = open ("/dev/mem", O_RDWR | O_SYNC);
    if (-1 == map_fd)
    {
        perror ("open");
        return 0;
    }

    /*
     * 对p_addr地址进行4K对齐
     * low_addr保存,非4K对齐的部分
     */
    low_addr = p_addr & 0xfff;

    /* 实际映射的空间大小 */
    size = buf_size + low_addr;

    /* 将输入的物理地址转换成虚拟空间 */
    v_addr = mmap (NULL, size, PROT_READ | PROT_WRITE,
        MAP_SHARED, map_fd, p_addr & ~0x00000fff);
    if (MAP_FAILED == v_addr)
    {
        perror ("mmap");
        close (map_fd);
        return 0;
    }

    if (NULL != actual_v_addr)
        *actual_v_addr = (ulong) v_addr;
    if (NULL != actual_size)
        *actual_size = size;
#if 0
    printf ("low_addr = 0x%x\n", low_addr);
    printf ("v_addr   = 0x%x\n", v_addr);
#endif

    close (map_fd);
    /* 将用户传入的物理地址p_addr所对应的虚拟地址返回给用户 */
    return (ulong) (v_addr + low_addr);
}

int addr_unmap (void *v_addr, ulong buf_size)
{
    int ret;
    ret = munmap (v_addr, buf_size);
    return ret;
}

int main ()
{
    ulong p_addr = 0;
    ulong buf_size = 0;
    ulong v_addr = 0;
    ulong i = 10;
    ulong actual_v_addr;        /* 用来保存实际映射的虚拟地址 */
    ulong actual_size;

    p_addr = 0x1234;
    buf_size = 1024 * 128;

    for (;;)
    {
        v_addr =
            addr_map (p_addr, buf_size, &actual_v_addr,
            &actual_size);
        if (0 != v_addr)
        {
            addr_unmap ((void *) actual_v_addr, actual_size);
        }
    }
}
原创粉丝点击