赞
踩
=====文件名: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");
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。