semaphore的实现机制详解.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
semaphore的实现机制详解

semaphore的实现机制详解 semaphore是内核中比较重要和常用的同步方式之一,他主要的特点是实现了Sleep机制下的同步。也就是当获取一个semaphore但是又不能立刻获取的时候,他使当前的执行进程进入到Sleep状态中等待,当semaphore可以获取的时候,从新开始运行,而不像splin lock在获取锁的时候是BusyWait。 首先看其定义: struct semaphore { atomic_t count; // 原子变量,是后续的实际代码中,我们能看到其即为我们在初始化时所设置的信号量。 int sleepers; // 有几个等待者。 wait_queue_head_t wait; // 等待队列 }; 初始化函数: static inline void sema_init (struct semaphore *sem, int val) { atomic_set(sem-count, val); // 原子操作,把信号量的值设为原子操作的值。 sem-sleepers = 0; // 设为等待者为0。 init_waitqueue_head(sem-wait); // 初始化等待队列。 } 好看完了初始化函数,我们来看一下一个特例PV操作: static inline void init_MUTEX (struct semaphore *sem) { sema_init(sem, 1); } static inline void init_MUTEX_LOCKED (struct semaphore *sem) { sema_init(sem, 0); } 从中我们可以看到,其实我们所说的PV操作就是调用sema_init来把其中的原子变量分别置0或者1。 下面我们来看下具体的操作函数: static inline void down(struct semaphore * sem) { might_sleep(); __asm__ __volatile__( # atomic down operation\n\t LOCK_PREFIX decl %0\n\t /* --sem-count */ jns 2f\n \tlea %0,%%eax\n\t call __down_failed\n 2: :+m (sem-count) : :memory,ax); } 关于might_sleep(): #define might_sleep() \ do { __might_sleep(__FILE__, __LINE__); might_resched(); } while (0) 从中可以看到其根本是调用might_resched(): #define might_resched() cond_resched() 其调用了cond_resched(): int __sched cond_resched(void) { if (need_resched() !(preempt_count() PREEMPT_ACTIVE) system_state == SYSTEM_RUNNING) { __cond_resched(); return 1; } return 0; } 其中: static inline int need_resched(void) { return unlikely(test_thread_flag(TIF_NEED_RESCHED)); // TIF_NEED_RESCHED 这个值在arm是2,在i386中是3。 } 其是判断进程的状态是否是需要调度。 其具体实现是: #define test_thread_flag(flag) \ test_ti_thread_flag(current_thread_info(), flag) 得到当前进程的状态,然后和flag做位操作,判断是否可以做调度。 看下关于抢占机制的判断: #define preempt_count() (current_thread_info()-preempt_count) 调用preempt_count()得到当前进程关于抢占的状态,preempt_count PREEMPT_ACTIVE 为TRUE,取反为当前不可以抢占,就不能调度,否则为可调度。 看些系统状态:system_state 为运行状态。 综合上面的几个条件,我们看出当前进程可以被调度或者说抢占,于是当前进程被调度放弃CPU资源。 might_sleep宏就是检查是否需要重新调度。 下面我们进入

文档评论(0)

bh10099 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档