• 同步问题: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的胖子
  • 相关阅读:
    设计模式中的多态——策略模式详解
    Spring IOC容器启动流程源码解析(一)——容器概念详解及源码初探
    并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)
    HNOI2020游记
    旧年之末,新年伊始
    退役V次后做题记录
    PKUWC2020 游记
    CSP2019退役记
    CTS/APIO2019游记
    HNOI2019游记
  • 原文地址:https://www.cnblogs.com/codestack/p/13401196.html
Copyright © 2020-2023  润新知