Linux的内核空间和用户空间通过内存共享来进行通信的实现

来源:互联网 发布:大学生软件培训班 编辑:程序博客网 时间:2024/06/11 21:54

一、内核空间的代码,经过编译后生成内核模块,利用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;
}

<完>

原创粉丝点击