Linux驱动开发——并发和竞态(中断屏蔽方式的使用②)

简介: Linux驱动开发——并发和竞态(中断屏蔽方式的使用②)

文章目录

解决竞态引起异常的方法之中断屏蔽

中断屏蔽的特点

中断屏蔽解决竞态引起的异常编程步骤

示例(保证led灯同一时刻只能有一个进程操作打开)


解决竞态引起异常的方法之中断屏蔽

中断屏蔽的特点

中断屏蔽能够解决进程与进程之间的抢占引起的异常(进程之间的抢占本身基于软中断实现),中断屏蔽能够解决中断和进程的抢占引起的异常,能够解决 中断和中断引起的异常。

但是中断屏蔽无法解决多核引起的异常。

注意:使用中断屏蔽保护的临界区的代码执行速度要越快越好,更不能进行休眠操作。因为Linux系统的很多机制都跟中断密切相关(tasklet、软件定时器、硬件定时器等),长时间屏蔽中断非常危险。


中断屏蔽解决竞态引起的异常编程步骤

  1. 找出代码中哪些是共享资源。
  2. 找出代码中哪些是临界区。
  3. 确定所保护的临界区中是否有休眠操作,如果有休眠操作则不能考虑中断屏蔽的方式,如果没有且没有多核参与竞态,则可以考虑使用中断屏蔽。
  4. 访问临界区之前屏蔽中断:
unsigned long flags;
local_irq_save(flags);//屏蔽中断,保存中断标志到flags(内核来完成)

  1. 正常访问临界区,此时不会有其他进程抢占、也不会有其他中断打断。
  2. 访问临界区之后,恢复中断。
local_irq_restore(flags);//恢复中断

  1. 屏蔽中断和恢复中断务必逻辑上成对使用。

示例(保证led灯同一时刻只能有一个进程操作打开)

使用全局变量open_cnt来记录当前操作使用设备者的个数,初始值为1,open之后先自减,判断是否不为0,保证同一时刻只能有一个进程在操作设备。(具体实现如下)


  • led_drv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
//共享资源
static int open_cnt = 1; //记录LED打开的状态开关
static int led_open(struct inode *inode, 
                        struct file *file)
{
    unsigned long flags;
    //屏蔽中断
    local_irq_save(flags);
    //临界区
    if(--open_cnt != 0) {
        printk("设备已被打开!\n");
        open_cnt++;
        //恢复中断
        local_irq_restore(flags);
        return -EBUSY;//返回设备忙错误码
    }
    //恢复中断
    local_irq_restore(flags);
    printk("设备打开成功!\n");
    return 0; //open返回成功
}
static int led_close(struct inode *inode, 
                        struct file *file)
{
    unsigned long flags;
    //屏蔽中断
    local_irq_save(flags);
    //临界区
    open_cnt++;
    //恢复中断
    local_irq_restore(flags);
    return 0;
}
//定义初始化硬件操作接口对象
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .release = led_close
};
//定义初始化混杂设备对象
static struct miscdevice led_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "myled",
    .fops = &led_fops
};
static int led_init(void)
{
    misc_register(&led_misc);
    return 0;
}
static void led_exit(void)
{
    misc_deregister(&led_misc);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");


  • led_test.c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int main(void)
{
    int fd;
    fd = open("/dev/myled", O_RDWR);
    if (fd < 0) {
        printf("打开设备失败!\n");
        return -1;
    }
    sleep(100000000);
    close(fd);
    return 0;
}


  • Makefile
obj-m += led_drv.o
all:
  make -C /opt/kernel SUBDIRS=$(PWD) modules
clean:
  make -C /opt/kernel SUBDIRS=$(PWD) clean


  • 执行结果(先后台运行一个led_test程序,再尝试运行一个进程试一下):

20191231080044558.png

  • 可以看到,当后台运行了一个进程在使用设备的时候,再有一个进程尝试打开设备就会失败(: Device or resource busy)。
  • 前一章描述的关于按键中断处理存在竞态的问题是单独一个进程在多核情况下导致的,所以使用中断屏蔽没不能解决问题,所以中断屏蔽并不适用于多核导致的竞态问题。


相关文章
|
13天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
54 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
存储 Linux 开发工具
如何进行Linux内核开发【ChatGPT】
如何进行Linux内核开发【ChatGPT】
|
3月前
|
Java Linux API
Linux设备驱动开发详解2
Linux设备驱动开发详解
41 6
|
3月前
|
消息中间件 算法 Unix
Linux设备驱动开发详解1
Linux设备驱动开发详解
46 5
|
3月前
|
移动开发 监控 网络协议
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
|
3月前
|
缓存 负载均衡 网络协议
Linux的TCP连接数量与百万千万并发应对策略
【8月更文挑战第15天】在Linux系统中,关于TCP连接数量的一个常见误解是认为其最大不能超过65535个。这一数字实际上是TCP端口号的上限,而非TCP连接数的直接限制。实际上,Linux服务器能够处理的TCP连接数远远超过这一数字,关键在于理解TCP连接的标识方式、系统配置优化以及应用架构设计。
430 2
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
|
3月前
|
网络协议 Linux
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
|
4月前
|
弹性计算 运维 自然语言处理
阿里云OS Copilot测评:重塑Linux运维与开发体验的智能革命
阿里云OS Copilot巧妙地将大语言模型的自然语言处理能力与操作系统团队的深厚经验相结合,支持自然语言问答、辅助命令执行等功能,为Linux用户带来了前所未有的智能运维与开发体验。
|
4月前
|
Ubuntu Linux Docker
Java演进问题之Alpine Linux创建更小的Docker镜像如何解决
Java演进问题之Alpine Linux创建更小的Docker镜像如何解决