nachos lab3-线程同步

本文详细介绍了Linux中线程同步的各种机制,包括原子操作、信号量、读写信号量和自旋锁。通过 Nachos 实验,实现了锁和条件变量,并用信号量和Lock解决了“生产者-消费者问题”。此外,还挑战了barrier和read/write lock的实现,加深了对同步互斥原理的理解。
摘要由CSDN通过智能技术生成

总体概述

本次lab的主要内容是拓展同步机制,实现同步互斥实例

本次lab的重要知识点在于对同步互斥原理的理解

任务完成情况

  1. Exercise 1 –> Y
  2. Exercise 2 –> Y
  3. Exercise 3 –> Y
  4. Exercise 4 –> Y
  5. Challenge 1 –> Y
  6. Challenge 2 –> Y

具体完成情况如下所示:

Exercise 1 调研

调研Linux中实现的同步机制

主流的Linux内核中包括了几乎所有现代操作系统具有的同步机制,这些同步机制包括:原子操作,信号量(semaphore),读写信号量(rw_semaphore),spinlock,BKL(Big Kernel Lock),rwlock、,brlock(只包含在2.4内核中),RCU(只包含在2.6内核中)和seqlock(只包含在2.6内核中)。linux操作系统中主要是现代同步机制如下:

原子操作

所谓的原子操作,就是该操作不会在执行完毕前被其他所有其他任务或事件打断,也就是说,一个原子操作就是最小的执行单位,不可能有更小的执行单位。

原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都在内核源码的includ/asm/aatomic.h中,使用汇编代码实现。

原子操作主要用于实现资源计数,非常多引用数(refcnt)就是通过原子操作实现的。原子类型的定义如下:

typedef struct 
{ 
    volatile int counter; 
} 
atomic_t; 

volatile字段告诉gcc编译器不要对该数据类型进行优化处理,对他的访问都是对内存的访问,而不是对寄存器的访问。

原子操作的API包括:

atomic_read(atomic_t * v); //该函数对原子类型的变量进行原子读操作,他返回原子类型的变量v的值。 
atomic_set(atomic_t * v, int i); //该函数设置原子类型的变量v的值为i。 
void atomic_add(int i, atomic_t *v); //该函数给原子类型的变量v增加值i。 
atomic_sub(int i, atomic_t *v); //该函数从原子类型的变量v中减去i。 
int atomic_sub_and_test(int i, atomic_t *v);//该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。 
void atomic_inc(atomic_t *v); //该函数对原子类型变量v原子地增加1。 
void atomic_dec(atomic_t *v); //该函数对原子类型的变量v原子地减1。 
int atomic_dec_and_test(atomic_t *v); //该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。 
int atomic_inc_and_test(atomic_t *v); //该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。 
int atomic_add_negative(int i, atomic_t *v); //该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。 
int atomic_add_return(int i, atomic_t *v); //该函数对原子类型的变量v原子地增加i,并且返回指向v的指针。 
int atomic_sub_return(int i, atomic_t *v); //该函数从原子类型的变量v中减去i,并且返回指向v的指针。 
int atomic_inc_return(atomic_t * v); //该函数对原子类型的变量v原子地增加1并且返回指向v的指针。 
int atomic_dec_return(atomic_t * v); //该函数对原子类型的变量v原子地减1并且返回指向v的指针。 
信号量

Linux内核实现了信号量用以同同步互斥机制。

信号量在创建时要设置一个初始值,表示同时能有几个任务能方法问该信号量保护的共享资源,初始值设为1就变成互斥锁(Mutex),即同时只能有一个任务能访问信号量保护的共享资源。

一个任务要想访问共享资源,该任务必须得到信号量,获取信号量的操作将信号量的值减1,若当前信号量为负数,则表明不能获得信号量,该任务必须挂起在信号量的等待队列等待该信号量可用,若当前信号量的值为非负数,表明能获取信号量,因而可以访问共享资源。

当任务访问完共享资源和后,必须释放信号量,释放信号量通过将信号量的值加一实现。如果信号量的值为非正数,表明有任务等待当前心好累,因此也将唤醒等待队列中的一个任务。

信号量的API有:

DECLARE_MUTEX(name) //该宏声明一个信号量name并初始化他的值为1,即声明一个互斥锁。 
DECLARE_MUTEX_LOCKED(name) //该宏声明一个互斥锁name,但把他的初始值设置为0,即锁在创建时就处在已锁状态。因此对于这种锁,一般是先释放后获得。 

void sema_init (struct semaphore *sem, int val); //该函用于数初始化设置信号量的初值,他设置信号量sem的值为val。 
void init_MUTEX (struct semaphore *sem); //该函数用于初始化一个互斥锁,即他把信号量sem的值设置为1。 
void init_MUTEX_LOCKED (struct semaphore *sem); 
//该函数也用于初始化一个互斥锁,但他把信号量sem的值设置为0,即一开始就处在已锁状态。 
void down(struct semaphore * sem); 
//该函数用于获得信号量sem,他会导致睡眠
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值