Linux设备驱动之semaphore机制

第十章 GPU 虚拟地址空间管理:10.2 GPU 虚拟地址空间演进与职责划分 本文梳理了GPU地址空间管理从提交时定址到VM_BIND的演进历程,分析了每种形态下内核与用户态的职责分工。随着硬件支持独立页表,地址分配权逐步下放至用户态,提交路径上的重定位与BO列表校验被移入虚拟机(VM)状态维护。为应对稀疏资源、显式同步等现代需求,VM_BIND成为主流,要求内核长期维护映射、驻留与同步状态。文章提出drm_gpuvm作为通用库,承担区间簿记、对象关联、加锁驻留等与硬件无关的职责,驱动则负责页表生成、绑定调度等硬件相关实现,形成清晰的职责划分。 阅读详情
Linux设备驱动之semaphore机制
在Linux系统中,信号号是一种重要的加锁机制,特别在互斥型资源中,semaphore更能很好的工作。
1: semaphore结构体定义
在Linux2.6.35内核中,semaphore的实现机制与以前的版本一点不同,在其中去除了DECLARE_MUTEX_LOCKED这个初始化互斥宏定义,但是,又添加了一个特别重要的函数,down_killable,这个函数的添加,使此版本的semaphore机制比以往的更强。semaphore结构全定义如下所示。
C/C++ code
struct semaphore { spinlock_t lock; /* 自旋锁结构体变量 */ unsigned int count; /* 用于计录资料数量 */ struct list_head wait_list; /* 内部链表结构体变量 */ };

从此结构体中可以看从,semaphore机制也就是自旋锁的包装,在后面的分析中,读者将会明白我为什么会这样说。
2: semaphore提供的操作函数
在semaphore机制中,系统给我们提供也几个函数用于操作,正因为内核给 
我们提供了这些函数接口,我们才能应用其来更好的完成我们对互斥型资料的加锁,使其能准确无误的在SMP或者多线程中应用。semaphore提供接口函数如下所示。
 DECLARE_MUTEX
 init_MUTEX
 init_MUTEX_LOCKED
 down
 down_interruptible
 down_killable
 down_trylock
 down_timeout
 up

3 DECLARE_MUTEX接口分析
DECLARE_MUTEX接口为一个宏定义,此定义调用另一个宏定义来完成对 
互斥型信号量进行初始化,其原型如下。
C/C++ code
#define DECLARE_MUTEX(name) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)

此宏用于初始化一个名为name的信号量,并把其资料数初始化为1。其中name为信号的名字,name为符合系统的标号,且不需提前定义。比如我们想定义一个名为my_semaphore的互斥型信号量,并把它初始化为1,我们将应用这个接口来实现,实现代码如下。
C/C++ code
DECLARE_MUTEX(my_semaphore);

从DECLARE_MUTEX宏义看出,此宏是通过调用另一个宏来实现的,此宏定义实现如下。
C/C++ code
#define __SEMAPHORE_INITIALIZER(name, n) \ { \ .lock = __SPIN_LOCK_UNLOCKED((name).lock), \ .count = n, \ .wait_list = LIST_HEAD_INIT((name).wait_list), \ }

4 init_MUTEX接口分析
init_MUTEX接口用于动态初始化一个信号量,此接口也是一个宏定义,通 
过调用sema_init函数来完成,此宏定义原型如下。
C/C++ code
#define init_MUTEX(sem) sema_init(sem, 1)

其中sem为struct semaphore结构体变量,所以,在应用此宏来初始化一个信号前,必须定义一个struct semaphore结构体变量。此宏初始化一个名为sem的信号量,并把其资料初始化为1。
在此宏中我们看到,宏定义是通过调用sema_init函数来完成初始化的,所可,可以这样说,真正初始化sem信号量的应该是sema_init函数。为了读者方便查看,所以在此把sema_init函数的实现过程列出,关于此函数请读者自行查看\include\linux\semaphore.h文件,这样读者对semaphore的理解更加深入。sema_init函数实现如下。
C/C++ code
static inline void sema_init(struct semaphore *sem, int val) { static struct lock_class_key __key; *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val); lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0); }

5 init_MUTEX_LOCKED接口分析
init_MUTEX_LOCKED接口的实现与init_MUTEX接口的实现过程是一样的, 
只是此接口把资源数初始化为0。所以在此不再进行分析,其实现如下。
C/C++ code
#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)

6 __down_common函数分析
在进行分析互斥信号量相关操作之前,进行分析一个特别重要的函数,因为 
这个函数非常重要,semaphore的加锁操作都是基于这个函数实现的,所以,在分析它们之前进行分析这个函数,读者更加能看懂semaphore的实现过程。此函数的原型如下。
C/C++ code
static inline int __sched __down_common(struct semaphore *sem, long state, long timeout)

在此函数中应用到的task_struct相关的知识,对于task_struct的知识在这个函数本人不进行分析,同时也不进行说明,因为task_struct机制是一个复杂的机制,不是三言两语就能分析的。在此函数中同样应用自旋锁的知识,关于自旋锁的知识本人将会在自旋锁机制相关的文章进行分析,在此文章中就不进行分析。本函数中一个重要的是超时调度,这一调度的实现如下。由于应用自旋锁加以保护,所以,超时调试过程有可中断,也不可中断,这就要看传入的state是允许中断还是不允许中断。超时调度实现过程如下。
C/C++ code
timeout = schedule_timeout(timeout);

7 down接口分析
down接口用于请求一个信号量。此函数的调用将会到致调用线程的睡眠, 
直到获取到信号。同时,该函数的调用不允许中断。
在此函数中首先进行信号量资源数的查看,如果信号量数据(count)不为0,则把其减1,并返回,调用成功;否则调用__down进行等待,调用者进行睡眠。实现过程如下。
C/C++ code
void down(struct semaphore *sem) { unsigned long flags; spin_lock_irqsave(&sem->lock, flags); if (likely(sem->count > 0)) sem->count--; else __down(sem); spin_unlock_irqrestore(&sem->lock, flags); }

在此函数中引起调用者进行睡眠的函数是__down函数,在等待中能不能中断同样是由于__down函数引起,所以,关键点在于__down函数,__down函数的实现如下。
C/C++ code
static noinline void __sched __down(struct semaphore *sem) { __down_common(sem,TASK_UNINTERRUPTIBLE,\ MAX_SCHEDULE_TIMEOUT); }

在__down函数中,通过调用__down_common函数来进行相关的操作,在上面的分析中我提到,传给__down_common函数的state参数将决定调用者是否可以中断,所以,down接口在睡眠过程中不能中断就是因为传入的实参决定。所以,在编过程中,最好很用此接口,尽量应用down_interruptible、 down_killable接口替代。MAX_SCHEDULE_TIMEOUT为一个宏定义,实定义如下。
C/C++ code
#define MAX_SCHEDULE_TIMEOUT LONG_MAX

LONG_MAX同时也是一个宏定义,其定义如下。
C/C++ code
#define LONG_MAX ((long)(~0UL>>1))

所以,此接口不会因为超时而用,因为需要等待232-1个时钟滴答才能超时,这是一个很长的时间。所以,如果不使用up接口进行唤醒,整个进程将死掉。
9 down_interruptible接口分析
down_interruptible接口也是用于获取一个信号量,与down接口不同的是, 
此接口在等待过程中是可以被中断的,是正常返回还是被中断返回通过返回值进行判断,其它与down相同,所以,在此不再进行分析。
10 down_killable接口分析
down_killable与down_interruptible相同,只是传入的__down_common的实 
参不同,所以,在此不再进行分析。
11 down_trylock接口分析
down_trylock接口用于试着获取一个信号量,但是,此接口不会引起调用者 
的睡眠。不管有无可用信号量,都马上进行返回,如果返回0,则获取信号量成功,如果返回1,则获取失败。所以,在调用此接口时,必须进行返回的值的查看,看是否获取成功。其实现过程如下。
C/C++ code
int down_trylock(struct semaphore *sem) { unsigned long flags; int count; spin_lock_irqsave(&sem->lock, flags); count = sem->count - 1; if (likely(count >= 0)) sem->count = count; spin_unlock_irqrestore(&sem->lock, flags); return (count < 0); }

12 down_timeout接口分析
down_timeout接口的实现过程与down接口的实现过程差不多,只是此接口 
可以自定义超时时间,也就是如果在超时间内不能得到信号量,调用者会因为超时而自行唤醒。其实现过程如下,请注意超时参数的传入。
C/C++ code
int down_timeout(struct semaphore *sem, long jiffies) { unsigned long flags; int result = 0; spin_lock_irqsave(&sem->lock, flags); if (likely(sem->count > 0)) sem->count--; else result = __down_timeout(sem, jiffies); spin_unlock_irqrestore(&sem->lock, flags); return result; }

13 up接口分析
up接口用于唤醒处于等待的线程,对于某些不能获取信号量的线程,如果不 
强制唤醒,那么也许会造此线程的死掉,所以,才有up接口。此接口的实现比较简单,所以不进行详细的分析,其实现如下。
C/C++ code
static noinline void __sched __up(struct semaphore *sem) { struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list, struct semaphore_waiter, list); list_del(&waiter->list); waiter->up = 1; wake_up_process(waiter->task); }

14 关于其它说明
从开始学习嵌入式Linux到现在也有差不多4个月的时间了,从一味的看书
到走进Linux内核,这是本人的一个重大的进步,很多时候知其然而不知其所以然,写不出好的程序,所以,深入Linux是每个学习嵌入式Linux驱动开发学习者的必经之路,同时也是一个生的事。
Linux内核的不断发展,每一个版本之间都或多或少的有改变,如果不进行入其内核进行分析,那么这样就等于把自己限定于某一内核版本内,对自己的技术的提高、发展有很大的影响。同时,在工作中,不是你知道什么,会什么就做什么,而是需要做什么,不管你会与会都必须得做,所以,能不能深入Linux内核在一点上把不同能力的人给区分了。
在能不能看懂Linux内核的问题上,起决定作用的是个人的C语言能力,这也是C语言好坏的体现,如果C语言不好,那么就不能可看懂Linux内核,那么也就决定了个人的发展。所以说在嵌入式C语言是决定个人发展的重大条件,同时也是个人能力的体现。
扩散模型与强化学习(13):In-Context Reward Hacking现象与解决方案 奖励作弊(Reward Hacking)指智能体通过钻规则漏洞而非真正完成任务来最大化奖励信号。以论文编辑实验为例,研究提出“上下文奖励作弊”(ICRH)概念,即模型利用共享上下文钻空子,如盲目添加“正确!”或输出无关内容。实验发现,模型规模扩大可能加剧ICRH,且提示词优化难以根治。与传统奖励作弊不同,ICRH发生在部署阶段,由通用性驱动。应对建议包括多轮测试、多样化反馈及异常场景模拟,但尚无完美解决方案。 阅读详情

相关推荐

服务器被矿工入侵记录

一次服务器被矿工入驻的处理记录

王瑞的技术专栏 1332

Linux信号量semaphore

信号量整体的介绍,以及semaphore.h下一些函数的使用

Strange_Head的博客 3532

pta——特立独行的幸福

这是我认为比较复杂的一道题了,比较迷茫的点在于不知道要算各位平方和几次到不了1,才算他不是幸福数。突破口在于如果如果不是回到1也会有一些数字重复出现,只要重复出现的数字不是1,那就不是幸福数

m0_65620244的博客 4034

linux 信号量(semaphore)

在Linux中,信号量是一种用于实现进程间同步和互斥的机制。信号量通常用于控制对共享资源的访问,以确保多个进程之间不会同时访问关键资源,从而避免竞态条件和数据损坏。

weixin_47139576的博客 1448

TPAMI审稿人关注什么

写在开头:被tpami接收大概是每个cs er最开心的事情吧!今天阅读TPAMI的文章时,发现有扩刊的文章,也有不是扩刊的文章,那么这两类文章哪个更容易被接收呢?

carlous0的专栏 1684

Linux 无名信号量(Semaphore)的使用

通过使用信号量empty和full,可以确保生产者不会在缓冲区满时写入数据,而消费者不会在缓冲区空时尝试读取数据。可以看到,第一种程序,因为没有sleep()让出 cpu,会一直生产数据,直到 empty 为空,也就是等待缓冲区空位为0 ,程序阻塞,让出 cpu ,消费者开始进行处理,直到 full 为空,处理完毕,让出 cpu。无名信号量(也被称为POSIX信号量)是POSIX标准的一部分,与System V信号量相比,它提供了更丰富的功能和更好的可移植性。:初始化一个无名信号量。

weixin_46158019的博客 2171

apple游客下单逆向分析

Apple游客下单Cookies注册激活流程逆向分析与算法实现

吴秋霖的博客 1998

【Linux内核】信号量semaphore机制

信号量机制是一种用于控制并发访问的同步机制,常用于多进程或多线程之间的协调。在Linux内核中,信号量机制是通过struct semaphore结构体来实现的。每个semaphore结构体包含一个计数器和一个等待队列,它们用于跟踪当前可用的资源数量以及正在等待这些资源的进程或线程。当某个进程或线程需要访问共享资源时,它会先尝试获取信号量。如果信号量的计数器大于0,表示有可用的资源,该进程或线程就可以继续执行,并将信号量计数器减1;

逆风水手的博客 2382

大模型安全-生成检测-事实核查-攻击-防御-思考-记忆-融合-语音相关研究 2025年版

本文整理了关于大模型安全领域的综合性资源,包括7篇综述论文、9个安全数据集以及5篇强化学习相关的安全研究论文。主要涉及大模型的对抗攻击、隐私保护、安全评估等方向,涵盖TruthfulQA、ToxiGen等知名数据集和TrustLLM、HarmBench等关键研究。资源包括知乎博主分享、arXiv预印本和顶会论文,并附有详细的中文讲解链接,为研究者提供了系统性的安全研究参考。

CSPhD-winston的博客 3572

【OpenClaw从入门到精通】零基础入门——OpenClaw核心概念快速理解(2026入门版)

OpenClaw是一个强大的AI代理框架,旨在构建智能化的自动化任务处理系统。随着人工智能技术的快速发展,OpenClaw为开发者和企业提供了一个完整的解决方案,用于创建能够理解、学习和执行复杂任务的智能体。本文将带领零基础的读者快速理解OpenClaw的核心概念,从基础架构到实际应用,为后续深入学习奠定坚实基础。通过本文的学习,你将掌握OpenClaw的基本原理、核心组件和快速上手方法。

一键难忘的博客 323

Linux设备驱动之semaphore机制【转】

转自:http://blog.youkuaiyun.com/xiao229404041/article/details/7031776  Linux设备驱动之semaphore机制在Linux系统中,信号号是一种重要的加锁机制,特别在互斥型资源中,semaphore更能很好的工作。1: semaphore结构体定义在Linux2.6.35内核中,semaphore的实现机制与以前的版本一点不同,在其中去除了...

weixin_33742618的博客 89

【系统分析师】2025年下半年真题:案例分析-答案及详解(回忆版)

Redis相比Memcached在电商高并发场景下具有显著优势:支持持久化(RDB/AOF)、丰富数据结构(如有序集合实现排行榜)、原生支持集群和哨兵模式(高可用性)。布隆过滤器通过位数组和哈希函数预先存储所有合法订单ID,当查询请求到达时快速拦截无效ID(如伪造ID),避免其穿透缓存直接冲击数据库,从而预防缓存击穿问题。

数据知道的博客 5982

Kubernetes RBAC实战:ClusterRole与RoleBinding权限边界详解

访问控制是Kubernetes多租户与安全治理的基石,而RBAC(基于角色的访问控制)正是授权阶段最核心的机制。它通过“角色”与“绑定”分离设计,将权限规则和用户主体解耦,既实现了权限复用,又提升了灵活性。其中ClusterRole可以跨命名空间充当权限模板,RoleBinding则把模板限定在特定命名空间内生效,这种组合方式在CICD账号、监控账号等需要细粒度授权的场景中极为常见。理解ClusterRole与RoleBinding的边界,以及它们与ClusterRoleBinding、Role之间的差异,

weixin_33884611的博客 188

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

linux驱动面试题

linux驱动面试常见题和答案

kv110的专栏 1834

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Linux内核同步原语:信号量机制详解

Linux内核揭秘项目中的同步原语是保证多任务并发安全的核心机制,而信号量作为其中重要的一员,在资源管理和进程同步中发挥着关键作用。本文将从基础概念到内核实现,全面解析Linux内核信号量机制的工作原理与应用场景。 ## 信号量基础:解决并发问题的关键机制 在多任务操作系统中,多个进程或线程同时访问共享资源时,可能会导致数据不一致或冲突。信号量作为一种高效的同步原语,通过维护一个计数器来控制对

gitblog_00258的博客 365

Linux设备驱动器 之二 线程同步第二篇

Linux APIs 在Linux驱动器中的应用 NXP freescale系列QSPI 驱动器 变量定义 初始化 存取数据 如果有大块数据,使用AHB总线,通过存取映射的存储器,存取数据。 semaphore 数据结构 Linux APIs 在Linux驱动器中的应用 ELAN 的 Uxxx 系列驱动器 ELAN 的 Uxxx 系列适配器是 USB 转 PCMCIA CardBus 适配器 初始化 usb_set_intfdata将FTDI的驱动器数据写入驱动器的数据结构变量中。在需要的生活可

IT_Beijing_BIT的博客 521

漫谈兼容内核之二:关于kernel-win32的对象管理

近来屡有网友提到一个旨在将Wineserver移入内核的开源项目kernel-win32;有问及其本身,希望能对其代码作一些分析、讲解的,也有问及兼容内核与此项目之间关系的。所以从这篇漫谈开始就来谈谈kernel-win32。 首先,兼容内核项目应当从所有(能找到的)相关开源项目吸取营养,有时候甚至就采取“拿来主义”,反正都是开源项目,只要遵守有关的规定就行。从这个意义上说,我们对于kernel

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 795

【Linux】【并发】设备驱动中的并发控制

原子操作是指在一个操作中不可被中断的部分。在Linux内核中,原子操作通常用来更新共享变量而不必担心被其他任务打断。

极客代码 1395

设备驱动之一 - linux 信号量semaphore

转载地址:http://soft.yesky.com/os/lin/10/2303010_2.shtml   信号量(semaphore)   Linux内核的信号量在概念和原理上与用户态的System V的IPC机制信号量是一样的,但是它绝不可能在内核之外使用,因此它与System V的IPC机制信号量毫不相干。   信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问

渡江客涂鸦板 1523

设备驱动之一 - linux读写信号量semaphore .

读写信号量(rw_semaphore)   读写信号量对访问者进行了细分,或者为读者,或者为写者,读者在保持读写信号量期间只能对该读写信号量保护的共享资源进行读访问,如果一个任务除了需要读,可能还需要写,那么它必须被归类为写者,它在对共享资源访问之前必须先获得写者身份,写者在发现自己不需要写访问的情况下可以降级为读者。读写信号量同时拥有的读者数不受限制,也就说可以有任意多个读者同时拥有一个读

宇宙的起源 857
上一篇: 深入探讨this指针
下一篇: ubuntu 12.04下访问windows共享文件夹
计算机与认知
博客等级 码龄14年 31粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值