线程
动态创建线程
/*任务回调函数*/
void rtt1_entry(void *parameter)
{
for(int i = 0;i<5;i++)
{
rt_kprintf("run1:%d\n",i);
rt_thread_delay(1000);
}
}
/*动态创建函数*/
rtt1_ptr = rt_thread_create("rtt1",rtt1_entry,NULL,1024,1,5);
if(rtt1_ptr == RT_NULL){
LOG_E("Thread creation 1 failure\n");
}
else{
LOG_D("Thread created 1 successfully\n");
rt_thread_startup(rtt1_ptr);
}
静态创建线程
/*简要:任务2回调函数*/
void rtt2_entry(void *parameter)
{
for(int i = 0;i<5;i++)
{
rt_kprintf("run2:%d\n",i);
rt_thread_delay(1000);
}
//rt_thread_delete(rtt1_ptr);
}
/*静态创建函数*/
int ret = rt_thread_init(&rtt2_ptr,"rtt2",rtt2_entry,NULL,rtt2_stack,sizeof(rtt2_stack),2,5);
if(ret == 0){
LOG_D("Thread created 2 successfully\n");
rt_thread_startup(&rtt2_ptr);
}
else {
LOG_E("Thread creation 2 failure\n");
}
钩子函数
在整个系统的运行时,系统都处于线程运行、中断触发 - 响应中断、切换到其他线程,甚至是线程间的切换过程中,或者说系统的上下文切换是系统中最普遍的事件。有时用户可能会想知道在一个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数。在系统线程切换时,这个钩子函数将被调用
/*简要:钩子函数*/
void scheduler_hook(struct rt_thread *from, struct rt_thread *to)
{
//rt_kprintf("from:%s ---> to:%s\n",from->name,to->name);
}
rt_scheduler_sethook(scheduler_hook);
定时器
RT-Thread 的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远持续执行下去。
获取系统时间
int main(void)
{
for(int i = 0;i<10;i++)
{
/*获取系统时间*/
rt_tick_t num = rt_tick_get();
rt_kprintf("tick : %u\n",num);
rt_thread_mdelay(500);
}
return 0;
}
动态创建定时器
/*
* 简要:动态定时器的回调函数
*/
void tim1_demo(void *parameter)
{
rt_kprintf("tim1 run\n");
}
rt_timer_t tim_1 = NULL;
/*动态创建定时器(周期)*/
tim_1 = rt_timer_create("tim1",tim1_demo,RT_NULL,3000,RT_TIMER_FLAG_PERIODIC);
/*启动定时器*/
if(tim_1 != RT_NULL)rt_timer_start(tim_1);
静态创建定时器
/*
* 简要:静态定时器的回调函数
*/
void tim2_demo(void *parameter)
{
rt_kprintf("tim2 run\n");
}
struct rt_timer tim_2;
/*静态创建定时器(单次)*/
rt_timer_init(&tim_2,"tim2",tim2_demo,RT_NULL,3000,RT_TIMER_FLAG_ONE_SHOT);
/*启动定时器*/
rt_timer_start(&tim_2);
信号量
以生活中的停车场为例来理解信号量的概念:
①当停车场空的时候,停车场的管理员发现有很多空车位,此时会让外面的车陆续进入停车场获得停车位;
②当停车场的车位满的时候,管理员发现已经没有空车位,将禁止外面的车进入停车场,车辆在外排队等候;
③当停车场内有车离开时,管理员发现有空的车位让出,允许外面的车进入停车场;待空车位填满后,又禁止外部车辆进入。
在此例子中,管理员就相当于信号量,管理员手中空车位的个数就是信号量的值(非负数,动态变化);停车位相当于公共资源(临界区),车辆相当于线程。车辆通过获得管理员的允许取得停车位,就类似于线程通过获得信号量访问公共资源。
静态创建与动态创建信号量
rt_sem_t rs1 = NULL;
struct rt_semaphore rs2;
int main(void)
{
/*动态创建信号量*/
rs1 = rt_sem_create("dsem",0,RT_IPC_FLAG_PRIO);
if(rs1 == RT_NULL)
{
LOG_E("dsem no\n");
return -1;
}
else
{
LOG_D("dsem yes\n");
}
/*静态创建信号量*/
rt_sem_init(&rs2,"dsem2",0,RT_IPC_FLAG_PRIO);
return RT_EOK;
}
信号量实例
/*全局变量*/
rt_sem_t rs1 = NULL;
rt_sem_t rs2 = NULL;
rt_thread_t rm1 = NULL;
rt_thread_t rm2 = NULL;
int num = 0;
/*任务1*/
void dome1_task(void *parameter)
{
while(1)
{
rt_sem_take(rs1,RT_WAITING_FOREVER);
num++;
rt_kprintf("[num: %d]dome1_task run\n",num);
if(num == 100)
{
num = 0;
}
rt_sem_release(rs2);
rt_thread_mdelay(1000);
}
}
/*任务2*/
void dome2_task(void *parameter)
{
while(1)
{
rt_sem_take(rs2,RT_WAITING_FOREVER);
if(num > 0)
{
num--;
rt_kprintf("[num: %d]dome2_task run\n",num);
}
rt_sem_release(rs1);
rt_thread_mdelay(3000);
}
}
/*主函数*/
int main(void)
{
/*创建信号量1*/
rs1 = rt_sem_create("dsem1",1,RT_IPC_FLAG_PRIO);
if(rs1 == RT_NULL)
{
LOG_E("dsem1 no\n");
return -1;
}
else
{
LOG_D("dsem1 yes\n");
}
/*创建信号量2*/
rs2 = rt_sem_create("dsem2",0,RT_IPC_FLAG_PRIO);
if(rs2 == RT_NULL)
{
LOG_E("dsem2 no\n");
return -1;
}
else
{
LOG_D("dsem2 yes\n");
}
/*创建线程1*/
rm1 = rt_thread_create("dome1",dome1_task,NULL,512,20,5);
if(rm1 == RT_NULL)
{
LOG_E("dome1 rt_thread_create NO\n");
return -1;
}
else
{
LOG_D("dome1 rt_thread_create YES\n");
rt_thread_startup(rm1);
}
/*创建线程2*/
rm2 = rt_thread_create("dome2",dome2_task,NULL,512,20,5);
if(rm2 == RT_NULL)
{
LOG_E("dome2 rt_thread_create NO\n");
return -1;
}
else
{
LOG_D("dome2 rt_thread_create YES\n");
rt_thread_startup(rm2);
}
return -1;
}
互斥量(互斥锁)
互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。
动态创建互斥量
rt_mutex_t Motor = NULL;
/*动态创建互斥锁*/
Motor = rt_mutex_create("Motor",0);
if (Motor == RT_NULL)
{
rt_kprintf("Motor rt_mutex_create NO");
return -1;
}
互斥量实例
/*全局变量*/
rt_thread_t t1 = NULL;
rt_thread_t t2 = NULL;
rt_mutex_t Motor = NULL;
int num1 = 0,num2 = 0;
/*线程1回调函数*/
void task1_main(void *parameter)
{
while(1)
{
rt_mutex_take(Motor,RT_WAITING_FOREVER);
num1++;
rt_thread_mdelay(500);
num2++;
rt_mutex_release(Motor);
}
}
/*线程2回调函数*/
void task2_main(void *parameter)
{
while(1)
{
rt_mutex_take(Motor,RT_WAITING_FOREVER);
if(num1 != num2){
rt_kprintf("num1:%d != num2:%d\n",num1,num2);
}
else {
rt_kprintf("num1:%d == num2:%d\n",num1,num2);
}
rt_thread_mdelay(500);
rt_mutex_release(Motor);
if(num1>58)
{
return;
}
}
}
int main(void)
{
/*动态创建互斥锁*/
Motor = rt_mutex_create("Motor",0);
if (Motor == RT_NULL)
{
rt_kprintf("Motor rt_mutex_create NO");
return -1;
}
/*动态创建线程1*/
t1 = rt_thread_create("task1",task1_main,RT_NULL,512,15,500);
if(t1 != RT_NULL){
LOG_D("task1 rt_thread_create YES");
rt_thread_startup(t1);
}
else {
LOG_E("task1 rt_thread_create NO");
return -1;
}
/*动态创建线程2*/
t2 = rt_thread_create("task2",task2_main,RT_NULL,512,17,500);
if(t2 != RT_NULL){
LOG_D("task2 rt_thread_create YES");
rt_thread_startup(t2);
}
else {
LOG_E("task2 rt_thread_create NO");
return -1;
}
return RT_EOK;
}
注意
- 线程任务执行完,线程不是挂起,而是删除了
- 在获得互斥量后,请尽快释放互斥量,并且在持有互斥量的过程中,不得再行更改持有互斥量线程的优先级,否则可能人为引入无界优先级反转的问题。
- 需要切记的是互斥量不能在中断服务例程中使用。