博客
关于我
Linux并发与同步专题 (3) 信号量
阅读量:674 次
发布时间:2019-03-16

本文共 2429 字,大约阅读时间需要 8 分钟。

信号量(Semaphore)是操作系统中常用的同步机制,用于管理进程间的互斥和同步问题。本文将深入探讨信号量的实现原理、初始化方法以及常见的down()/up()操作函数。

信号量数据结构

信号量由struct semaphore结构体描述,主要成员包括:

  • spinlock_t lock:用于保护信号量中的count和wait_list成员,spinlock是一种EncodingException,允许在持锁状态下进行短时间内_Draw的操作。
  • unsigned int count:表示允许进入临界区的内核执行路径个数。
  • list_head wait_list:用于管理所有在该信号量上睡眠的进程,未成功获取锁的进程会在这个链表上等待。
  • 信号量还定义了一个与其相关的struct semaphore_waiter结构体,该结构体用于描述等待信号量的进程:

    • list_head list:表示该进程在信号量的等待队列中的位置。
    • task_struct task*:指向等待信号量的进程结构。
    • bool up:标记该进程是否需要被唤醒。

    信号量的初始化

    信号量的初始化分为两种:动态初始化和静态定义。两种方式均通过__SEMAPHORE_INITIALIZER()初始化相关成员变量。

    #define __SEMAPHORE_INITIALIZER(name, n) {    .lock        = __RAW_SPIN_LOCK_UNLOCKED((name).lock),    .count        = n,    .wait_list    = LIST_HEAD_INIT((name).wait_list),}#define DEFINE_SEMAPHORE(name)    struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)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);}

    down()/up()

    信号量的使用基础上,down()/up()函数对信号量的加锁和解锁操作起着关键作用。

    down()的实现主要包括以下步骤:

    void down(struct semaphore *sem) {    unsigned long flags;    raw_spin_lock_irqsave(&sem->lock, flags);    if (likely(sem->count > 0)) {        sem->count--;    } else {        __down(sem);    }    raw_spin_unlock_irqrestore(&sem->lock, flags);}

    当信号量.count大于0时,本地加锁并减少count值,表示当前进程已获得信号量。否则,调用__down()进入等待队列。

    __down()函数会根据不同的 errno类型调用__down_common(),参数state决定进程进入哪种睡眠状态:

    • TASK_UNINTERRUPTIBLE:在不可中断睡眠,直到信号量被唤醒。
    • TASK_INTERRUPTIBLE或TASK_KILLABLE:进入可中断或不可中断但可杀死的睡眠等待。

    down_interruptible()与down()类似,但进程进入可中断睡眠状态。

    down_killable()允许进程在不可中断状态下被唤醒。

    down_timeout()是在超时后唤醒的特定实现。

    down_trylock()尝试获取锁但不阻塞。

    int down_trylock(struct semaphore *sem) {    unsigned long flags;    int count;    raw_spin_lock_irqsave(&sem->lock, flags);    count = sem->count - 1;    if (likely(count >= 0)) {        sem->count = count;    }    raw_spin_unlock_irqrestore(&sem->lock, flags);    return (count < 0);}

    up()函数的实现相对简单:

    void up(struct semaphore *sem) {    unsigned long flags;    raw_spin_lock_irqsave(&sem->lock, flags);    if (list_empty(&sem->wait_list)) {        sem->count++;    } else {        __up(sem);    }    raw_spin_unlock_irqrestore(&sem->lock, flags);}

    信号量与spinlock的对比

    spinlock和信号量都是同步机制,但主要区别如下:

    • spinlock:不允许进程在加锁期间进入睡眠,采用忙等待策略。同一时刻只能被一个内核代码路径持有,最适用于快速完成的临界区保护。
    • 信号量:允许进程在加锁失败时进入睡眠状态。同一时刻可以由多个进程持有,最适用于加锁时间较长或需要等待的场景。

    转载地址:http://fpoqz.baihongyu.com/

    你可能感兴趣的文章
    ofborg 项目常见问题解决方案
    查看>>
    Ofelia:在Pd中融合openFrameworks与Lua的创意编程利器
    查看>>
    Office 2024 专业增强版安装教程(附安装包),高效办公由此开启
    查看>>
    Office 365身份认证管理-安装并配置活动目录同步
    查看>>
    Office online server 部署
    查看>>
    office 中墨迹书写工具_自动生成英文书法稿纸的几个网址,及Briem 的cursive italic书写教程...
    查看>>
    Office2010每次启动都要配置的解决办法
    查看>>
    Office2016 打开excel出现丢失appvisvsubsystems32.dll
    查看>>
    Office365 PowerShell打开邮箱审计功能
    查看>>
    OfficeWeb365 Indexs 任意文件读取漏洞复现
    查看>>
    OfficeWeb365 Readfile 任意文件读取漏洞复现
    查看>>
    OfficeWeb365 SaveDraw 文件上传漏洞复现
    查看>>
    office中的所有content type
    查看>>
    office之Excel 你会用 Ctrl + E 吗?
    查看>>
    Office办公软件里的“开发工具”选项卡-ChatGPT4o作答
    查看>>
    Office开发工具选项卡中的控件-ChatGPT4o作答
    查看>>
    Offline Installation the .NET Framework 3.5 on Windows 8
    查看>>
    OGC服务标准(地图资料篇.3)
    查看>>
    OGG初始化之使用数据库实用程序加载数据
    查看>>
    ogg参数解析
    查看>>