用户空间与kernel空间通信的例子(利用mmap)

本文介绍了一个简单的Linux内核模块,该模块用于在内核空间分配共享内存,并通过用户空间程序进行读取。模块使用`__get_free_pages`函数分配页面并设置保留标志,然后将字符串Hello world! 写入共享内存。用户空间程序通过`mmap`函数映射内核虚拟地址空间到用户空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wheelz");
MODULE_DESCRIPTION("mmap demo");

static unsigned long p = 0;

static int __init init(void)
{
    //分配共享内存(一个页面)
    p = __get_free_pages(GFP_KERNEL, 0); //得到的当然是一个虚拟地址了
    SetPageReserved(virt_to_page(p)); //#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) //12
    printk("<1> p = 0x%08x\n", p);
    //在共享内存中写上一个字符串
    strcpy(p, "Hello world!\n");
    return 0;
}

static void __exit exit(void)
{
    ClearPageReserved(virt_to_page(p));
    free_pages(p, 0);
}

module_init(init);
module_exit(exit);

用户空间的测试程序:

#include <sys/mman.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
#include <stdio.h> 

#define PAGE_SIZE (4*1024)

#define PAGE_OFFSET        0xc0000000
#define KERNEL_VIRT_ADDR    0xcf9e5000 //这里是硬编址的, 可以通过ioctl 或者proc来实现的。


int main() 
{ 
    char *buf; 
    int fd; 
    unsigned long phy_addr; 

    fd=open("/dev/mem",O_RDWR); 
    if(fd == -1)
        perror("open");
    phy_addr=KERNEL_VIRT_ADDR - PAGE_OFFSET; 

    buf=mmap(0, PAGE_SIZE, 
        PROT_READ|PROT_WRITE, MAP_SHARED, 
        fd, phy_addr); 
    if(buf == MAP_FAILED)
        perror("mmap");
    puts(buf);//打印共享内存的内容

    munmap(buf,PAGE_SIZE); 

    close(fd); 
    return 0; 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值