一、内核空间的代码,经过编译后生成内核模块,利用insmod mmap_kernelspace.o进行该模块的加载
/*
* The program is used for testing communication between
* kernel-space and user-space in linux operating system.
*
* mmap_kernelspace.c
* Author: jiangyb (101381@gmail.com)
* Date: 11/23/2005
* gcc -c mmap_kernelspace.c -I/usr/src/linux-2.4/include -o mmap_kernelspace.o
*/
#define __KERNEL__
#define MODULE
#include
#include
#include
#include
#include
#include
#include
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#endif
#define PAGES_ORDER 3
#define PAGES 8
#define MEM_WIDTH 1500
unsigned long mem_addr;
struct MEM_DATA {
unsigned short width;
unsigned short length;
unsigned short wptr;
unsigned short rptr;
} *mem_data;
struct MEM_PACKET {
unsigned int len;
unsigned char packetp[MEM_WIDTH - 4];/*sizeof(unsigned int) == 4*/
};
void init_mem()
{
char *addr;
char *buff;
int pages = 0;
int i;
struct MEM_PACKET *pdatapack;
mem_addr = __get_free_pages(GFP_KERNEL,PAGES_ORDER);
printk("inti_mem(), memory address that get from free pages is %x\n", mem_addr);
addr = (char *)mem_addr;
while(pages < PAGES) {
mem_map_reserve(virt_to_page(addr));
addr = addr + PAGE_SIZE;
pages++;
}
mem_data = (struct MEM_DATA *)mem_addr;
mem_data[0].length = PAGES*4*1024 / MEM_WIDTH;
mem_data[0].width = MEM_WIDTH;
mem_data[0].rptr = 1;
mem_data[0].wptr = 1;
for( i = 1; i <= mem_data[0].length; i++) {
buff = ( void * )( (char *)mem_addr + MEM_WIDTH * i );
pdatapack = (struct MEM_PACKET *)buff;
pdatapack->len = 0;
}
}
void del_mem()
{
int pages = 0;
char *addr;
addr = (char *)mem_addr;
while( pages < PAGES ) {
mem_map_unreserve(virt_to_page(addr));
addr = addr + PAGE_SIZE;
pages ++;
}
free_pages(mem_addr, PAGES_ORDER);
}
int put_mem(char *aBuf,unsigned int pack_size)
{
register int mem_ptr;
register int width,length;
register int s = 0;
register int i;
char *buf;
struct MEM_PACKET *pdatapack;
printk("put_mem(), content: %s, size: %d\n", aBuf, pack_size);
mem_data = (struct MEM_DATA *)mem_addr;
width = mem_data[0].width;
length = mem_data[0].length;
mem_ptr = mem_data[0].wptr;
buf = (void *)( (char *)mem_addr + width * mem_ptr);
for ( i=1; i < length; i++ ) {
pdatapack = (struct MEM_PACKET *)buf;
if ( pdatapack->len == 0) {
memcpy(pdatapack->packetp,aBuf,pack_size);
pdatapack->len = pack_size;
s = mem_ptr;
mem_ptr++;
if (mem_ptr >= length)
mem_ptr = 1;
mem_data[0].wptr = mem_ptr;
break;
}
mem_ptr++;
if (mem_ptr >= length) {
mem_ptr = 1;
buf = (void *)((char *)mem_addr + width);
}
else buf = (char *)mem_addr + width*mem_ptr;
}
if(i >= length)
s = 0;
return s;
}
int read_procaddr(char *buf,char **start,off_t offset,
int count,int *eof,void *data)
{
sprintf(buf,"%u\n",__pa(mem_addr));
printk("Memory address is : %u\n", __pa(mem_addr));
*eof = 1;
return 9;
}
int init_module(void)
{
printk("---------------------------\n");
printk("Corem module is installed\n");
init_mem();
put_mem("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26);
create_proc_read_entry("nf_addr",0,NULL,read_procaddr,NULL);
return 0;
}
void cleanup_module(void)
{
del_mem();
remove_proc_entry("nf_addr",NULL);
printk("Corem module is uninstalled\n");
}
MODULE_LICENSE("GPL");
二、用户空间的代码,编译成可执行文件
/*
* The program is used for testing communication between
* kernel-space and user-space in linux operating system.
*
* mmap_userspace.c
* Author: jiangyb (101381@gmail.com)
* Date: 11/23/2005
* gcc mmap_userspace.c -o mmap_userspace
*/
#include
#include
#include
#include
#include
#define PAGES 8
#define MEM_WIDTH 1500
char *mem_addr;
struct MEM_DATA {
unsigned short width;
unsigned short length;
unsigned short wptr;
unsigned short rptr;
} *mem_data;
struct MEM_PACKET {
unsigned int len;
unsigned char packetp[MEM_WIDTH - 4];/*sizeof(unsigned int) == 4*/
};
int get_mem(char *memaddr,char *inbuff,unsigned int *size)
{
register int mem_ptr;
register int width, length;
register int i;
register int s = 0;
char *buf;
struct MEM_PACKET *pdatapack;
mem_data = (void *)memaddr;
width = mem_data[0].width;
length = mem_data[0].length;
mem_ptr = mem_data[0].rptr;
buf = (void *)(memaddr + width * mem_ptr);
pdatapack = (struct MEM_PACKET *)buf;
if(pdatapack->len != 0) {
memcpy(inbuff,pdatapack->packetp,pdatapack->len);
*size = pdatapack->len;
pdatapack->len = 0;
s = mem_data[0].rptr;
mem_data[0].rptr++;
if(mem_data[0].rptr >= length)
mem_data[0].rptr = 1;
goto ret;
}
for (i=1;i
mem_ptr++;
if (mem_ptr >= length)
mem_ptr = 1;
buf = (void *)(memaddr + width*mem_ptr);
pdatapack = (struct MEM_PACKET *)buf;
if (pdatapack->len == 0)
continue;
memcpy(memaddr, pdatapack->packetp,pdatapack->len);
*size = pdatapack->len;
pdatapack->len = 0;
s = mem_data[0].rptr = mem_ptr;
mem_data[0].rptr++;
if(mem_data[0].rptr >= length)
mem_data[0].rptr = 1;
break;
}
ret:
return s;
}
int put_mem(char *mem_addr, char *aBuf, unsigned int pack_size)
{
register int mem_ptr;
register int width,length;
register int s = 0;
register int i;
char *buf;
struct MEM_PACKET *pdatapack;
mem_data = (struct MEM_DATA *)mem_addr;
width = mem_data[0].width;
length = mem_data[0].length;
mem_ptr = mem_data[0].wptr;
buf = (void *)( (char *)mem_addr + width * mem_ptr);
for(i=1; i < length; i++) {
pdatapack = (struct MEM_PACKET *)buf;
if(pdatapack->len == 0) {
memcpy(pdatapack->packetp,aBuf,pack_size);
pdatapack->len = pack_size;
s = mem_ptr;
mem_ptr++;
if (mem_ptr >= length)
mem_ptr = 1;
mem_data[0].wptr = mem_ptr;
break;
}
mem_ptr++;
if (mem_ptr >= length) {
mem_ptr = 1;
buf = (void *)((char *)mem_addr + width);
} else
buf = (char *)mem_addr + width*mem_ptr;
}
if(i >= length)
s = 0;
return s;
}
int main()
{
char *mem_addr;
char inbuff[1500];
int fd;
int fd_procaddr;
unsigned int size;
char addr[9];
unsigned long proc_addr;
fd = open("/dev/mem", O_RDWR);
/* read procaddr from nf_addr file in proc directory */
fd_procaddr = open("/proc/nf_addr", O_RDONLY);
read(fd_procaddr, addr, 9);
proc_addr = atol(addr);
close(fd_procaddr);
printf("read proc address is : %u[%8lx]\n", proc_addr, proc_addr);
/* Map the address in kernel to user space, use mmap function*/
mem_addr = mmap(0, PAGES*4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, proc_addr);
put_mem(mem_addr, "hello world", 12);
get_mem(mem_addr, inbuff, &size);
printf("Get data from core space, content: %s\n", inbuff); munmap(mem_addr,PAGES*4*1024); close(fd); return 0; }