0
点赞
收藏
分享

微信扫一扫

同步问题:pthread_cond && complete分析

互斥:是指散布在不同进程之间的若干程序片段,当某个进程执行其中的一个程序片段时,其他进程就不能运行它们之中的任一程序片段,只能等到该进程运行完之后才可以继续运行。 

同步:是指散布在不同进程之间的若干程序片段,它们的运行必须严格按照一定的先后次序来运行,这种次序依赖于要完成的任务

  内核中的同步问题一般都是通过 “完成量 completion” 解决 

Completion在内核中的实现基于等待队列

 

/*
* struct completion - structure used to maintain state for a "completion"
*
* This is the opaque structure used to maintain the state for a "completion".
* Completions currently use a FIFO to queue threads that have to wait for
* the "completion" event.
*
* See also: complete(), wait_for_completion() (and friends _timeout,
* _interruptible, _interruptible_timeout, and _killable), init_completion(),
* reinit_completion(), and macros DECLARE_COMPLETION(),
* DECLARE_COMPLETION_ONSTACK().
*/
struct completion {
unsigned int done;
wait_queue_head_t wait;
};

 

初始化:

static inline void init_completion(struct completion *x)  
{
x->done = 0;
init_waitqueue_head(&x->wait);
}

两种初始化都将用于同步的done原子量置位了0,后面我们会看到,该变量在wait相关函数中减一,在complete系列函数中加一

static inline long __sched
__wait_for_common(struct completion *x,
long (*action)(long), long timeout, int state)
{
might_sleep();

spin_lock_irq(&x->wait.lock);
timeout = do_wait_for_common(x, action, timeout, state);
spin_unlock_irq(&x->wait.lock);
return timeout;
}

 

static inline long __sched
do_wait_for_common(struct completion *x, long timeout, int state)
{
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);

wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
if (signal_pending_state(state, current)) {
timeout = -ERESTARTSYS;
break;
}
__set_current_state(state);
spin_unlock_irq(&x->wait.lock);
timeout = schedule_timeout(timeout);
spin_lock_irq(&x->wait.lock);
} while (!x->done && timeout);
__remove_wait_queue(&x->wait, &wait);
if (!x->done)
return timeout;
}
// 就是相当于 拿到资源 将done 减一 复位
x->done--;
return timeout ?: 1;
}
void complete(struct completion *x)
{
unsigned long flags;

spin_lock_irqsave(&x->wait.lock, flags);
x->done++;
__wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL);
spin_unlock_irqrestore(&x->wait.lock, flags);
}

 

可以看到 对done 资源的判断 必须使用 lock 防止资源竞争!!!

  也就是如果 wait-done; 判断done 条件,如果不满足,加入等待队列,再次检测是否获取到资源, 没有获取到,释放un-lock, 调度休眠

  如果notify -done; 首先lock, 然后唤醒等待队列中等待资源的进程, 释放锁-unlock,让唤醒的进程去加锁拿去资源 

 

再来看一看 用户态的 同步问题:

  • 生产者和消费者中存在有同步关系,需要使用pthread_cond_wait和pthread_cond_signal解决
  • 生产者和消费者中存在有互斥关系,需要使用pthread_mutex_lock和pthread_mutex_unlock解决
进程A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
process---so-on
pthread_mutex_unlock(&mutex);

进程B:
process-so-on
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);

  问什么除了cond 还要有 mutex? 因为一但有多个线程同时操作这个Conditional Variable,就不可避免会出现Race Condition; mutex是为了 condition  同时只能被一个线程拥有

其实 pthread_cond_wait/signal   底层实现 和内核完成量 complete应该差不多!!

其mutex作用可以看:​​http://blog.sina.com.cn/s/blog_967817f20101bsf0.html ​​

同步问题:pthread_cond  && complete分析_等待队列

 对于 __pthread_cond_wait_common 底层实现  就不看了 没时间  觉得没意义

http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子

举报

相关推荐

0 条评论