LED互斥访问
本次实验是在此前原子操作、自旋锁、信号量实验的基础上,学习用**互斥体(mutex)**实现对LED灯的互斥访问,这是最适合互斥场景的同步机制。
一、实验程序编写
驱动文件修改
新建10_mutex文件夹,创建VSCode工程并命名为mutex,将之前的semaphore.c复制过来,重命名为mutex.c。
核心改动是把原驱动中信号量相关代码替换为mutex,其余逻辑基本不变,关键操作如下:定义互斥体:在设备结构体gpioled_dev中新增struct mutex lock成员,用于实现互斥控制。
获取互斥锁:在open()函数中,调用mutex_lock_interruptible()(可被信号打断,推荐)或mutex_lock()(不可被信号打断)获取mutex,获取成功才能操作LED,失败则进入休眠等待,逻辑和信号量一致。
释放互斥锁:在release()函数中,调用mutex_unlock()释放mutex,让其他进程能获取锁并操作LED。
初始化互斥体:在驱动入口函数led_init()中,调用mutex_init()完成mutex的初始化,这一步和二值信号量的初始化类似,只是mutex专为互斥场景设计。
测试程序准备
直接复用之前的atomicApp.c,复制到当前工程后重命名为mutexApp.c即可,无需额外修改,测试逻辑保持不变。
二、运行测试
编译驱动程序
编写Makefile,和第1章的Makefile结构一致,只需把obj-m变量的值改为mutex.o。
执行make -j32命令,编译成功后会生成mutex.ko驱动模块文件。
编译测试程序
执行arm-linux-gnueabihf-gcc mutexApp.c -o mutexApp命令,编译成功后生成mutexApp应用程序。
加载驱动与测试
将生成的mutex.ko和mutexApp复制到开发板的rootfs/lib/modules/4.1.15目录,重启开发板后进入该目录。
首次加载驱动先执行depmod,再执行modprobe mutex加载驱动模块。
加载成功后,用mutexApp测试驱动,测试方法和9.3节的信号量测试完全一致,验证多进程对LED的互斥访问是否正常。
若要卸载驱动,执行rmmod mutex即可。
三、核心要点补充
mutex的优势:相比信号量,mutex是专为互斥设计的同步机制,语义更清晰,只有持有锁的进程才能释放,还支持优先级继承,能有效避免优先级反转问题,更适合设备驱动的互斥场景。
锁的使用注意:
必须遵循“谁加锁谁解锁”的原则,本次实验在open加锁、release解锁,符合打开-关闭的对称逻辑。
推荐用mutex_lock_interruptible()获取锁,这样进程等待锁时若收到信号(比如Ctrl+C),能及时响应退出,避免进程卡死;
mutex_lock()不可被信号打断,使用时需谨慎。
潜在优化方向:当前驱动在open函数加锁,会导致只要有一个进程打开设备,其他进程就无法打开,锁粒度偏大。若仅需互斥控制LED的写操作,可在write函数中加锁,缩短临界区,提升并发能力。
异常场景应对:若进程获取锁后崩溃,未调用close释放锁,会导致mutex永久锁定。缓解办法是尽量缩短临界区,把锁放在具体的操作函数而非打开函数中,减少异常风险。