RTT Nano学习笔记 8 - 信号量

目录

1. 创建

2. 删除

3. 获取

4. 释放

5. 实例


信号量(Semaphore)的功能有一点与互斥量类似,同样是保护临界资源的一种有用方法。信号量可以但不一定实现互斥(不是说不能,一种情况是不存在共享临界区,谈不上互斥,另一种情况是允许共同进入临界区,比如读操作)。

它的运行机制可以理解为:信号量是一个正值,代表资源的可访问数目,当有任务访问时,这个数目减一,任务访问完成时,任务访问结束,释放他,让他加一,信号量为0时,其他任务则不能获取他,选择退出或者等待挂起,直到有信号量释放后,按照优先级来获取信号量,获取后就绪。

把资源想象成车位,信号量就是车位管理员,汽车需要停进有限的车位,当车位管理员发现车位足够时,则将汽车放行,如果车位数为0,则汽车都需要按照某种规则(比如按照优先级)等待空闲车位的出现。

1. 创建

同样,信号量的创建也分动态和静态两种方式,这里只考虑动态方式。

#define rtosSemCreate(                                  \
    handle                                              \
    name,                                               \
    value,                                              \
    flag                                                \
    )                                                   \
    {                                                   \
        handle = rt_sem_create(name, value, flag);      \
    }

参数:

handle - 信号量的句柄,属于返回值,创建成功则为非NULL值。

#define rtosSem_t                                       rt_sem_t

name - 信号量的名字,输入参数,字符串。

value - 信号量的默认值,一般是初始化为0

flag -  信号量的标志,支持2种方式:FIFO和PRIO。FIFO模式表示在多个线程等待信号量时,将按照先来先得的顺序获得信号量;PRIO模式表示在多个线程等待信号量时,将由优先级高的线程优先获得信号量。

2. 删除

系统不再使用信号量时,可通过删除信号量以释放系统资源。

#define rtosSemDelete(                                  \
    handle                                              \
    )                                                   \
    {                                                   \
        rt_sem_delete(handle);                          \
    }

3. 获取

线程通过调用该函数获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量, 并且相应的信号量值会减 1;如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。

#define rtosSemTake(                                    \
    handle,                                             \
    time,                                               \
    ret                                                 \
    )                                                   \
    {                                                   \
        ret = rt_sem_take(handle, time);                \
    }

 返回0表示获取成功。

4. 释放

释放一个信号量,当信号量的值等于零时,并且有线程等待这个信号量时, 释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则 将把信号量的值加一

#define rtosSemRelease(                                 \
    handle,                                             \
    ret                                                 \
    )                                                   \
    {                                                   \
        ret = rt_sem_release(handle);                   \
    }

返回0表示释放成功。

5. 实例

和互斥量的实例类似,2个进程,一个进程负责修改变量,变量值变为10的倍数则释放信号量,这里连续释放2次信号量,另外一个负责显示变量的值,只有获取到信号量才打印变量值。2个进程的优先级依然是显示的优先级更高。

static rtosSem_t sem = NULL;
static uint8_t gSemValue = 0;
static void threadSemShow(void *parameter)
{
    while(1)
    {
        uint32_t ret;
        rtosSemTake(sem, RTOS_WAIT_FOREVER, ret);
        if(ret == RTOS_EOK)
        {
            Printf("Sem Value = %d\n", gSemValue);
        }
        else
        {
            Printf("Take sem fail\n");
            return;
        }
    }
}

static void threadSemChange(void *parameter)
{
    while(1)
    {
        uint32_t ret;
        gSemValue++;
        rtosThreadSleep(100);
        if((gSemValue % 10) == 0)
        {
            Printf("Change thread release a semaphore.\n");
            rtosSemRelease(sem, ret);
            rtosSemRelease(sem, ret);
        }
    }
}

static void semTestInit(void)
{
    rtosSemCreate(sem, "sem", 0, RTOS_IPC_FLAG_FIFO);
    rtosCreateThread(
        handle1,
        "Mutex S",
        threadSemShow,
        (void *)0,
        NULL,
        256,
        RTOS_PRIORITY_MAX - 2, 
        100);
    rtosCreateThread(
        handle2,
        "Mutex C",
        threadSemChange,
        (void *)0,
        NULL,
        256,
        RTOS_PRIORITY_MAX - 1, 
        100);
    rtosStartThread(handle1);
    rtosStartThread(handle2);
}

打印结果:

Change thread release a semaphore.
Sem Value = 10
Sem Value = 10
Change thread release a semaphore.
Sem Value = 20
Sem Value = 20
Change thread release a semaphore.
Sem Value = 30
Sem Value = 30
Change thread release a semaphore.
Sem Value = 40
Sem Value = 40
Change thread release a semaphore.
Sem Value = 50
Sem Value = 50

因为修改进程会释放2次信号量,所以显示进程会连续2次拿到信号量,从而打印了2次值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值