什么是线程
首先讲一下进程与线程的区别:
1、一个程序就是一个进程,一个程序中的多个任务称为线程
2、一个线程只能属于一个进程,一个进程可以有多个线程
3、线程是操作系统可识别的最小执行和调度单位
4、多线程可提高效率
线程的切换
首先看一下裸机系统实现两个变量轮流翻转
uint32_t flag1;
uint32_t flag2;
void delay(uint32_t count)
{
for(; count!=0; count--);
}
int main(void)
{
for(; ;){
flag1 = 1;
delay(100);
flag1 = 0;
delay(100);
flag2 = 1;
delay(100);
flag2 = 0;
delay(100);
}
}
flag1、flag2必须定义成全局变量才能添加到逻辑分析仪里面观察波形
flag1、flag2在逻辑分析仪中设置成bit的模式才能看到波形,不能用默认的模拟量
代码仿真图如下:

在多线程中,两个线程不断切换的效果图如下:

两个变量的波形是完全一样的,就好像CPU同时在干两件事情一样,这才是多线程的意义。虽然两者的波形图一样,但代码的实现方式完全不一样,由原来的顺序执行变成了主动切换,这是根本区别。
代码如下:
#include <rtthread.h>
#include "ARMCM3.h"
/*
*************************************************************************
* 全局变量
*************************************************************************
*/
rt_uint8_t flag1;
rt_uint8_t flag2;
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
/*
*************************************************************************
* 线程控制块 & STACK & 线程声明
*************************************************************************
*/
/* 定义线程控制块 */
struct rt_thread rt_flag1_thread;
struct rt_thread rt_flag2_thread;
ALIGN(RT_ALIGN_SIZE)
/* 定义线程栈 */
rt_uint8_t rt_flag1_thread_stack[512];
rt_uint8_t rt_flag2_thread_stack[512];
/* 线程声明 */
void flag1_thread_entry(void *p_arg);
void flag2_thread_entry(void *p_arg);
/*
*************************************************************************
* 函数声明
*************************************************************************
*/
void delay(uint32_t count);
/************************************************************************
* @brief main函数
* @param 无
* @retval 无
*
* @attention
***********************************************************************
*/
int main(void)
{
/* 硬件初始化 */
/* 将硬件相关的初始化放在这里,如果是软件仿真则没有相关初始化代码 */
/* 调度器初始化 */
rt_system_scheduler_init();
/* 初始化线程 */
rt_thread_init( &rt_flag1_thread, /* 线程控制块 */
flag1_thread_entry, /* 线程入口地址 */
RT_NULL, /* 线程形参 */
&rt_flag1_thread_stack[0], /* 线程栈起始地址 */
sizeof(rt_flag1_thread_stack) ); /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );
/* 初始化线程 */
rt_thread_init( &rt_flag2_thread, /* 线程控制块 */
flag2_thread_entry, /* 线程入口地址 */
RT_NULL, /* 线程形参 */
&rt_flag2_thread_stack[0], /* 线程栈起始地址 */
sizeof(rt_flag2_thread_stack) ); /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
rt_list_insert_before( &(rt_thread_priority_table[1]),&(rt_flag2_thread.tlist) );
/* 启动系统调度器 */
rt_system_scheduler_start();
}
/*
*************************************************************************
* 函数实现
*************************************************************************
*/
/* 软件延时 */
void delay (uint32_t count)
{
for(; count!=0; count--);
}
/* 线程1 */
void flag1_thread_entry( void *p_arg )
{
for( ;; )
{
flag1 = 1;
delay( 100 );
flag1 = 0;
delay( 100 );
/* 线程切换,这里是手动切换 */
rt_schedule();
}
}
/* 线程2 */
void flag2_thread_entry( void *p_arg )
{
for( ;; )
{
flag2 = 1;
delay( 100 );
flag2 = 0;
delay( 100 );
/* 线程切换,这里是手动切换 */
rt_schedule();
}
}
线程控制块类型声明:
struct rt_thread
{
void *sp; /* 线程栈指针 */
void *entry; /* 线程入口地址 */
void *parameter; /* 线程形参 */
void *stack_addr; /* 线程起始地址 */
rt_uint32_t stack_size; /* 线程栈大小,单位为字节 */
rt_list_t tlist; /* 线程链表节点 */
};
typedef struct rt_thread *rt_thread_t;
本文介绍了进程与线程的基本概念,强调了一个程序是进程,进程内可包含多个线程。通过示例代码展示了单线程和多线程环境下变量翻转的差异,解释了线程切换的概念。在多线程代码中,通过rtthread库实现了线程的创建和手动切换,以达到并发执行的效果。线程的使用能够提高程序的执行效率。
1378

被折叠的 条评论
为什么被折叠?



