Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1408756
  • 博文数量: 120
  • 博客积分: 182
  • 博客等级: 入伍新兵
  • 技术积分: 2278
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-19 16:31
文章分类

全部博文(120)

文章存档

2015年(12)

2014年(13)

2013年(40)

2012年(55)

分类:

2012-11-04 23:00:05

原文地址:linux mmap使用例子 作者:gududesiling


=====文件名:abc.c=====
一。
linux mmap使用例子
转自:http://blog.163.com/zhaoxin851055@126/blog/static/8112929820122872212734/

#include /* for mmap and munmap */
#include /* for open */
#include /* for open */
#include /* for open */
#include /* for lseek and write */
#include

int main(int argc, char **argv)  
{
  int fd;
  char *mapped_mem, * p;
  int flength = 1024;
  void * start_addr = 0;
  fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  flength = lseek(fd, 1, SEEK_END);
  write(fd, "\0", 1); /* 在文件最后添加一个空字符,以便下面printf正常工作 */
  lseek(fd, 0, SEEK_SET);
  mapped_mem = mmap(start_addr, flength, PROT_READ, //允许读
  MAP_PRIVATE, //不允许其它进程访问此内存区域
  fd, 0);
  /* 使用映射区域. */
  printf("%s\n", mapped_mem); /* 为了保证这里工作正常,参数传递的文件名最好是一个文本文件 */
  close(fd);
  munmap(mapped_mem, flength);
  return 0;

}
编译运行此程序:
gcc -Wall mmap.c
./a.out text_filename
上面的方法因为用了PROT_READ,所以只能读取文件里的内容,不能修改,如果换成PROT_WRITE就可以修改文件的内容了。又由于 用了MAAP_PRIVATE所以只能此进程使用此内存区域,如果换成MAP_SHARED,则可以被其它进程访
#include /* for mmap and munmap */
#include /* for open */
#include /* for open */
#include /* for open */
#include /* for lseek and write */
#include
#include /* for memcpy */

int main(int argc, char **argv)
{
  int fd;
  char *mapped_mem, * p;
  int flength = 1024;
  void * start_addr = 0;
  fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  flength = lseek(fd, 1, SEEK_END);
  write(fd, "\0", 1); /* 在文件最后添加一个空字符,以便下面printf正常工作 */
  lseek(fd, 0, SEEK_SET);
  start_addr = 0x80000;
  mapped_mem = mmap(start_addr, flength, PROT_READ|PROT_WRITE, //允许写入
  MAP_SHARED, //允许其它进程访问此内存区域
  fd, 0);
  /* 使用映射区域. */
  printf("%s\n", mapped_mem); /* 为了保证这里工作正常,参数传递的文件名最好是一个文本文 */
  while((p = strstr(mapped_mem, "Hello"))) /* 此处来修改文件 内容 */
{
  memcpy(p, "Linux", 5);
  p += 5;

}
  close(fd);
  munmap(mapped_mem, flength);
  return 0;

}

/*
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明:

头文件:


原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);
返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).
参数:
addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.
length: 将文件的多大长度映射到内存.
prot: 映射区的保护方式, 可以是:
PROT_EXEC: 映射区可被执行.
PROT_READ: 映射区可被读取.
PROT_WRITE: 映射区可被写入.
PROT_NONE: 映射区不能存取.
flags: 映射区的特性, 可以是:
MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.
MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.
此外还有其他几个flags不很常用, 具体查看linux C函数说明.
fd: 由open返回的文件描述符, 代表要映射的文件.
offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.


下面说一下内存映射的步骤:

用open系统调用打开文件, 并返回描述符fd.
用mmap建立内存映射, 并返回映射首地址指针start.
对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).
用munmap(void *start, size_t lenght)关闭内存映射.
用close系统调用关闭文件fd.*/



二。下面这个代码比较经典,但是我们基于这个修改ppc8280的gpio操作时,没有成功。
/*linux下使用mmap控制GPIO
2008-07-12 7:41
欢迎看看我的另一个小窝,说不定有意外的惊喜哦 ^_^ www.devres.info

如果没有/dev/mem,则执行

mknod /dev/mem c 1 1

编译下面的代码*/

#include
#include
#include
#include
#include
#include


#define GPIO_CTL_BASE 0x56000000
#define rGPBCON 0x10
#define rGPBDAT 0x14
#define rGPBUP 0x18

unsigned int *GPBCON,*GPBDAT,*GPBUP;

void Led_Display(int data)
{
*(volatile unsigned int *)GPBDAT= (~data & 0xf)<<7;//因为是第7-10位,且只有4位,故 左移7
}

int main(int argc, char** argv)
{
int gpio_fd, ip=0, i=0;
unsigned char *gpio_map;

gpio_map = NULL;
GPBCON = NULL;
GPBDAT = NULL;
GPBUP = NULL;

gpio_fd =open("/dev/mem",O_RDWR);
if (gpio_fd == -1)
{
printf("can't open /dev/mem.\n");
return ;
}

gpio_map = (unsigned char *)mmap(0, 0xbc,PROT_READ | PROT_WRITE, MAP_SHARED,gpio_fd, GPIO_CTL_BASE);
GPBCON = (volatile unsigned int *) (gpio_map+rGPBCON);
GPBDAT = (volatile unsigned int *) (gpio_map+rGPBDAT);
GPBUP = (volatile unsigned int *) (gpio_map+rGPBUP);

//初始化io
*(volatile unsigned int *)GPBCON=0x154000;
*(volatile unsigned int *)GPBUP=0x7ff;

for(i=0;i<16;i++)
{
Led_Display(i);
sleep(1);
}

munmap(0, 0xbc);
if (gpio_fd != 0x0)
{
close(gpio_fd);
}

printf("GPIO Control Test end\n");

}

阅读(1271) | 评论(0) | 转发(0) |
0

上一篇:printk实现分析

下一篇:linux 内存管理

给主人留下些什么吧!~~