同步问题: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_wait_common 底层实现  就不看了 没时间  觉得没意义

http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
原文地址:https://www.cnblogs.com/codestack/p/13401196.html