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互斥锁和条件变量实现的信号量》

  • 相关阅读:
    linux系统下安全管理
    Linux查看所有用户用什么命令
    linux下配置ip地址四种方法(图文方法)
    如何在linux系统中设置静态ip地址
    算法与cpu
    汇编 分支之跳转结构程序设计--待处理文档
    从汇编的角度理解程序(二)—— 分支和循环控制
    指令计数器--Program counter
    类型的分类
    CPU的内部架构和工作原理
  • 原文地址:https://www.cnblogs.com/westfly/p/2384929.html
Copyright © 2011-2022 走看看