zoukankan      html  css  js  c++  java
  • 利用POSIX互斥锁和条件变量实现的信号量

    在LwIP移植的代码中有信号量相关接口,但是是通过线程来模拟的。

    以前读过,最近才感觉它是在 利用POSIX互斥锁和条件变量实现POSIX的信号量

    在《Unix网络编程 卷二进程间通信》中有用System V模拟 POSIX信号量的论述。

    LwIP是一个轻型TCP/IP协议栈,它利用操作系统模拟层实现了信号灯。

    主要有如下接口函数:

    /**新建一个信号灯,并初始化灯的值为count*/
    sys_sem_t sys_sem_new(u8_t count);
    /**将标示符为sem的信号灯释放掉。*/
    void sys_sem_free(sys_sem_t sem);
    /**将标示符为sem的信号灯的值加1*/
    void sys_sem_signal(sys_sem_t sem);
    /**锁住——等待*/
    u32_t sys_sem_wait(struct sys_sem **s);

    sys_sem结构

    struct sys_sem { 
      unsigned int c;
      pthread_cond_t cond;
      pthread_mutex_t mutex;
    };
    typedef sys_sem * sys_sem_t;

    初始化与释放直接调用了malloc/free这对好基友。

    sys_sem_t sys_sem_new(u8_t count)
    {
    sys_sem_t sem = (sys_sem_t) malloc(sizeof(sys_sem));
    if(sem)
    {
    sem->c = count;
    pthread_cond_init(&(sem->cond), NULL);
    pthread_mutex_init(&(sem->mutex), NULL);
    return sem;
    }
    return NULL;
    }

    void sys_sem_free(sys_sem_t sem)
    {
        pthread_cond_destroy(&(sem->cond));
        pthread_mutex_destroy(&(sem->mutex));
        free(sem);
    }

    重点是PV操作,分别对应sys_sem_wait 和 sys_sem_signal

    u32_t sys_sem_wait(struct sys_sem **s)
    {
    struct sys_sem *sem;
    sem = *s;
    pthread_mutex_lock(&(sem->mutex));
    //进入的数目有限
    while (sem->c <= 0) {
    pthread_cond_wait(&(sem->cond), &(sem->mutex));
    }
    sem->c--;//消费了一个
    pthread_mutex_unlock(&(sem->mutex));
    }
    void sys_sem_signal(struct sys_sem **s)
    {
    struct sys_sem *sem;
    sem = *s;
    pthread_mutex_lock(&(sem->mutex));
    sem->c++;
    //设计的只是二值选项?
    if (sem->c > 1) {
      sem->c = 1;
    }
    pthread_cond_broadcast(&(sem->cond));
    pthread_mutex_unlock(&(sem->mutex));
    }

    但LwIP的V实现,感觉有些不对,其将sem实现为二值的了,由于sys_sem主要提供给sys_mbox(参考定义如下)。

    /*移植信号量代码*/
    struct sys_mbox {
    int first, last;
    void *msgs[SYS_MBOX_SIZE];
    struct sys_sem *not_empty;
    struct sys_sem *not_full;
    struct sys_sem *mutex;
    int wait_send;
    };

    由于not_empty、not_full和mutex都是二值,所以不影响使用,但是个人结合《Linux下利用条件变量实现信号量机制 》还是以为V的实现中if是不用的。

    相应修改为

    void sys_sem_signal(struct sys_sem **s)
    {
    struct sys_sem *sem;
    sem = *s;
    pthread_mutex_lock(&(sem->mutex));
    ++(sem->c);
      if(sem->c > 0)
        pthread_cond_broadcast(&(sem->cond));
    pthread_mutex_unlock(&(sem->mutex));
    }

    u32_t sys_sem_wait(struct sys_sem **s)
    {
    struct sys_sem *sem;
    sem = *s;
    pthread_mutex_lock(&(sem->mutex));
    //进入的数目有限
    while (sem->c <= 0) {
        pthread_cond_wait(&(sem->cond), &(sem->mutex));
    }
    --(sem->c);//消费了一个
    pthread_mutex_unlock(&(sem->mutex));
    }

    以上代码可以看做是《Linux下利用条件变量实现信号量机制 》的C版本。

    参考

    Linux下利用条件变量实现信号量机制

    《利用POSIX互斥锁和条件变量实现的信号量》

  • 相关阅读:
    python selenium-webdriver 执行js (八)
    python selenium-webdriver 等待时间(七)
    python selenium-webdriver 处理JS弹出对话框(六)
    python selenium-webdriver 元素操作之键盘操作(五)
    python selenium-webdriver 元素操作之鼠标操作(四)
    Jmeter 设置全部变量(十三)
    Jmeter 执行Python代码(十二)
    Jmeter Java Request (十一)
    Jenkins进阶-定时任务(17)
    JMeter 设置间隔时间(十)
  • 原文地址:https://www.cnblogs.com/westfly/p/2384929.html
Copyright © 2011-2022 走看看