打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux的内核空间和用户空间通过内存共享来进行通信的实现
Linux的内核空间和用户空间通过内存共享来进行通信的实现
2008-09-02 23:21

一、内核空间的代码,经过编译后生成内核模块,利用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 <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/wrapper.h>
#include <asm/page.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>

#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 <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

#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<length;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;

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
devmem读写物理内存和devkmem读取内核虚拟内存
Linux内存初始化
linux内存映射相关知识点
带你用纯C实现一个内存池(图文结合)
DNS协议 报文格式
使用libpng,libjpeg从文件读取和从内存读取2中方式的实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服