当前位置: 首页 > news >正文

linux 内核同步互斥技术之信号量

信号量

信号量允许多个进程同时进入临界区,大多数情况下只允许一个进程进入临界区,把信号量的计数值设置为 1,即二值信号量,这种信号量称为互斥信号量。可允许多个锁持有者。
和自旋锁相比,信号量适合保护比较长的临界区,因为竞争信号量时进程可能睡眠和再次唤醒,代价很高。中断服务函数不能进行睡眠,因此信号量不能用于中断当中
信号量的使用流程:
定义一个信号量
    ↓
初始化信号量
    ↓
获得信号量(减操作)
    ↓
释放信号量(加操作)

内核使用的信号量定义如下:
include/linux/semaphore.h
struct semaphore {
    raw_spinlock_t      lock;
    unsigned int        count;
    struct list_head    wait_list;
};
成员 lock 是自旋锁,用来保护信号量的其他成员。
成员 count 是计数值,表示还可以允许多少次进入临界区。
成员 wait_list 是等待进入临界区的进程链表。
struct semaphore_waiter {
    struct task_struct *task;
    bool up;
    struct list_head list;
};

初始化静态信号量的方法如下。
(1)    __SEMAPHORE_INITIALIZER(name, n):指定名称和计数值,允许同时n 次进入临界区。
(2)    DEFINE_SEMAPHORE(name):初始化一个互斥信号量。
在运行时动态初始化信号量的方法如下:
static inline void sema_init(struct semaphore *sem, int val);
参数 val 指定允许同时进入临界区的数量。
获取信号量的函数如下。
(1) void down(struct semaphore *sem);
获取信号量,如果计数值是 0,进程深度睡眠。
(2) int down_interruptible(struct semaphore *sem);
获取信号量,如果计数值是 0,进程轻度睡眠(可以被系统消息打断,该函数的调用允许中断)。如果返回0,表示获得信号量正常返回,如果被信号打断,返回-EINTR。
(3) int down_killable(struct semaphore *sem);
获取信号量,如果计数值是 0,进程中度睡眠(可以因为受到致命信号而被唤醒)。
(4) int down_trylock(struct semaphore *sem);
获取信号量,如果计数值是 0,进程不等待不会导致调用者睡眠。
(5) int down_timeout(struct semaphore *sem, long jiffies);
获取信号量,指定等待的时间。
释放信号量的函数如下:
void up(struct semaphore *sem);


使用示例

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h> 
#include <linux/semaphore.h> 
#include <linux/delay.h>

int num[2][5]= { {
        0,2,4,6,8
    }
    , {
        1,3,5,7,9
    }
}
;
struct semaphore sem_first;
struct semaphore sem_second;
struct task_struct * task1;
struct task_struct * task2;

int thread_print_first(void *p) {
    int i;
    int *num=(int *)p;
    if(kthread_should_stop()){
        return 0;
    }
    printk(KERN_ALERT"Hello World:first\n");
    for (i=0;i<5;i++) {
        down(&sem_first);
        printk(KERN_ALERT"Hello World:%d\n",num[i]);
        up(&sem_second);
    }
    do {
        msleep(1000);
    }
    while(!kthread_should_stop());
    return 0;
}

int thread_print_second(void *p) {
    int i;
    int *num=(int *)p;
    if(kthread_should_stop()){
        return 0;
    }
    printk(KERN_ALERT"Hello World:second\n");
    for (i=0;i<5;i++) {
        down(&sem_second);
        printk(KERN_ALERT"Hello World:%d\n",num[i]);
        up(&sem_first);
    }
    do {
        msleep(1000);
    }
    while(!kthread_should_stop());
    return 0;
}

static int hello_init(void) {
    printk(KERN_ALERT"Hello World enter\n");
    sema_init(&sem_first,1);
    sema_init(&sem_second,0);
    task1 = kthread_create(thread_print_first,num[0],"first");
    if(IS_ERR(task1)) {
        printk(KERN_ALERT"kthread_create error!\n");
        return -1;
    }
    task2 = kthread_create(thread_print_second,num[1],"second");
    if(IS_ERR(task2)) {
        printk(KERN_ALERT"kthread_create error!\n");
        kthread_stop(task1);
        return -1;
    }
    wake_up_process(task1);
    wake_up_process(task2);
    return 0;
}

static void hello_exit(void) {
    int ret;
    if (!IS_ERR(task1)) {
        ret = kthread_stop(task1);
        printk("<<<<<<<<task1 exit, ret = %d\n", ret);
    }
    if (!IS_ERR(task2)) {
        ret = kthread_stop(task2);
        printk("<<<<<<<<task2 exit, ret = %d\n", ret);
    }
    printk(KERN_ALERT"hello world exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

 

相关文章:

linux 内核同步互斥技术之信号量

信号量 信号量允许多个进程同时进入临界区&#xff0c;大多数情况下只允许一个进程进入临界区&#xff0c;把信号量的计数值设置为 1&#xff0c;即二值信号量&#xff0c;这种信号量称为互斥信号量。可允许多个锁持有者。 和自旋锁相比&#xff0c;信号量适合保护比较长的临界…...

交通强国添力量 无人机巡航为何备受期待?

在高速建设交通强国的过程中&#xff0c;交通运输部海事局计划完善“陆海空天”一体化水上交通运输安全保障体系。无人机巡航系统将在提升海事船舶监管和水上搜救能力方面发挥关键作用&#xff0c;以构建更为全面的监管体系。尽管已初步建立了海事监管体系&#xff0c;但仍存在…...

【PID学习笔记 6 】控制系统的性能指标之二

写在前面 上文介绍了控制系统的稳态与动态、过渡过程、阶跃响应以及阶跃信号作用下过渡过程的四种形式。本文紧接上文&#xff0c;首先总结过渡过程的分类&#xff0c;然后介绍控制系统的性能评价&#xff0c;最后重点介绍控制系统性能指标中的单项指标。 一、过渡过程的分类…...

ZLMediakit-method ANNOUNCE failed: 401 Unauthorized(ffmpeg、obs推流rtmp到ZLM发现的问题)

错误截图 解决办法&#xff1a;能推流成功&#xff0c;但是不能写入到wvp数据库中 修改配置文件config.ini 改成0 修改之后 重启服务 systemctl restart zlm*推流成功 解决办法&#xff1a;能推流&#xff0c;能写入数据库中 替换zlm版本&#xff0c;可以用我文章中提供的编译…...

聊聊logback的ThrowableProxyConverter

序 本文主要研究一下logback的ThrowableProxyConverter ThrowableHandlingConverter ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java /*** Converter which handle throwables should be derived from this class.**/ public abstract class ThrowableHa…...

Kubernetes(k8s)访问不了Pod服务

在k8s集群部署java web应用的服务时&#xff0c;浏览器访问不了pod服务或linux终端curl http://192.168.138.112:30000即curl http://ip地址:端口号失败&#xff0c;如下图&#xff1a; 在网上找了很久的答案&#xff0c;最后还是没解决&#xff0c;后来突然想起来一直是在k8…...

python-学生管理|汉罗塔

1.编写程序&#xff0c;实现学生信息管理系统。 运行程序&#xff0c;在控制台输入“1”之后的结果如下所示&#xff1a; 学生管理系统 1.添加学生信息 2.删除学生信息 3.修改学生信息 4.显示所有学生信息 0.退出系统 请选择功能&#xff1a;1 请输入新学生的姓名:小红 请输入…...

python 堆与栈

【一】堆与栈 【 1 】简介 栈&#xff08;stack&#xff09;&#xff0c;有些地方称为堆栈&#xff0c;是一种容器&#xff0c;可存入数据元素、访问元素、删除元素&#xff0c;它的特点在于只能允许在容器的一端&#xff08;称为栈顶端指标&#xff0c;英语&#xff1a;top&a…...

园区规划技术要点

&#xff08;一&#xff09;技术点介绍 1.WLAN&#xff1a;无线局域网WLAN&#xff08;Wireless Local Area Network&#xff09;是一种无线计算机网络&#xff0c;使用无线信道代替有线传输介质连接两个或多个设备形成一个局域网LAN&#xff08;Local Area Network&#xff09…...

深入浅出 Linux 中的 ARM IOMMU SMMU III

系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的 dma_alloc_coherent()/dma_alloc_attrs() 等接口。dma_alloc_coherent()/dma_alloc_attrs() 等接口通过 DMA IOMMU 的回调分配内存&#xff0c;并为经过 IOMMU 的 DMA 内…...

Linux系统---图书管理中的同步问题

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、问题描述 &#xff08;1&#xff09;图书馆阅览室最多能够容纳N&#xff08;N5&#xff09;名学生&#xff0c;若有更多学生想…...

Vue学习笔记-activated和deactivated生命周期

作用 路由组件所独有的2个生命周期 activated生命周期函数用于在路由组件每次由消失到出现时所调用的函数deactivated生命周期函数用于路由组件每次由出现到消失时&#xff08;无论是否缓存&#xff09;所调用的函数 案例 定义一个NewsVue组件&#xff0c;要求&#xff1a;…...

102.套接字-Socket网络编程4(TCP通信流程)

目录 TCP编程流程 套接字函数 1.创建套接字 2.绑定地址 3.监听连接请求 4.接受连接 5. 连接到服务器 6. 发送数据 7. 接收数据 8.关闭套接字 服务器端通信流程 示例代码 客户端通信流程 代码示例 TCP编程流程 TCP是一个面向连接的&#xff0c;安全的&#xff0c;流…...

spring boot 2 升级到 spring boot 3 后文件上传失败

背景 项目需要&#xff0c;要求升级 spring boot 2.7 到 spring boot 3.2&#xff0c;升级过程中发现很多不兼容问题&#xff0c;下面说明文件上传失败的解决方案。 问题 spring boot 2 中不需要额外的配置&#xff0c;直接在 Controller 中配置 MultipartFile 接收页面传的…...

Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象

Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异&#xff0c;并取出不同的对象。这可以通过使用 distinct() 和 filter() 方法来实现。 假设我们有两个 List&#xff0c;一个是 list1&#xff0c;另一个是 list2&#xff0c;我们想找出 list1 中存在但 list2…...

C语言还会存在多久

一、C语言的生命力 在当前的科技发展和就业市场需求下&#xff0c;可以肯定地说C语言并没有像一些新兴语言&#xff08;如Python、JavaScript等&#xff09;那样受到大量的关注。然而&#xff0c;并不意味着学习C语言的人会越来越少。 首先&#xff0c;C语言作为一种深受尊重…...

手持式安卓主板_PDA安卓板_智能手持终端方案

手持式安卓主板方案是一种智能终端设备&#xff0c;具备自动对焦和闪光灯功能&#xff0c;可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能&#xff0c;为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板&#xff0c;并搭载了八…...

LeetCode103. Binary Tree Zigzag Level Order Traversal

文章目录 一、题目二、题解 一、题目 Given the root of a binary tree, return the zigzag level order traversal of its nodes’ values. (i.e., from left to right, then right to left for the next level and alternate between). Example 1: Input: root [3,9,20,n…...

PHP 判断给定两个时间是否在同一周,月,年

判断是否在同一周 date_default_timezone_set(PRC); //判断是否在同一周&#xff0c;原理&#xff1a;求出其中一个时间戳所在周的周一凌晨时间戳和周日24.00时间戳&#xff0c;如果另一个时间戳在这个范围内&#xff0c;则说明在同一周&#xff0c;否则不在同一周 function g…...

单机无锁线程安全队列-Disruptor

Disruptor 1、基本介绍 说到队列&#xff0c;除了常见的mq中间件&#xff0c;java中也自带线程安全的BlockingQueue&#xff0c;但是BlockingQueue通过在入队和出队时加锁的方式避免并发操作&#xff0c;性能上会大打折扣。 而Disruptor是一个线程安全、低延迟、吞吐量高的队…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...