wordpress 用户站点,济南制作网站有哪些,海口新闻头条最新消息,网站服务器租用年度价格RT-Thread 操作系统 之 线程间同步 IO设备模型 一、线程间同步1.1、信号量1.1.1、信号量结构体1.1.2、信号量的使用和管理1.1.3、信号量同步例程 1.2、互斥量1.2.1、互斥量的使用和管理 1.3、事件集1.3.1、事件集使用和管理方法1.3.2、事件集三个线程同步实例 二、IO设备模型2.… RT-Thread 操作系统 之 线程间同步 IO设备模型 一、线程间同步1.1、信号量1.1.1、信号量结构体1.1.2、信号量的使用和管理1.1.3、信号量同步例程 1.2、互斥量1.2.1、互斥量的使用和管理 1.3、事件集1.3.1、事件集使用和管理方法1.3.2、事件集三个线程同步实例 二、IO设备模型2.1、IO设备类型2.2、创建和注册IO设备2.3、访问IO设备 一、线程间同步
多个执行单元线程、中断同时执行临界区操作临界资源会导致竟态产生为了解决这种竟态问题RT-Thread OS提供了如下几种同步互斥机制 ☐ 信号量 ☐ 互斥量 ☐ 事件集
1.1、信号量
信号量是一种轻型的用于解决线程间同步问题的内核对象线程可以获取或释放它从而达到同步或互斥的目的。 每个信号量对象都有一个信号量值和一个线程等待队列信号量的值对应了信号量对象的实例数目、资源数目假如信号量值为 5则表示共有 5 个信号量实例资源可以被使用当信号量实例数目为零时再申请该信号量的线程就会被挂起在该信号量的等待队列上等待可用的信号量实例资源
1.1.1、信号量结构体
struct rt_semaphore
{struct rt_ipc_object parent; /** inherit from ipc_object 继承自ipc_object类*/rt_uint16_t value; /** value of semaphore. */rt_uint16_t reserved; /** reserved field 预留*/
};
typedef struct rt_semaphore *rt_sem_t;1.1.2、信号量的使用和管理
对一个信号量的操作包含创建 / 初始化信号量、获取信号量、释放信号量、删除 / 脱离信号量。 ☐ 创建和删除信号量 系统不再使用信号量时可通过删除信号量以释放系统资源适用于动态创建的信号量。 调用这个函数时系统将删除这个信号量。如果删除该信号量时有线程正在等待该信号量那么删除操作会先唤醒等待在该信号量上的线程等待线程的返回值是-RT_ERROR然后再释放信号量的内存资源。
/*** This function will delete a semaphore object and release the memory** param sem the semaphore object** return the error code** see rt_sem_detach*/
rt_err_t rt_sem_delete(rt_sem_t sem)☐ 初始化和脱离信号量
/*** This function will initialize a semaphore and put it under control of* resource management.** param sem the semaphore object* param name the name of semaphore* param value the initial value of semaphore* param flag the flag of semaphore** return the operation status, RT_EOK on successful*/
rt_err_t rt_sem_init(rt_sem_t sem,const char *name,rt_uint32_t value,rt_uint8_t flag)脱离信号量就是让信号量对象从内核对象管理器中脱离适用于静态初始化的信号量 使用该函数后内核先唤醒所有挂在该信号量等待队列上的线程然后将该信号量从内核对象管理器中脱离。原来挂起在信号量上的等待线程将获得 - RT_ERROR 的返回值。
/*** This function will detach a semaphore from resource management** param sem the semaphore object** return the operation status, RT_EOK on successful** see rt_sem_delete*/
rt_err_t rt_sem_detach(rt_sem_t sem)☐ 获取信号量 线程通过获取信号量来获得信号量资源实例当信号量值大于零时线程将获得信号量并且相应的信号量值会减 1如果信号量的值等于零那么说明当前信号量资源实例不可用申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待直到其他线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量线程将超时返回返回值是 - RT_ETIMEOUT。
☐ 释放信号量 释放信号量可以唤醒挂起在该信号量上的线程
/*** This function will release a semaphore, if there are threads suspended on* semaphore, it will be waked up.** param sem the semaphore object** return the error code*/
rt_err_t rt_sem_release(rt_sem_t sem)1.1.3、信号量同步例程 1.2、互斥量
互斥量体现的是排他性也是解决多线程同时操作临界区临界资源导致的竟态的一种方法。类似于特殊的信号量——二值信号量 区别信号量可由不同线程释放互斥量只能由同一线程进行释放。
1.2.1、互斥量的使用和管理
互斥量的操作包含创建 / 初始化互斥量、获取互斥量、释放互斥量、删除 / 脱离互斥量 ☐ 创建和删除 不再使用互斥量时通过删除互斥量以释放系统资源适用于动态创建的互斥量 当删除一个互斥量时所有等待此互斥量的线程都将被唤醒等待线程获得的返回值是
RT_ERROR
/*** This function will delete a mutex object and release the memory** param mutex the mutex object** return the error code** see rt_mutex_detach*/
rt_err_t rt_mutex_delete(rt_mutex_t mutex)☐ 初始化和脱离互斥量
/*** This function will initialize a mutex and put it under control of resource* management.** param mutex the mutex object* param name the name of mutex* param flag the flag of mutex** return the operation status, RT_EOK on successful*/
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)使用该函数接口后内核先唤醒所有挂在该互斥量上的线程线程的返回值是 -RT_ERROR 然后系统将该互斥量从内核对象管理器中脱离。
/*** This function will detach a mutex from resource management** param mutex the mutex object** return the operation status, RT_EOK on successful** see rt_mutex_delete*/
rt_err_t rt_mutex_detach(rt_mutex_t mutex)☐ 获取互斥量
/*** This function will take a mutex, if the mutex is unavailable, the* thread shall wait for a specified time.** param mutex the mutex object* param time the waiting time** return the error code*/
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)☐ 释放互斥量
/*** This function will release a mutex, if there are threads suspended on mutex,* it will be waked up.** param mutex the mutex object** return the error code*/
rt_err_t rt_mutex_release(rt_mutex_t mutex)1.3、事件集
事件集也是线程间同步的机制之一一个事件集可以包含多个事件利用事件集可以完成一对多多对多的线程间同步。 一个线程和多个事件的关系可设置为 其中任意一个事件唤醒 线程或几个事件都到达后唤醒线程多个事件集合可以用一个32bit无符号整型变量来表示变量的每一位代表一个事件线程通过逻辑与或逻辑或将一个或多个事件关联起来形成事件组合。 RT-Thread 定义的事件集有以下特点 ☐ 事件只与线程相关事件间相互独立 ☐ 事件仅用于同步不提供数据传输功能 ☐ 事件无排队性即多次向线程发送同一事件(如果线程还未来得及读走)其效果等同于只发送一次 1.3.1、事件集使用和管理方法
对一个事件集的操作包含创建/初始化事件集、发送事件、接收事件、删除/脱离事件集。 ☐ 创建和删除
/** event structure*/
struct rt_event
{struct rt_ipc_object parent; /** inherit from ipc_object */rt_uint32_t set; /** event set */
};
typedef struct rt_event *rt_event_t;/*** This function will create an event object from system resource** param name the name of event* param flag the flag of event RT_IPC_FLAG_FIFO RT_IPC_FLAG_PRIO** return the created event, RT_NULL on error happen*/
rt_event_t rt_event_create(const char *name, rt_uint8_t flag)/*** This function will delete an event object and release the memory** param event the event object** return the error code*/
rt_err_t rt_event_delete(rt_event_t event)☐ 初始化和脱离
/*** This function will initialize an event and put it under control of resource* management.** param event the event object* param name the name of event* param flag the flag of event** return the operation status, RT_EOK on successful*/
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)/*** This function will detach an event object from resource management** param event the event object** return the operation status, RT_EOK on successful*/
rt_err_t rt_event_detach(rt_event_t event)☐ 发送事件
/*** This function will send an event to the event object, if there are threads* suspended on event object, it will be waked up.** param event the event object* param set the event set** return the error code*/
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)☐ 接收事件
/*** This function will receive an event from event object, if the event is* unavailable, the thread shall wait for a specified time.** param event the fast event object* param set the interested event set* param option the receive option, either RT_EVENT_FLAG_AND or* RT_EVENT_FLAG_OR should be set. RT_EVENT_FLAG_CLEAR * param timeout the waiting time RT_WAITING_FOREVER RT_WAITING_NO* param recved the received event, if you dont care, RT_NULL can be set.** return the error code*/
rt_err_t rt_event_recv(rt_event_t event,rt_uint32_t set,rt_uint8_t option,rt_int32_t timeout,rt_uint32_t *recved)1.3.2、事件集三个线程同步实例
见源码 二、IO设备模型
RT-Thread 提供了一套简单的 I/O 设备模型框架如下图所示它位于硬件和应用程序之间共分成三层从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。 ☐ 应用程序通过 I/O 设备管理接口获得正确的设备驱动然后通过这个设备驱动与底层 I/O 硬件设备进行交互。 ☐ I/O 设备管理层实现了对设备驱动程序的封装 ☐ 设备驱动框架层是对同类硬件设备驱动的抽象将不同厂家的同类硬件设备驱动中相同的部分抽取出来将不同部分留出接口由驱动程序实现。 ☐ 设备驱动层是一组驱使硬件设备工作的程序实现访问硬件设备的功能。
简单设备的注册不经过设备驱动框架层直接将设备注册到I/O设备管理器中 ☐ 设备驱动根据设备模型定义创建出具备硬件访问能力的设备实例将该设备通过rt_device_register()接口注册到 I/O 设备管理器中 ☐ 应用程序通过 rt_device_find()接口查找到设备然后使用 I/O 设备管理接口来访问硬件如下图所示 对于一些复杂设备需要使用到对应的设备驱动框架层进行注册如看门狗定时器 ☐ 看门狗设备驱动程序根据看门狗设备模型定义创建出具备硬件访问能力的看门狗设备实例并将该看门狗设备通过 rt_hw_watchdog_register()接口注册到看门狗设备驱动框架中 ☐ 看门狗设备驱动框架通过 rt_device_register()接口将看门狗设备注册到 I/O 设备管理器中 ☐ 应用程序通过 I/O 设备管理接口来访问看门狗设备硬件 2.1、IO设备类型
☐ RT-Thread 支持多种 I/O 设备类型主要设备类型如下所示
RT_Device_Class_Char 0, /** character device */ RT_Device_Class_Block, /** block device */ RT_Device_Class_NetIf, /** net interface */ RT_Device_Class_MTD, /** memory device */ RT_Device_Class_CAN, /** CAN device */ RT_Device_Class_RTC, /** RTC device */ RT_Device_Class_Sound, /** Sound device */ RT_Device_Class_Graphic, /** Graphic device */ RT_Device_Class_I2CBUS, /** I2C bus device */ RT_Device_Class_USBDevice, /** USB slave device */ RT_Device_Class_USBHost, /** USB host bus */ RT_Device_Class_SPIBUS, /** SPI bus device */ RT_Device_Class_SPIDevice, /** SPI device */ RT_Device_Class_SDIO, /** SDIO bus device */ RT_Device_Class_Timer, /** Timer device */ RT_Device_Class_Miscellaneous, /** misc device */ RT_Device_Class_Sensor, /** Sensor device */ RT_Device_Class_Touch, /** Touch device */ RT_Device_Class_Unknown /** unknown device */ 2.2、创建和注册IO设备
☐ 驱动层负责创建设备实例并注册到 I/O 设备管理器中
当一个动态创建的设备不再需要使用时可以通过如下函数来销毁
☐设备被创建后需要实现它访问硬件的操作方法
☐ 设备被创建后需要注册到 I/O 设备管理器中应用程序才能够访问
/*** This function registers a device driver with specified name.** param dev the pointer of device driver structure* param name the device drivers name* param flags the capabilities flag of device 设备模式标志** return the error code, RT_EOK on initialization successfully.*/
rt_err_t rt_device_register(rt_device_t dev,const char *name,rt_uint16_t flags)#define RT_DEVICE_FLAG_RDONLY 0x001 /*只读*/
#define RT_DEVICE_FLAG_WRONLY 0x002 /*只写*/
#define RT_DEVICE_FLAG_RDWR 0x003 /*读写*/
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /*可移除*/
#define RT_DEVICE_FLAG_STANDALONE 0x008 /*独立*/
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /*挂起*/
#define RT_DEVICE_FLAG_STREAM 0x040 /*流模式*/
#define RT_DEVICE_FLAG_INT_RX 0x100 /*中断接收*/
#define RT_DEVICE_FLAG_DMA_RX 0x200 /*DMA接收*/
#define RT_DEVICE_FLAG_INT_TX 0x400 /*中断发送*/
#define RT_DEVICE_FLAG_DMA_TX 0x800 /* DMA发送*/设备注销后的设备将从设备管理器中移除也就不能再通过设备查找搜索到该设备。注销设备不会释放设备控制块占用的内存
/*** This function removes a previously registered device driver** param dev the pointer of device driver structure** return the error code, RT_EOK on successfully.*/
rt_err_t rt_device_unregister(rt_device_t dev)2.3、访问IO设备
应用程序通过 I/O 设备管理接口来访问硬件设备当设备驱动实现后应用程序就可以访问该硬件I/O 设备管理接口与 I/O 设备的操作方法的映射关系下图所示 ☐ 查找设备
/*** This function finds a device driver by specified name.** param name the device drivers name** return the registered device driver on successful, or RT_NULL on failure.*/
rt_device_t rt_device_find(const char *name)☐ 初始化设备
☐ 打开和关闭设备
注RT_DEVICE_FLAG_STREAM流模式用于向串口终端输出字符串当输出的字符是 “\n”对应 16 进制值为 0x0A时自动在前面输出一个 “\r”对应 16 进制值为 0x0D做分行。 流模式 RT_DEVICE_FLAG_STREAM 可以和接收发送模式参数使用或 “|” 运算符一起使用
☐ 控制设备
☐ 读写设备
/*** This function will read some data from a device.** param dev the pointer of device driver structure* param pos the position of reading* param buffer the data buffer to save read data* param size the size of buffer** return the actually read size on successful, otherwise negative returned.** note since 0.4.0, the unit of size/pos is a block for block device.*/
rt_size_t rt_device_read(rt_device_t dev,rt_off_t pos,void *buffer,rt_size_t size)/*** This function will write some data to a device.** param dev the pointer of device driver structure* param pos the position of written* param buffer the data buffer to be written to device* param size the size of buffer** return the actually written size on successful, otherwise negative returned.** note since 0.4.0, the unit of size/pos is a block for block device.*/
rt_size_t rt_device_write(rt_device_t dev,rt_off_t pos,const void *buffer,rt_size_t size)☐ 数据收发回调当硬件设备收到数据时可以通过如下函数回调另一个函数来设置数据接收指示通知上层应用线程有数据到达
/*** This function will set the reception indication callback function. * This callback function* is invoked when this device receives data.** param dev the pointer of device driver structure* param rx_ind the indication callback function** return RT_EOK*/
rt_err_t
rt_device_set_rx_indicate(rt_device_t dev,rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size))/*** This function will set the indication callback function when device has* written data to physical hardware.** param dev the pointer of device driver structure* param tx_done the indication callback function** return RT_EOK*/
rt_err_t
rt_device_set_tx_complete(rt_device_t dev,rt_err_t (*tx_done)(rt_device_t dev, void *buffer))