线程的切换

本文介绍了进程与线程的基本概念,强调了一个程序是进程,进程内可包含多个线程。通过示例代码展示了单线程和多线程环境下变量翻转的差异,解释了线程切换的概念。在多线程代码中,通过rtthread库实现了线程的创建和手动切换,以达到并发执行的效果。线程的使用能够提高程序的执行效率。

什么是线程

首先讲一下进程与线程的区别:

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;

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值