mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-09-24 05:53:54 +08:00
鏇存柊浜嗗唴瀛樼鐞嗕箣椤靛紡绠$悊鏈哄埗...
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := mmap_test.o
|
||||
|
||||
else
|
||||
|
||||
#KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
KERNELDIR ?= /home/gatieme/Work/Kernel/linux-headers-3.14-desktop/
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
gcc test.c -o test
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
rm ./test
|
||||
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define DEVKMEM "/dev/kmem"
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("usage...");
|
||||
exit(-1);
|
||||
}
|
||||
int fd;
|
||||
char *mbase;
|
||||
char read_buf[10];
|
||||
unsigned int regAddr;
|
||||
unsigned int varAddr;
|
||||
|
||||
varAddr = strtoul(argv[1], 0, 16);
|
||||
|
||||
unsigned int ptr = varAddr & ~(PAGE_MASK);
|
||||
|
||||
fd = open(DEVKMEM, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
printf("%s %d", __func__, __LINE__);
|
||||
perror("open");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
mbase = (char *)mmap(0, PAGE_SIZE, PROT_READ, MAP_SHARED,fd, (varAddr & PAGE_MASK));
|
||||
if (mbase == MAP_FAILED)
|
||||
{
|
||||
printf("map failed %s\n",strerror(errno));
|
||||
}
|
||||
|
||||
printf("varAddr = 0x%X \n", varAddr);
|
||||
printf("mapbase = 0x%X \n", (unsigned int)mbase);
|
||||
printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr));
|
||||
printf("char = %c%c%c%c \n",
|
||||
*(char *)(mbase+ptr), *(char *)(mbase+ptr+1),
|
||||
*(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3));
|
||||
|
||||
close(fd);
|
||||
munmap(mbase,PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* devmem2.c: Simple program to read/write from/to any location in memory.
|
||||
*
|
||||
* Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
|
||||
*
|
||||
*
|
||||
* This software has been developed for the LART computing board
|
||||
* (http://www.lart.tudelft.nl/). The development has been sponsored by
|
||||
* the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/)
|
||||
* and Ubiquitous Communications (http://www.ubicom.tudelft.nl/)
|
||||
* projects.
|
||||
*
|
||||
* The author can be reached at:
|
||||
*
|
||||
* Jan-Derk Bakker
|
||||
* Information and Communication Theory Group
|
||||
* Faculty of Information Technology and Systems
|
||||
* Delft University of Technology
|
||||
* P.O. Box 5031
|
||||
* 2600 GA Delft
|
||||
* The Netherlands
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <termios.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
|
||||
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
|
||||
|
||||
#define MAP_SIZE 4096UL
|
||||
#define MAP_MASK (MAP_SIZE - 1)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int fd;
|
||||
void *map_base, *virt_addr;
|
||||
unsigned long read_result, writeval;
|
||||
off_t target;
|
||||
int access_type = 'w';
|
||||
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
|
||||
"\taddress : memory address to act upon\n"
|
||||
"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"
|
||||
"\tdata : data to be written\n\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
target = strtoul(argv[1], 0, 0);
|
||||
|
||||
if(argc > 2)
|
||||
access_type = tolower(argv[2][0]);
|
||||
|
||||
|
||||
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
|
||||
printf("/dev/mem opened.\n");
|
||||
fflush(stdout);
|
||||
|
||||
/* Map one page */
|
||||
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
|
||||
if(map_base == (void *) -1) FATAL;
|
||||
printf("Memory mapped at address %p.\n", map_base);
|
||||
fflush(stdout);
|
||||
|
||||
virt_addr = map_base + (target & MAP_MASK);
|
||||
switch(access_type) {
|
||||
case 'b':
|
||||
read_result = *((unsigned char *) virt_addr);
|
||||
break;
|
||||
case 'h':
|
||||
read_result = *((unsigned short *) virt_addr);
|
||||
break;
|
||||
case 'w':
|
||||
read_result = *((unsigned long *) virt_addr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal data type '%c'.\n", access_type);
|
||||
exit(2);
|
||||
}
|
||||
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
|
||||
fflush(stdout);
|
||||
|
||||
if(argc > 3)
|
||||
{
|
||||
writeval = strtoul(argv[3], 0, 0);
|
||||
switch(access_type) {
|
||||
case 'b':
|
||||
*((unsigned char *) virt_addr) = writeval;
|
||||
read_result = *((unsigned char *) virt_addr);
|
||||
break;
|
||||
case 'h':
|
||||
*((unsigned short *) virt_addr) = writeval;
|
||||
read_result = *((unsigned short *) virt_addr);
|
||||
break;
|
||||
case 'w':
|
||||
*((unsigned long *) virt_addr) = writeval;
|
||||
read_result = *((unsigned long *) virt_addr);
|
||||
break;
|
||||
}
|
||||
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
/*
|
||||
* getjiff.c
|
||||
*
|
||||
* this toolkit shows how to get jiffies value from user space:
|
||||
* 1. find jiffies's address from kernel image.
|
||||
* 2. access virtual address space to get jiffies value.
|
||||
* 3. access physical address sapce to get jiffies value.
|
||||
*
|
||||
* demostrate following techniques:
|
||||
* o get ELF object symbol address by calling nlist()
|
||||
* o access virtual memory space from /dev/kmem
|
||||
* o access virtual memory space from /dev/mem
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //exit
|
||||
#include <linux/a.out.h> //nlist
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define LONG *(volatile unsigned long*)
|
||||
|
||||
/* read from virtual memory */
|
||||
int read_kmem(off_t offset, void* buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
fd = open("/dev/kmem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open /dev/kmem failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
n = read(fd, buf, count);
|
||||
if (n != count)
|
||||
perror("/dev/kmem read failed");
|
||||
else
|
||||
printf("/dev/kmem read buf = %ld\n", *(unsigned long *)buf);
|
||||
|
||||
close(fd);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* read from physical memory */
|
||||
int read_mem(off_t offset, void* buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
int page_size;
|
||||
void *map_base;
|
||||
unsigned long value;
|
||||
|
||||
printf("/dev/mem: the offset is %lx\n", offset);
|
||||
|
||||
fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open /dev/mem failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(1){
|
||||
page_size = getpagesize();
|
||||
printf("the page size = %d\n", page_size);
|
||||
map_base = mmap(0,page_size,PROT_READ,MAP_SHARED,fd,offset);
|
||||
if (map_base == MAP_FAILED){
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
value = LONG(map_base);
|
||||
printf("/dev/mem: the value is %ld\n", value);
|
||||
buf = (unsigned long *)map_base;
|
||||
}
|
||||
|
||||
if(0){
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
n = read(fd, buf, count);
|
||||
if (n != count)
|
||||
perror("/dev/mem read failed");
|
||||
else
|
||||
printf("/dev/mem read buf = %ld\n", *(unsigned long *)buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char addr_str[11]="0x";
|
||||
char var[51];
|
||||
unsigned long addr;
|
||||
unsigned long jiffies;
|
||||
char ch;
|
||||
int r;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr,"usage: %s System.map\n",argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((fp = fopen(argv[1],"r")) == NULL) {
|
||||
perror("fopen");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
r = fscanf(fp,"%8s %c %50s\n",&addr_str[2],&ch,var); // format of System.map
|
||||
if (strcmp(var,"jiffies")==0)
|
||||
break;
|
||||
} while(r > 0);
|
||||
if (r < 0) {
|
||||
printf("could not find jiffies\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
addr = strtoul(addr_str,NULL,16); //Convert string to unsigned long integer
|
||||
printf("found jiffies at (%s) %08lx\n",addr_str,addr);
|
||||
|
||||
read_kmem(addr, &jiffies, sizeof(jiffies));
|
||||
printf("jiffies=%ld (read from virtual memory)\n\n", jiffies);
|
||||
|
||||
jiffies = 0; //reinit for checking read_mem() below
|
||||
|
||||
read_mem(addr-0xC0000000, &jiffies, sizeof(jiffies));
|
||||
printf("jiffies=%ld (read from physical memory)\n", jiffies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* http://blog.csdn.net/weed_hz/article/details/9787163
|
||||
*/
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
|
||||
#define DEVICE_NAME "mymap"
|
||||
|
||||
|
||||
static unsigned char array[10]={0,1,2,3,4,5,6,7,8,9};
|
||||
static unsigned char *buffer;
|
||||
|
||||
|
||||
static int my_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int my_map(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long page;
|
||||
|
||||
unsigned char i;
|
||||
|
||||
unsigned long start = (unsigned long)vma->vm_start;
|
||||
unsigned long end = (unsigned long)vma->vm_end;
|
||||
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
|
||||
|
||||
|
||||
//得到物理地址
|
||||
page = virt_to_phys(buffer);
|
||||
|
||||
//将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上
|
||||
if(remap_pfn_range(vma, start, page>>PAGE_SHIFT,size,PAGE_SHARED)) //第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//往该内存写10字节数据
|
||||
for(i=0;i<10;i++)
|
||||
{
|
||||
buffer[i] = array[i];
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct file_operations dev_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = my_open,
|
||||
.mmap = my_map,
|
||||
};
|
||||
|
||||
static struct miscdevice misc =
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = DEVICE_NAME,
|
||||
.fops = &dev_fops,
|
||||
};
|
||||
|
||||
static ssize_t hwrng_attr_current_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 10 ; i++)
|
||||
{
|
||||
printk("%d\n",buffer[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
|
||||
hwrng_attr_current_show,
|
||||
NULL);
|
||||
|
||||
|
||||
static int __init dev_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
//注册混杂设备
|
||||
ret = misc_register(&misc);
|
||||
|
||||
//内存分配
|
||||
buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);
|
||||
|
||||
//将该段内存设置为保留
|
||||
SetPageReserved(virt_to_page(buffer));
|
||||
|
||||
ret = device_create_file(misc.this_device,&dev_attr_rng_current);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void __exit dev_exit(void)
|
||||
{
|
||||
//注销设备
|
||||
misc_deregister(&misc);
|
||||
|
||||
//清除保留
|
||||
ClearPageReserved(virt_to_page(buffer));
|
||||
|
||||
//释放内存
|
||||
kfree(buffer);
|
||||
}
|
||||
|
||||
|
||||
module_init(dev_init);
|
||||
module_exit(dev_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("LKN@SCUT");
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
|
||||
int main(int argc , char *argv[])
|
||||
{
|
||||
|
||||
int fd;
|
||||
int i;
|
||||
unsigned char *p_map;
|
||||
|
||||
|
||||
//打开设备
|
||||
fd = open("/dev/mymap",O_RDWR);
|
||||
|
||||
if(fd < 0)
|
||||
{
|
||||
printf("open fail\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//内存映射
|
||||
p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
|
||||
if(p_map == MAP_FAILED)
|
||||
{
|
||||
|
||||
printf("mmap fail\n");
|
||||
goto here;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//打印映射后的内存中的前10个字节内容
|
||||
for(i=0;i<10;i++)
|
||||
{
|
||||
printf("%d\n",p_map[i]);
|
||||
p_map[i] = i + 10;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
here:
|
||||
|
||||
munmap(p_map, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user