操作系统实践之路——四、同步(2.Linux下的数据同步方法)

前言

​ 上节课,讨论了解决数据同步问题的思路与方法。而Linux作为一个成熟的操作系统的内核,当然也是有很多的数据同步机制,它也有原子变量、开启和关闭中断、自旋锁和信号量。那么今天,就来看看这些机制在Linux中的实现。

一、Linux的原子变量

​ Linux是支持多进程的系统,如果有多个进程同时打开或者关闭文件,就有可能导致(未做任何保护的)计数器计算失误,为了避免这个问题,Linux提供了一个原子类型变量 atomic_t。该变量的定义如下:

typedef struct {
   
    int counter;
} atomic_t;//常用的32位的原子变量类型
#ifdef CONFIG_64BIT
typedef struct {
   
    s64 counter;
} atomic64_t;//64位的原子变量类型
#endif

​ 上述代码自然不能用普通的代码去读写加减,而是要用 Linux 专门提供的接口函数去操作,否则就不能保证原子性了,代码如下:

//原子读取变量中的值
static __always_inline int arch_atomic_read(const atomic_t *v)
{
   
    return __READ_ONCE((v)->counter);
}
//原子写入一个具体的值
static __always_inline void arch_atomic_set(atomic_t *v, int i)
{
   
    __WRITE_ONCE(v->counter, i);
}
//原子加上一个具体的值
static __always_inline void arch_atomic_add(int i, atomic_t *v)
{
   
    asm volatile(LOCK_PREFIX "addl %1,%0"
             : "+m" (v->counter)
             : "ir" (i) : "memory");
}
//原子减去一个具体的值
static __always_inline void arch_atomic_sub(int i, atomic_t *v)
{
   
    asm volatile(LOCK_PREFIX "subl %1,%0"
             : "+m" (v->counter)
             : "ir" (i) : "memory");
}
//原子加1
static __always_inline void arch_atomic_inc(atomic_t *v)
{
   
    asm volatile(LOCK_PREFIX "incl %0"
             : "+m" (v->counter) :: "memory");
}
//原子减1
static __always_inline void arch_atomic_dec(atomic_t *v)
{
   
    asm volatile(LOCK_PREFIX "decl %0"
             : "+m" (v->counter) :: "memory");
}

​ Linux 原子类型变量的操作函数有很多,这里我只是介绍了最基础的几个函数,其它的原子类型变量操作也依赖于上述几个基础的函数。

​ 会发现,Linux 的实现也同样采用了 x86 CPU 的原子指令,LOCK_PREFIX 是一个宏,根据需要展开成“lock;”或者空串。单核心 CPU 是不需要 lock 前缀的,只要在多核心 CPU 下才需要加上 lock 前缀。

二、Linux的控制中断

​ linux中断代码,与前文讲的原理基本相同,Linux 中通过定义的方式对一些底层函数进行了一些包装。Linux控制CPU响应中断的函数如下:

//实际保存eflags寄存器
extern __always_inline unsigned long native_save_fl(void){
   
    unsigned long flags;
    asm volatile("# __raw_save_flags\n\t"
                 "pushf ; pop %0":"=rm"(flags)::"memory");
    return flags;
}
//实际恢复eflags寄存器
extern inline void native_restore_fl(unsigned long flags){
   
    asm volatile("push %0 ; popf"::"g"(flags):"memory","cc");
}
//实际关中断
static __always_inline void native_irq_disable(void){
   
    asm volatile("cli":::"memory");
}
//实际开启中断
static __always_inline void native_irq_enable(void){
   
    asm volatile("sti":::"memory");
}
//arch层关中断
static __always_inline void arch_local_irq_disable(void){
   
    native_irq_disable();
}
//arch层开启中断
static __always_inline void arch_local_irq_enable(void){
    
    native_irq_enable();
}
//arch层保存eflags寄存器
static __always_inline unsigned long           arch_local_save_flags(void){
   
    return native_save_fl();
}
//arch层恢复eflags寄存器
static  __always_inline void arch_local_irq_restore
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值