12.RT-Thread生产者消费者问题-IPC对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_38245860/article/details/80895016

生产者消费者问题:线程同步问题

生产者--->产品(带缓冲区)--->消费者

生产者生产产品放到缓冲区,消费者从缓冲区拿产品消费,当缓冲区中产品满了之后,生产者会挂起,只有当消费者消费了一个产品之后,缓冲区产生一个空位,生产者才会继续生产。

对于缓冲区的访问是互斥的,缓冲区满了生产者要挂起,缓冲区空了消费者要挂起。

使用RT-Thread任务同步的相关机制给出一个生产者-消费者模型

/*
 * 程序清单:信号量例程
 *
 * 该例程创建了一个动态信号量和静态信号量,分别展示了获取信号量超时和获取成功的情况
 *
 */
#include <rtthread.h>

/* 信号量控制块 */
static struct rt_semaphore static_sem;
/* 指向信号量的指针 */
static rt_sem_t dynamic_sem = RT_NULL;

ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
static void rt_thread_entry1(void *parameter)
{
    rt_err_t result;
    rt_tick_t tick;

    /* 1. staic semaphore demo */

    /* 获得当前的OS Tick */
    tick = rt_tick_get();

    /* 试图持有信号量,最大等待10个OS Tick后返回 */
    result = rt_sem_take(&static_sem, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_detach(&static_sem);
            return;
        }
        rt_kprintf("take semaphore timeout\n");
    }
    else
    {
        /* 因为没有其他地方释放信号量,所以不应该成功持有信号量,否则测试失败 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);
        return;
    }

    /* 释放一次信号量 */
    rt_sem_release(&static_sem);

    /* 永久等待方式持有信号量 */
    result = rt_sem_take(&static_sem, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("take a static semaphore, failed.\n");
        rt_sem_detach(&static_sem);
        return;
    }

    rt_kprintf("take a staic semaphore, done.\n");

    /* 脱离信号量对象 */
    rt_sem_detach(&static_sem);

    /* 2. dynamic semaphore test */

    tick = rt_tick_get();

    /* 试图持有信号量,最大等待10个OS Tick后返回 */
    result = rt_sem_take(dynamic_sem, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_sem_delete(dynamic_sem);
            return;
        }
        rt_kprintf("take semaphore timeout\n");
    }
    else
    {
        /* 因为没有其他地方释放信号量,所以不应该成功持有信号量,否则测试失败 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return;
    }

    /* 释放一次信号量 */
    rt_sem_release(dynamic_sem);

    /* 永久等待方式持有信号量 */
    result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("take a dynamic semaphore, failed.\n");
        rt_sem_delete(dynamic_sem);
        return;
    }

    rt_kprintf("take a dynamic semaphore, done.\n");
    /* 删除信号量对象 */
    rt_sem_delete(dynamic_sem);
}

/* 信号量示例的初始化 */
int semaphore_sample_init()
{
    rt_err_t result;

    /* 初始化静态信号量,初始值是0 */
    result = rt_sem_init(&static_sem, "ssem", 0, RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init dynamic semaphore failed.\n");
        return -1;
    }

    /* 创建一个动态信号量,初始值是0 */
    dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
    if (dynamic_sem == RT_NULL)
    {
        rt_kprintf("create dynamic semaphore failed.\n");
        return -1;
    }

    rt_thread_init(&thread1,
                   "thread1",
                   rt_thread_entry1,
                   RT_NULL,
                   &thread1_stack[0],
                   sizeof(thread1_stack), 11, 5);
    rt_thread_startup(&thread1);

    return 0;
}
/* 如果设置了RT_SAMPLES_AUTORUN,则加入到初始化线程中自动运行 */
#if defined (RT_SAMPLES_AUTORUN) && defined(RT_USING_COMPONENTS_INIT)
    INIT_APP_EXPORT(semaphore_sample_init);
#endif
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(semaphore_sample_init, semaphore sample);

思考:互斥量如何实现?


猜你喜欢

转载自blog.csdn.net/sinat_38245860/article/details/80895016