信号量、互斥锁、计数信号量

大家好,我叫徐锦桐,个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识,还有日常折腾的经验,欢迎大家来访。

信号量(semaphores)一个多进程共享的非负整型全局变量。信号量常用于多进程的进程同步。

介绍

信号量(semaphores)是一个简单的多进程共享非负 整型全局变量。

信号量简称为s,它除了初始化外只能通过两个标准原子(原子:一个进程修改信号量时,信号量不可被其他进程修改)操作:wait() 和 signal() 来访问。

wait()

wait()操作(也称 P 操作,荷兰语proberen,测试的意思),测试是否有其他进程使用该资源。\

Talk is cheap.Show you the code.。

cpp 复制代码
wait(semaphores S) {
    while(S <=0)
         ;// no operator
    S--;
}

那个while循环里面只有一个;,表示不进行任何操作。在这个循环里,该进程被挂起,不能访问临界资源或共享资源。

引用CSAPP中的话。

如果 s 是非零的,那么 P 将 s-1,并且立即返回。如果 s 为零,那么就挂起这个进程,直到 s 变为非零,而一个 V 操作会重启这个线程。在重启之后,P 操作将 s 减1并将控制返回给调用者。

signal()

signal()操作(也称 V 操作,荷兰语verhogen,增加的意思)。

Show you the code.

cpp 复制代码
V(semaphores S) {
    S++;
}

二元信号量(互斥锁)

二元信号量(binary semaphore)只有两个值(0或1),初始的二元信号量为1。
s == 0表示共享资源正在被占用,其他进程挂起等待。
s == 1表示共享资源空闲,可以被进程使用。

P操作在二元信号量中也叫上锁,V操作在二元信号量中也叫解锁。通常会在一段代码前上锁,然后运行完这段代码解锁。比如下面这段代码。

cpp 复制代码
void gdt_free_sel(int sel) {
    mutex_lock(&mutex);
    gdt_table[sel/sizeof(segment_desc_t)].attr = 0;
    mutex_unlock(&mutex);
}

当然,在互斥锁在实际中的使用并不是像上面那样只是增加计数,真正的应用还涉及到添加到等待队列等等。

给个互斥锁的例子。

cpp 复制代码
/**
 * 申请锁
 */
void mutex_lock (mutex_t * mutex) {
    irq_state_t state = irq_enter_protection();

    task_t * curr = task_current();
    if (mutex->locked_count == 0) {
        // 没有任务占用,占用之
        mutex->locked_count++;
        mutex->owner = curr;
    } else if (mutex->owner == curr) {
        // 已经为当前任务所有,只增加计数
        mutex->locked_count++;
    } else {
        // 有其它任务占用,则进入队列等待
        task_set_block(curr);
        list_insert_last(&mutex->wait_list, &curr->wait_node);
        task_dispatch();
    }

    irq_leave_protection(state);
}

计数信号量

计数信号量(Counting Semaphore)的信号量值的范围取决于共享资源分的实例个数。

如图,共享资源有两个实例,sem的值就是当前空闲的实例。当前进程A占用了实例一,进程B占用了实例二,所以sem=0进程C就挂起等待。

相关推荐
即将头秃的程序媛2 小时前
centos 7.9安装tomcat,并实现开机自启
linux·运维·centos
fangeqin2 小时前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
爱奥尼欧3 小时前
【Linux 系统】基础IO——Linux中对文件的理解
linux·服务器·microsoft
超喜欢下雨天4 小时前
服务器安装 ros2时遇到底层库依赖冲突的问题
linux·运维·服务器·ros2
tan77º5 小时前
【Linux网络编程】网络基础
linux·服务器·网络
笑衬人心。5 小时前
Ubuntu 22.04 + MySQL 8 无密码登录问题与 root 密码重置指南
linux·mysql·ubuntu
chanalbert7 小时前
CentOS系统新手指导手册
linux·运维·centos
星宸追风7 小时前
Ubuntu更换Home目录所在硬盘的过程
linux·运维·ubuntu
热爱生活的猴子8 小时前
Poetry 在 Linux 和 Windows 系统中的安装步骤
linux·运维·windows
myloveasuka8 小时前
[Linux]内核如何对信号进行捕捉
linux·运维·服务器