- 論壇徽章:
- 36
|
之所以想寫(xiě)這篇帖子,是有兩個(gè)方面原因。其一是內(nèi)核版有一個(gè)關(guān)于《內(nèi)核可以從線(xiàn)性地址直接計(jì)算物理地址,用來(lái)做什么呢?》的討論,偶說(shuō)計(jì)算出物理地址可以共享給用戶(hù)空間讀寫(xiě)。dreamice兄說(shuō)能否說(shuō)一下詳細(xì)的應(yīng)用。其二是alb*版主提到wheelz曾經(jīng)寫(xiě)過(guò)這樣一個(gè)例程,拜讀了一把,發(fā)現(xiàn)在傳遞物理地址和內(nèi)存大小上,wheelz的例程還有些不夠靈活。alb*版主提到可以通過(guò)文件的方式實(shí)現(xiàn)動(dòng)態(tài)的傳遞。
因此,偶也寫(xiě)了這樣一個(gè)例程,可以動(dòng)態(tài)的將內(nèi)核空間的物理地址和大小傳給用戶(hù)空間。
整個(gè)內(nèi)核模塊,在模塊插入時(shí)建立proc文件,分配內(nèi)存。卸載模塊的時(shí)候?qū)⒂脩?hù)空間寫(xiě)入的內(nèi)容打印出來(lái)。
以下是內(nèi)核模塊的代碼和用戶(hù)空間的測(cè)試代碼。
/*This program is used to allocate memory in kernel
and pass the physical address to userspace through proc file.*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
#define PROC_MEMSHARE_DIR "memshare"
#define PROC_MEMSHARE_PHYADDR "phymem_addr"
#define PROC_MEMSHARE_SIZE "phymem_size"
/*alloc one page. 4096 bytes*/
#define PAGE_ORDER 0
/*this value can get from PAGE_ORDER*/
#define PAGES_NUMBER 1
struct proc_dir_entry *proc_memshare_dir ;
unsigned long kernel_memaddr = 0;
unsigned long kernel_memsize= 0;
static int proc_read_phymem_addr(char *page, char **start, off_t off, int count)
{
return sprintf(page, "%08lx\n", __pa(kernel_memaddr));
}
static int proc_read_phymem_size(char *page, char **start, off_t off, int count)
{
return sprintf(page, "%lu\n", kernel_memsize);
}
static int __init init(void)
{
/*build proc dir "memshare"and two proc files: phymem_addr, phymem_size in the dir*/
proc_memshare_dir = proc_mkdir(PROC_MEMSHARE_DIR, NULL);
create_proc_info_entry(PROC_MEMSHARE_PHYADDR, 0, proc_memshare_dir, proc_read_phymem_addr);
create_proc_info_entry(PROC_MEMSHARE_SIZE, 0, proc_memshare_dir, proc_read_phymem_size);
/*alloc one page*/
kernel_memaddr =__get_free_pages(GFP_KERNEL, PAGE_ORDER);
if(!kernel_memaddr)
{
printk("Allocate memory failure!\n");
}
else
{
SetPageReserved(virt_to_page(kernel_memaddr));
kernel_memsize = PAGES_NUMBER * PAGE_SIZE;
printk("Allocate memory success!. The phy mem addr=%08lx, size=%lu\n", __pa(kernel_memaddr), kernel_memsize);
}
return 0;
}
static void __exit fini(void)
{
printk("The content written by user is: %s\n", (unsigned char *) kernel_memaddr);
ClearPageReserved(virt_to_page(kernel_memaddr));
free_pages(kernel_memaddr, PAGE_ORDER);
remove_proc_entry(PROC_MEMSHARE_PHYADDR, proc_memshare_dir);
remove_proc_entry(PROC_MEMSHARE_SIZE, proc_memshare_dir);
remove_proc_entry(PROC_MEMSHARE_DIR, NULL);
return;
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Godbach (nylzhaowei@163.com)");
MODULE_DESCRIPTION("Kernel memory share module.");
用戶(hù)空間的測(cè)試代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Usage: %s string\n", argv[0]);
return 0;
}
unsigned long phymem_addr, phymem_size;
char *map_addr;
char s[256];
int fd;
/*get the physical address of allocated memory in kernel*/
fd = open("/proc/memshare/phymem_addr", O_RDONLY);
if(fd < 0)
{
printf("cannot open file /proc/memshare/phymem_addr\n");
return 0;
}
read(fd, s, sizeof(s));
sscanf(s, "%lx", &phymem_addr);
close(fd);
/*get the size of allocated memory in kernel*/
fd = open("/proc/memshare/phymem_size", O_RDONLY);
if(fd < 0)
{
printf("cannot open file /proc/memshare/phymem_size\n");
return 0;
}
read(fd, s, sizeof(s));
sscanf(s, "%lu", &phymem_size);
close(fd);
printf("phymem_addr=%lx, phymem_size=%lu\n", phymem_addr, phymem_size);
/*memory map*/
int map_fd = open("/dev/mem", O_RDWR);
if(map_fd < 0)
{
printf("cannot open file /dev/mem\n");
return 0;
}
map_addr = mmap(0, phymem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, phymem_addr);
strcpy(map_addr, argv[1]);
munmap(map_addr, phymem_size);
close(map_fd);
return 0;
}
測(cè)試的內(nèi)核是2.6.25.以下是執(zhí)行結(jié)果。
debian:/home/km/memshare# insmod memshare_kernel.ko
debian:/home/km/memshare# ./memshare_user 'hello,world!'
phymem_addr=e64e000, phymem_size=4096
debian:/home/km/memshare# cat /proc/memshare/phymem_addr
0e64e000
debian:/home/km/memshare# cat /proc/memshare/phymem_size
4096
debian:/home/km/memshare# rmmod memshare_kernel
debian:/home/km/memshare# tail /var/log/messages
Sep 27 18:14:24 debian kernel: [50527.567931] Allocate memory success!. The phy mem addr=0e64e000, size=4096
Sep 27 18:15:31 debian kernel: [50592.570986] The content written by user is: hello,world!
倉(cāng)促之間,有些地方處理的還是比較簡(jiǎn)單。希望高手多多指正。需要了解這方面實(shí)現(xiàn)的可以參考一下,共同學(xué)習(xí)。
[ 本帖最后由 Godbach 于 2008-11-12 17:45 編輯 ] |
評(píng)分
-
查看全部評(píng)分
|