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 内核同步互斥技术之信号量
信号量 信号量允许多个进程同时进入临界区,大多数情况下只允许一个进程进入临界区,把信号量的计数值设置为 1,即二值信号量,这种信号量称为互斥信号量。可允许多个锁持有者。 和自旋锁相比,信号量适合保护比较长的临界…...

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

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

ZLMediakit-method ANNOUNCE failed: 401 Unauthorized(ffmpeg、obs推流rtmp到ZLM发现的问题)
错误截图 解决办法:能推流成功,但是不能写入到wvp数据库中 修改配置文件config.ini 改成0 修改之后 重启服务 systemctl restart zlm*推流成功 解决办法:能推流,能写入数据库中 替换zlm版本,可以用我文章中提供的编译…...
聊聊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应用的服务时,浏览器访问不了pod服务或linux终端curl http://192.168.138.112:30000即curl http://ip地址:端口号失败,如下图: 在网上找了很久的答案,最后还是没解决,后来突然想起来一直是在k8…...

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

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

园区规划技术要点
(一)技术点介绍 1.WLAN:无线局域网WLAN(Wireless Local Area Network)是一种无线计算机网络,使用无线信道代替有线传输介质连接两个或多个设备形成一个局域网LAN(Local Area Network)…...

深入浅出 Linux 中的 ARM IOMMU SMMU III
系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的 dma_alloc_coherent()/dma_alloc_attrs() 等接口。dma_alloc_coherent()/dma_alloc_attrs() 等接口通过 DMA IOMMU 的回调分配内存,并为经过 IOMMU 的 DMA 内…...

Linux系统---图书管理中的同步问题
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、问题描述 (1)图书馆阅览室最多能够容纳N(N5)名学生,若有更多学生想…...
Vue学习笔记-activated和deactivated生命周期
作用 路由组件所独有的2个生命周期 activated生命周期函数用于在路由组件每次由消失到出现时所调用的函数deactivated生命周期函数用于路由组件每次由出现到消失时(无论是否缓存)所调用的函数 案例 定义一个NewsVue组件,要求:…...

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

spring boot 2 升级到 spring boot 3 后文件上传失败
背景 项目需要,要求升级 spring boot 2.7 到 spring boot 3.2,升级过程中发现很多不兼容问题,下面说明文件上传失败的解决方案。 问题 spring boot 2 中不需要额外的配置,直接在 Controller 中配置 MultipartFile 接收页面传的…...
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象。这可以通过使用 distinct() 和 filter() 方法来实现。 假设我们有两个 List,一个是 list1,另一个是 list2,我们想找出 list1 中存在但 list2…...
C语言还会存在多久
一、C语言的生命力 在当前的科技发展和就业市场需求下,可以肯定地说C语言并没有像一些新兴语言(如Python、JavaScript等)那样受到大量的关注。然而,并不意味着学习C语言的人会越来越少。 首先,C语言作为一种深受尊重…...

手持式安卓主板_PDA安卓板_智能手持终端方案
手持式安卓主板方案是一种智能终端设备,具备自动对焦和闪光灯功能,可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能,为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板,并搭载了八…...
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); //判断是否在同一周,原理:求出其中一个时间戳所在周的周一凌晨时间戳和周日24.00时间戳,如果另一个时间戳在这个范围内,则说明在同一周,否则不在同一周 function g…...

单机无锁线程安全队列-Disruptor
Disruptor 1、基本介绍 说到队列,除了常见的mq中间件,java中也自带线程安全的BlockingQueue,但是BlockingQueue通过在入队和出队时加锁的方式避免并发操作,性能上会大打折扣。 而Disruptor是一个线程安全、低延迟、吞吐量高的队…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...