mmap--最简单的测试程序(用户空间与内核空间数据交换&&用户态和内核态的数据交换用例)

本文介绍了一个简单的Linux内核模块实现,该模块用于在内核空间分配并初始化共享内存区域,并通过用户态程序访问这块共享内存。演示了如何从用户空间读取内核空间中的字符串。

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

//内核模块测试程序

#include <Linux/config.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/mm.h>

 

static unsigned long p = 0;

 

static int __init shao_init(void)

{

         //分配共享内存(一个页面)

         p = __get_free_pages(GFP_KERNEL, 0);

         SetPageReserved(virt_to_page(p));

 

         printk("<1> p = 0x%08x/n", p);

 

         //在共享内存中写上一个字符串

         strcpy(p, "Hello world!/n");

 

         return 0;

}

 

static void __exit shao_exit(void)

{

         ClearPageReserved(virt_to_page(p));

         free_pages(p, 0);    

}

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Kuanish");

MODULE_DESCRIPTION("mmap test");

 

module_init(shao_init);

module_exit(shao_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 0xc5e3c000 //此处地址即为内核模块打印的地址p,动态的不固定,需要自行修改

 

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;

}

### JobThread中CompletionException和ConcurrentModificationException错误的原因及解决方案 #### 一、CompletionException 错误分析与解决 `CompletionException` 是 Java 中 `CompletableFuture` 或其他异步任务框架中的常见异常。它通常表示某个异步任务在执行过程中发生了未捕获的异常,而该异常会被封装到 `CompletionException` 中并向上抛出。 - **原因** 当 `JobThread` 使用 `CompletableFuture` 执行异步任务时,如果子任务内部发生异常(如空指针异常、非法参数异常等),这些异常会被封装成 `CompletionException` 并传递给调用方[^1]。 - **解决方案** 可通过以下方式处理: - 明确捕获异常:使用 `.exceptionally()` 方法显式定义如何处理异常情况。 ```java CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 模拟可能引发异常的任务 throw new RuntimeException("Task failed"); }).exceptionally(ex -> { System.err.println("Caught exception: " + ex.getMessage()); return null; }); ``` - 调试日志记录:增加详细的日志信息以便定位问题源头。 ```java try { future.get(); } catch (InterruptedException | ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof CompletionException) { System.err.println("Root cause of CompletionException: " + cause.getCause().getMessage()); } } ``` --- #### 二、ConcurrentModificationException 错误分析与解决 `ConcurrentModificationException` 表示集合在迭代期间被外部线程或方法修改而导致的一致性破坏。这种异常常发生在多线程环境下对共享集合的操作。 - **原因** 如果 `JobThread` 的任务涉及对共享集合(如 `ArrayList`、`HashMap` 等)的并发访问,在某些场景下可能会触发此异常。例如,当一个线程正在遍历集合的同时,另一个线程对该集合进行了结构性修改(如添加或删除元素)。这违反了迭代器的安全假设[^2]。 - **解决方案** 下面列举了几种常见的解决策略: - **Collections.synchronizedXXX() 方法** 对于简单的线程安全需求,可以使用 `Collections.synchronizedList()` 或 `Collections.synchronizedSet()` 来包装原始集合。需要注意的是,虽然这种方法提供了基本的同步机制,但在复杂操作(如迭代)时仍需手动加锁。 ```java List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>()); synchronized(synchronizedList) { Iterator<String> iterator = synchronizedList.iterator(); while (iterator.hasNext()) { String item = iterator.next(); // 处理逻辑... } } ``` - **CopyOnWriteArrayList / CopyOnWriteArraySet** 这些类适用于读多写少的场景。它们通过每次写入时创建新副本的方式来避免并发冲突,从而天然支持线程安全。 ```java Set<String> threadSafeSet = new CopyOnWriteArraySet<>(); threadSafeSet.add("item1"); threadSafeSet.remove("item1"); ``` - **ConcurrentHashMap** 在需要高性能并发哈希表的情况下,推荐使用 `ConcurrentHashMap` 替代普通的 `HashMap`。它的设计基于分段锁技术,能够显著提升性能。 ```java Map<String, Integer> concurrentMap = new ConcurrentHashMap<>(); concurrentMap.put("key", 1); int value = concurrentMap.computeIfAbsent("key", k -> 0); ``` --- ### 总结 对于 `CompletionException` 和 `ConcurrentModificationException`,分别采取针对性措施可有效解决问题。前者主要依赖于完善的异常捕捉机制;后者则可以通过选用合适的线程安全容器或者合理控制并发行为来规避风险。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值