互斥:是指散布在不同进程之间的若干程序片段,当某个进程执行其中的一个程序片段时,其他进程就不能运行它们之中的任一程序片段,只能等到该进程运行完之后才可以继续运行。
同步:是指散布在不同进程之间的若干程序片段,它们的运行必须严格按照一定的先后次序来运行,这种次序依赖于要完成的任务
内核中的同步问题一般都是通过 “完成量 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_wait_common 底层实现 就不看了 没时间 觉得没意义
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子