当前位置: 首页 > news >正文

虹口门户网站建设梅州做网站公司

虹口门户网站建设,梅州做网站公司,河北建设秦皇岛分公司,网页游戏排行榜2013前十名第三十九章 linux-并发解决方法二(互斥锁mutex) 文章目录第三十九章 linux-并发解决方法二(互斥锁mutex)互斥锁的定义与初始化互斥锁的DOWN操作互斥锁的UP操作用count1的信号量实现的互斥方法还不是Linux下经典的用法,…

第三十九章 linux-并发解决方法二(互斥锁mutex)


文章目录

  • 第三十九章 linux-并发解决方法二(互斥锁mutex)
  • 互斥锁的定义与初始化
  • 互斥锁的DOWN操作
  • 互斥锁的UP操作


用count=1的信号量实现的互斥方法还不是Linux下经典的用法,Linux内核针对count=1的信号量重新定义了一个新的数据结构,一般都称其为互斥锁或者互斥体。同时内核根据使用场景的不同,把用于信号量的DOWN和UP操作在struct mutex上作了优化与扩展,专门用于这种新的数据类型。

互斥锁的定义与初始化

互斥锁mutex的概念本来就来自semaphore,如果去除掉那些跟调试相关的成员,struct mutex和struct semaphore并没有本质的不同:

struct mutex {/* 1: unlocked, 0: locked, negative: locked, possible waiters */atomic_t        count;spinlock_t        wait_lock;struct list_head    wait_list;
#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)struct task_struct    *owner;
#endif
#ifdef CONFIG_MUTEX_SPIN_ON_OWNERstruct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
#ifdef CONFIG_DEBUG_MUTEXESvoid            *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_map    dep_map;
#endif
};

如同struct semaphore一样,对struct mutex的初始化不能直接通过操作其成员变量的方式进行,而应该利用内核提供的宏或者函数定义一个静态的struct mutex变量同时初始化的方法是利用内核的DEFINE_MUTEX:


#define __MUTEX_INITIALIZER(lockname) \{ .count = ATOMIC_INIT(1) \, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \__DEBUG_MUTEX_INITIALIZER(lockname) \__DEP_MAP_MUTEX_INITIALIZER(lockname) }#define DEFINE_MUTEX(mutexname) \struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)

如果在程序执行期间要初始化一个mutex变量,则可以使用mutex_init宏。去除掉那些与调试相关的操作之后,mutex_init宏可以展开成如下的函数定义形式:

# define mutex_init(mutex) \
do {                            \static struct lock_class_key __key;        \\__mutex_init((mutex), #mutex, &__key);        \
} while (0)void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{atomic_set(&lock->count, 1);spin_lock_init(&lock->wait_lock);INIT_LIST_HEAD(&lock->wait_list);mutex_clear_owner(lock);
#ifdef CONFIG_MUTEX_SPIN_ON_OWNERosq_lock_init(&lock->osq);
#endifdebug_mutex_init(lock, name, key);
}

互斥锁的DOWN操作

互斥锁mutex上的DOWN操作在Linux内核中为mutex_lock函数,定义如下:

void __sched mutex_lock(struct mutex *lock)
{might_sleep();/** The locking fastpath is the 1->0 transition from* 'unlocked' into 'locked' state.*/__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);mutex_set_owner(lock);
}

函数的设计思想体现在__mutex_fastpath_lock和__mutex_lock_slowpath两条主线上,__mutex_fastpath_lock用来快速判断当前可否获得互斥锁,如果成功获得锁,则函数直接返回,否则进入到__mutex_lock_slowpath函数中·这种设计是基于这样一个事实:想要获得某一互斥锁的代码绝大部分时候都可以成功获得。由此延伸开来在代码层面就是,mutex_lock函数进入__mutex_lock_slowpath的概率很低。

__mutex_fastpath_lock是一平台相关函数,下面以ARM处理器为例,分析其代码实现:

static inline void
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
{int __done, __res;__asm__ __volatile__ (L1            "movli.l    @%2, %0    \n""add        #-1, %0    \n""movco.l    %0, @%2    \n""movt        %1    \n": "=&z" (__res), "=&r" (__done): "r" (&(count)->counter): "t");if (unlikely(!__done || __res != 0))fail_fn(count);
}

函数在百处通过ldrex完成“__res=count->counter,L2处完成__res=__res-1,L3处试图用__res的当前值来更新count->counter.这里说“试图”是因为这个更新的操作未必会成功,主要是考虑到可能有别的进程也在操作count->counter,为不使这种可能的竞争引起对
作count->counter值更新的混乱,这里用了ARM指令中用于实现互斥访问的指令ldrex和strex(前面在spinlock的代码分析时己经提过)。ldrex和strex保证了对count->counter读取一更新一写回”操作序列的原子性。如果L3处的更新操作成功,那么_ex_flag将为0。

接下来在__res|=__ex_flag执行完之后,通过if语句判断__res是否为0,有两种情况会导致__res不为0:一是在调用这个函数前count->counter=0,表明互斥锁己经被别的进程获得,
这样L2处的__res=-1:二是在L3处的更新操作不成功,表明当前有另外一个进程也在对count->counter进行同样的操作·这两种情况都将导致__mutex_fastpath_lock不能直接返回,而是进入fail_fn也就是调用__mutex_lock_slowpath。

此处if语句中的unlikely是利用GCC编译优化扩展的一个宏,这里的意思是条件语句__res!=0为真的可能性很小,编译器借此可以调整一些编译后代码的顺序达到某种程度的优化。与之对应的是likely。
如果__mutex_fastpath_lock函数不能在第一时间获得互斥锁返回,那么将进入__mutex_lock_slowpath,正如其名字所预示的那样,代码将进入一段艰难坎坷的旅途。

在Linux源码中,__mutex_lock_slowpath函数与信号量DOWN操作中的函数非常相似,不过__mutex_lock_slowpath在把当前进程放入mutex的wait_list之前会试图多次询问mutex中的count是否为1,也就是说当前进程在进入wait_list之前会多次考察别的进程是否己经释放了这个互斥锁。这主要基于这样一个事实:拥有互斥锁的进程总是会在尽可能短的时间里释放·如果别的进程己经释放了该互斥锁·那么当前进程将可以获得该互斥锁而没有必要再去睡眠。

互斥锁的UP操作

互斥锁的操作为mutex_unlock,函数定义如下:

void __sched mutex_unlock(struct mutex *lock)
{/** The unlocking fastpath is the 0->1 transition from 'locked'* into 'unlocked' state:*/
#ifndef CONFIG_DEBUG_MUTEXES/** When debugging is enabled we must not clear the owner before time,* the slow path will always be taken, and that clears the owner field* after verifying that it was indeed current.*/mutex_clear_owner(lock);
#endif__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
}

和mutex_lock函数一样,mutex_unlock函数也有两条主线:__mutex_fastpath_unlock和__mutex_unlock_slowpath,分别用于对互斥锁的快速和慢速解锁操作。

static inline void
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{int __done, __res;__asm__ __volatile__ ("movli.l    @%2, %0    \n\t""add        #1, %0    \n\t""movco.l    %0, @%2 \n\t""movt        %1    \n\t": "=&z" (__res), "=&r" (__done): "r" (&(count)->counter): "t");if (unlikely(!__done || __res <= 0))fail_fn(count);
}

这里除了是将count->counter的值加1以外,代码和__mutex_fastpath_lock中的几乎完全一样。在最后的if语句中,导致代码count->counter不为0也有两种情况:一是在调用这个函数前count->counter不为0,表明在当前进程占有互斥锁期间有别的进程竞争该互斥锁:二是对count->counter的更新操作不成功,表明当前有另外一个进程也在对count->counter进行操作,这种情况主要是针对别的进程此时调用mutex1k函数导致的竞争,因为互斥的原因别的进程此时不可能调用mutex_lock。这种情况的处理是非常重要的,不只是关系到count->counter正确更新的问题,还涉及能否防止一个唤醒操作的丢失。

在没有别的进程竞争该互斥锁的情况下,__mutex_fastpath_unlock函数要完成的工作最简单,把count->counter的值加1然后返回·如果有别的进程在竞争该互斥锁,那么函数进入__mutex_unlock_slowpath这个函数主要用来唤醒在当前mutex的wait_list中休眠的进程,如同up函数一样。

http://www.yayakq.cn/news/68565/

相关文章:

  • 访问公司网站公司会知道吗江宁滨江网站建设
  • 快速做网站视频网站导航的交互怎么做
  • 焦作专业网站建设费用seo免费
  • php开发大型网站开发河北住房和城乡建设局网站
  • 网站移动端生成器wordpress 修改文章
  • 网站挂马怎么办周村区建设局网站
  • 游泳池建设有专门的网站吗wordpress 下载功能
  • 京推推cms网站建设哪些网站用c 做的
  • 站内推广wordpress报价计算器
  • ppt模板网站大全网站建设设计原则
  • 东莞网站建设制作公司排名有没有建网站的app
  • 建设网站前台费用广告片拍摄制作公司
  • asp网站开发环境多模室内设计网
  • 个人网站咋推广啥叫流量鲜花网站建设项目概述
  • 有人做家具网站中介吗嘉兴网站建设培训
  • 自己做的网站如何引流网络营销方式单一的后果
  • 管理学习网站沈阳seo自然优化排名
  • 什么样 个人网站 备案十大不收费看盘软件排名
  • 外贸网站违反谷歌规则内江市住房和城乡建设局网站电话
  • 伙购网官方网站wordpress好的插件推荐
  • 深圳成豪设计如何做优化网站排名
  • 河北省住房和城乡建设厅新网站淄博市住房和城乡建设厅网站
  • 厦门南希网站建设wordpress 图片 空间
  • 网站开发应该学哪门语言嘉兴市城市建设门户网站
  • 沂水网站开发网站平台建设哪家公司好
  • 加强档案网站建设WordPress服务器应用镜像
  • 买好域名和云主机后怎么做网站wordpress 英文转中文
  • 蛋糕网站制作答辩韩国网页游戏网站
  • 南昌网站建设q479185700棒电子商务seo实训总结
  • 怎么做自己的设计网站洛阳小程序开发公司