嵌入式实时操作系统的设计与开发New(四)

aCoral线程

aCoral调度的基本单位是线程(任务)
真正的RTOS,基本上没有做到进程,只是停留在多线程,因为多进程要解决很多问题,且需要硬件支持,这样就使系统复杂得多,从而影响系统实时性。

线程和进程的区别:
线程之间是共享地址的,当前线程的地址对于其它线程地址是可见的,如果修改了地址的内容,其他线程是可以知道,并且能访问的。

int i = 1;
void test()
{
	sleep(10s);
	printf("%d",i);
}
int main()
{
	create_task(test,....);
	i++;
}

如果create_task对应的是创建线程的接口,则test输出2;如果对应的是创建进程的接口,则test输出1。
因为如果是多进程,main函数进程和test所在进程是不能相互访问彼此之间的变量的。
明明地址一样,为什么访问的值不一样?

  1. 地址保护。每个进程有自己的地址空间,如果当前进程跨界访问到了其它进程的区域,则会出错,就访问不了这个地址,这种地址保护需要硬件有存储器保护单元MPU的支持。
  2. 虚拟地址。各个进程仅管都是访问同一地址,但由于虚拟地址的机制,它们对应的物理地址是不一样的,所以读取的值就会不一样。这种虚拟地址需要硬件有内存管理单元MMU的支持。

因此,进程之间相互独立、隔离,一个进程的崩溃或错误操作不会影响其它进程。
但是无法访问全局变量了,因为全局变量都变成了进程范围内的全局变量了,这样进程之间如何共享,如何通信就变得困难了。
因此,RTOS很少支持线程,因为硬件不支持;进程间通信、互斥的开销太大,导致系统复杂,对注重实时性的应用来说,代价太大。

描述线程

线程就是一段代码的执行体。

void test3(uint32_t timer)
{
	acoral_delay_self(timer);
}

void test_delay_init()
{
	for(i=0; i<34; i++)
	{
		acoral_print("%d\n",i);
		id = acoral_create_thread(test3,256,500+i*10,"delay",i+1,-1);
	}
}

线程保护了“执行代码+执行环境”,执行环境就是“堆栈+寄存器”。

typedef union{
	int id;
	int next_id;
}acoral_res_t;

struct acoral_list{
	struct acoral_list *next,*prev;
};
typedef strcut acoral_list acoral_list_t;
typedef struct{//SPG加注释
  	acoral_res_t res;	//资源id,线程创建后作为线程id
	unsigned char state;
	unsigned char prio;
	unsigned char policy;
	acoral_list_t ready;	//挂载到全剧就绪队列
	acoral_list_t timeout;	//挂载到超时阻塞队列
	acoral_list_t waiting;	//挂载到延时队列
	acoral_list_t global_list;	//挂载到全局线程列表
	acoral_evt_t* evt;		///<用于指向线程占用的事件(信号量、互斥量等),方便线程退出时释放事件
	unsigned int *stack;	///<指示线程的堆栈,线程被抢占切换时会保存cpu堆栈寄存器sp的值
	unsigned int *stack_buttom;	///<栈底
	unsigned int stack_size;	///<堆栈大小
	int delay;				///<指定线程延时时间,单位是Ticks,调用acoral_delay_self时会把时间参数转换成Ticks后赋值给delay
	char *name;				///<线程名字
	int console_id;			///<线程控制台ID号
	void*	private_data;	///<长久备用数据指针
	void*	data;			///<临时备用数据指针
}acoral_thread_t;

ACORAL_THREAD_STATE_EXIT为退出状态,意味着某个线程退出了,不会再参与调度,但此时程序的资源,如线程控制块TCB、堆栈等资源还未释放。
ACORAL_THREAD_STATE_RELEASE意味着可以释放这些资源。

typedef strcut
{
	acoral_res_t res; //event也是一种资源
	unsigned char type;
	int count;
	acoral_list_t wait_queue; //等待使用这个event的线程队列
	void* data; //当event是mutex或semaphore时,指向占用线程,当是消息队列时,存放传递的消息
}acoral_evt_t;

线程退出时,必须释放该线程占用的事件。

stack表示线程的堆栈。在当前线程被其它线程抢占,并在切换到其它线程的时候,当前线程的stack会赋值为CPU堆栈寄存器sp的值。
每个线程都有自己的堆栈,存放自己的运行环境。

stack_buttom:栈底,当堆栈指针超过了栈底,这时sp指向的内存地址已经不是本线程自己的内存空间,这样可能会破坏其它线程的数据结构,严重时会导致系统崩溃。

delay:当用户需要延迟某个线程的执行时,用它来指定延迟时间,单位是Ticks,当用户调用acoral_delay_self时传入的时间参数转化为Ticks再赋值给delay成员。
private_data:长久备用数据指针,用于数据策略私有数据指针。
data:临时备用数据指针。

你可能感兴趣的:(嵌入式实时操作系统的设计与开发,RTOS)