首页 > 系统相关 >linux 内核 ---信号量(semaphore)

linux 内核 ---信号量(semaphore)

时间:2023-10-18 23:46:31浏览次数:41  
标签:信号量 struct list --- semaphore sem down

信号量使用说明

(1)定义信号量

struct semaphore sem;

(2)初始化信号量

void sema_init(struct semaphore *sem, int val);

该函数初始化信号量,并设置信号量sem的值为val。

(3)获得信号量

extern void down(struct semaphore *sem);
extern int __must_check down_interruptible(struct semaphore *sem);
extern int __must_check down_killable(struct semaphore *sem);
extern int __must_check down_trylock(struct semaphore *sem);
extern int __must_check down_timeout(struct semaphore *sem, long jiffies);

void down(struct semaphore * sem);

该函数用于获得信号量sem,它会导致睡眠,因此不能在中断上下文中使用。

int down_interruptible(struct semaphore * sem);

该函数功能与down类似,不同之处为,因为down()进入睡眠状态的进程不能被信号打断,但因为down_interruptible()进入睡眠状态的进程能被信号打断,信号也会导致该函数返回,这时候函数的返回值非0。在使用down_interruptible()获取信号量时,对返回值一般会进行检查,如果非0,通常立即返回- ERESTARTSYS

int down_trylock(struct semaphore * sem);

该函数尝试获得信号量sem,如果能够立刻获得,它就获得该信号量并返回0,否则,返回非0值。它不会导致调用者睡眠,可以在中断上下文中使用。

(4)释放信号量

void up(struct semaphore * sem);

该函数释放信号量sem,唤醒等待者。

信号量原理

struct semaphore {
    raw_spinlock_t        lock; // 对于信号量的操作,比如获取信号量时的减一操作,都需要做临界区保护(critial section),通过自旋锁实现临界区
    unsigned int        count; 
    struct list_head    wait_list; // 当 count 为0时表示无法获取到信号量,需要把获取信号量的当前线程记录到这个链表,等 up 操作时唤醒等待信号量的线程
};

释放信号量函数时,发现链表内记录着等待此信号量的线程,唤醒线程

void up(struct semaphore *sem)
{
    unsigned long flags;

    raw_spin_lock_irqsave(&sem->lock, flags);
    if (likely(list_empty(&sem->wait_list)))
        sem->count++;
    else
        __up(sem);
    raw_spin_unlock_irqrestore(&sem->lock, flags);
}

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 = true;     wake_up_process(waiter->task); }
 

获取信号量时,发现count为0,把当前线程记录到信号量的链表里,释放自旋锁,启调度



void down(struct semaphore *sem)
{
    unsigned long flags;

    might_sleep();     raw_spin_lock_irqsave(&sem->lock, flags);     if (likely(sem->count > 0))         sem->count--;     else         __down(sem);     raw_spin_unlock_irqrestore(&sem->lock, flags); }
static noinline void __sched __down(struct semaphore *sem)
{
    __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}

static inline int __sched __down_common(struct semaphore *sem, long state,
                                long timeout)
{
    struct semaphore_waiter waiter;

    list_add_tail(&waiter.list, &sem->wait_list);
    waiter.task = current;
    waiter.up = false;

    for (;;) {
        if (signal_pending_state(state, current))
            goto interrupted;
        if (unlikely(timeout <= 0))
            goto timed_out;
        __set_current_state(state);
        raw_spin_unlock_irq(&sem->lock);
        timeout = schedule_timeout(timeout);
        raw_spin_lock_irq(&sem->lock);
        if (waiter.up)
            return 0;
    }

 timed_out:
    list_del(&waiter.list);
    return -ETIME;

 interrupted:
    list_del(&waiter.list);
    return -EINTR;
}

无论是释放信号量,还是获取信号量,临界区的实现都是通过自旋锁。所以在多核场景下,一个核如果获取了自旋锁操作信号量参数,其他核尝试获取锁会自旋在那。在临界区内如果需要睡眠,会先释放自旋锁,从而允许其他线程能够执行。

 

标签:信号量,struct,list,---,semaphore,sem,down
From: https://www.cnblogs.com/god-of-death/p/17773680.html

相关文章

  • 服务部署图绘制--Mermaid
    官网:https://mermaid.js.org/syntax/flowchart.html 例子:https://blog.csdn.net/weixin_55508765/article/details/125735923 npminstallmermaid <template><divclass="test-container"><h1>输入编辑流程图</h1><divcla......
  • Atcoder Beginner Contest 324 G Generate Arrays 题解-Treap
    为了更好的阅读体验,请点击这里题目链接套上平衡树板子就能做的很快的题,然后因为是指针存树,因此交换只需要把序列大小较小的挨个拿出来插到相应的地方即可。复杂度\(O(N\log^2N)\)。但是一定要记住不可以直接使用std::swap交换包含带有指针的类的实例(如代码中的Treap类)!......
  • Pytorch-(三)张量
    1、张量支持的数据类型  (1)获取/设置Pytorch默认的张量类型importtorch#2、张量Tensor#2.1、获取/设置Pytorch的默认类型defDefaultType_func():dtype=torch.tensor([1,2,3.4]).dtypeprint("张量Tensor的默认类型为:",dtype)print("") 2、张量生成......
  • 2023-2024-1 20231402《计算机基础与程序设计》第四周学习总结
    2023-2024-120231402《计算机基础与程序设计》第四周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第4周作业这个作业的目标自学计算机科学概论第4章,第5章,《C语言程序设计》第3章......
  • 基于Python的《计算机组成原理》在线学习平台-计算机毕业设计源码+LW文档
    摘 要 随着互联网的发展,通过计算机来学习是当前非常流行的一种学习方式。通过课程虽然可以面对面的进行交流和学习,但是很多时候因为地区和空间的限制会受到很多的影响但是通过网络来进行学习可以打破这一局限性,为此我开发了本基于Python的《计算机组成原理》在线学习平台网站......
  • 基于python的旅游网站-计算机毕业设计源码+LW文档
    摘 要 随着时代的发展,人们对旅游也越来越重视,近些年来我国的旅游产业也发生了翻天覆地的变化,但是很多人在出去旅游的时候不知道去哪里旅游,在预订酒店和机票的时候也没有一个综合性的旅游网站,为了让人们的旅游变的更加的方便,为此我开发了本基于python的旅游网站本基于python的......
  • openGauss学习笔记-103 openGauss 数据库管理-管理数据库安全-客户端接入之SSL证书管
    openGauss学习笔记-103openGauss数据库管理-管理数据库安全-客户端接入之SSL证书管理-证书生成openGauss默认配置了通过openssl生成的安全证书、私钥。并且提供证书替换的接口,方便用户进行证书的替换。103.1操作场景在测试环境下,用户可以用通过以下方式进行数字证书测试。在......
  • ic下载安装下载-简体中文版-正版下载 软件激活版
    AdobeInCopy2023作为一款音频制作剪辑软件,Audition2021具备非常强大的功能,可以满足音频工作者在各种制作场景下的需求。这款软件在界面设计和用户体验方面也做了很多优化,让用户可以更加方便快捷地进行各种操作。其中,波形编辑器中的插入模式和关键帧拖动功能的优化,无疑是Audition......
  • dreamweaver下载-dreamweaver最新版 软件激活版
    AdobeDreamweaver官方简介AdobeDreamweaver,简称“DW”,中文名称"梦想编织者",最初为美国MACROMEDIA公司开发,2005年被Adobe公司收购。Macromedia,Inc(纳斯达克:MACR),成立于1992年,2005年被Adobe公司收购。在全球信息产业迅猛发展的今天,Macromedia公司把发展的重点转向以中国大陆地......
  • 习题专题- 运用递归 输出第n个 斐波那契数
    斐波那契数 1123581321...............#include<stdio.h>intxy(intn){ if(n<=2) { return1; } else { returnxy(n-1)+xy(n-2); }}intmain(){ intn=0; intret=0;printf("请输入要查找第几个:") scanf("%d",&......