嵌入式操作系统内核原理和开发消息队列.docx

上传人:b****4 文档编号:24106662 上传时间:2023-05-24 格式:DOCX 页数:18 大小:69.68KB
下载 相关 举报
嵌入式操作系统内核原理和开发消息队列.docx_第1页
第1页 / 共18页
嵌入式操作系统内核原理和开发消息队列.docx_第2页
第2页 / 共18页
嵌入式操作系统内核原理和开发消息队列.docx_第3页
第3页 / 共18页
嵌入式操作系统内核原理和开发消息队列.docx_第4页
第4页 / 共18页
嵌入式操作系统内核原理和开发消息队列.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

嵌入式操作系统内核原理和开发消息队列.docx

《嵌入式操作系统内核原理和开发消息队列.docx》由会员分享,可在线阅读,更多相关《嵌入式操作系统内核原理和开发消息队列.docx(18页珍藏版)》请在冰豆网上搜索。

嵌入式操作系统内核原理和开发消息队列.docx

嵌入式操作系统内核原理和开发消息队列

嵌入式操作系统内核原理和开发(消息队列)

嵌入式操作系统内核原理和开发(消息队列)

消息队列是线程交互的一种方法,任务可以通过消息队列来实现数据的沟通和交换。

在嵌入式系统上,这可以说这是用的最多的一种方法。

通过消息队列,无论是发送者,还是接受者都可以循环地处理各种消息。

而我们知道,存储消息最好的方式就是循环队列,如果消息已满,那么发送者可以把自己pend到等待队列上;而如果此时没有消息,那么接受者也可以把自己pend到等待队列上。

当然实现消息队列的方法很多,甚至用户可以自己利用互斥量和信号量来实现,而嵌入式系统常常会默认提供这样的功能函数,我想主要的目的还是为了方便用户,让他们可以更多地从业务的角度来看问题,而不是把重点关注在这些底层的细节上面。

首先,我们还是看看rawos上面关于消息队列的数据结构是怎么定义的,

[cpp]viewplaincopy

1typedefstructRAW_MSG_Q{

2

3RAW_VOID**queue_start;/*Pointertostartofqueuedata*/

4RAW_VOID**queue_end;/*Pointertoendofqueuedata*/

5RAW_VOID**write;/*PointertowherenextmessagewillbeinsertedintheQ*/

6RAW_VOID**read;/*PointertowherenextmessagewillbeextractedfromtheQ*/

7RAW_U32size;/*Sizeofqueue(maximumnumberofentries)*/

8RAW_U32current_numbers;/*Currentnumberofentriesinthequeue*/

9RAW_U16blocked_send_task_numbers;/*numberofblockedsendtasknumbers*/

10RAW_U16blocked_receive_task_numbers;/*numberofblockedsendtasknumbers*/

11

12}RAW_MSG_Q;

13

14typedefstructRAW_QUEUE

15{

16RAW_COMMON_BLOCK_OBJECTcommon_block_obj;

17RAW_MSG_Qmsg_q;

18

19}RAW_QUEUE;

上面的代码中有两段数据结构,第一段主要表示循环队列的内容,其中包括了队列首地址、队列末尾地址、当前队列读取地址、当前队列插入地址、队列大小、消息个数、阻塞的发送线程数据、阻塞的接受线程数目。

而第二段数据结构就比较简单,它把通用等待结构和循环队列合在了一起,共同构成了消息队列的数据结构。

根据我们以前的经验,互斥同步数据结构的操作都会分成几个部分,当然消息队列也不例外,也会分成初始化、发送消息、接受消息、清除消息、删除消息队列等几种操作函数。

当然,消息队列还是增加了一个新的选项,那就是插入消息的时候可以插入在队列的前方,还是插入在队列的尾部,这在某种程度上决定了消息的优先级。

说到这,我们还是看看消息队列是怎么初始化的,

[cpp]viewplaincopy

20RAW_U16raw_queue_create(RAW_QUEUE*p_q,RAW_U8*p_name,RAW_VOID**msg_start,RAW_U32number)

21{

22

23#if(RAW_QUEUE_FUNCTION_CHECK>0)

24

25if(p_q==0){

26

27returnRAW_NULL_OBJECT;

28}

29

30if(msg_start==0){

31

32returnRAW_NULL_POINTER;

33}

34

35if(number==0){

36

37returnRAW_ZERO_NUMBER;

38}

39

40#endif

41

42list_init(&p_q->common_block_obj.block_list);

43

44p_q->common_block_obj.name=p_name;

45p_q->common_block_obj.block_way=0;

46p_q->msg_q.queue_start=msg_start;/*Initializethequeue*/

47p_q->msg_q.queue_end=&msg_start[number];

48p_q->msg_q.write=msg_start;

49p_q->msg_q.read=msg_start;

50p_q->msg_q.size=number;

51p_q->msg_q.current_numbers=0;

52p_q->msg_q.blocked_send_task_numbers=0;

53p_q->msg_q.blocked_receive_task_numbers=0;

54returnRAW_SUCCESS;

55}

56

虽然相比较之前的互斥函数,消息队列的初始化内容好像多一些。

但是大家如果对循环队列的知识比较了解的话,其实也不是很复杂的。

我们看到,函数除了对通用阻塞结构进行初始化之外,就是对这些循环队列进行初始化。

接着,我们就可以看看消息发送函数是怎么样的,

[cpp]viewplaincopy

57staticRAW_U16internal_msg_post(RAW_QUEUE*p_q,RAW_VOID*p_void,RAW_U8opt_send_method,RAW_U8opt_wake_all,RAW_U32wait_option)

58{

59RAW_U16error_status;

60LIST*block_list_head;

61RAW_U8block_way;

62

63RAW_SR_ALLOC();

64

65#if(RAW_QUEUE_FUNCTION_CHECK>0)

66

67if(raw_int_nesting){

68

69if(wait_option!

=RAW_NO_WAIT){

70

71returnRAW_NOT_CALLED_BY_ISR;

72}

73}

74

75if(p_q==0){

76

77returnRAW_NULL_OBJECT;

78}

79

80if(p_void==0){

81

82returnRAW_NULL_POINTER;

83}

84

85#endif

86

87block_list_head=&p_q->common_block_obj.block_list;

88

89RAW_CRITICAL_ENTER();

90

91/*queueisfullcondition,thereshouldbenoreceivedtaskblockedonqueueobject!

*/

92if(p_q->msg_q.current_numbers>=p_q->msg_q.size){

93

94if(wait_option==RAW_NO_WAIT){

95RAW_CRITICAL_EXIT();

96returnRAW_MSG_MAX;

97}

98

99else{

100

101/*systemislockedsotaskcannotbeblockedjustreturnimmediately*/

102if(raw_sched_lock){

103RAW_CRITICAL_EXIT();

104returnRAW_SCHED_DISABLE;

105}

106/*queueisfullandSEND_TO_FRONTmethodisnotallowd*/

107if(opt_send_method==SEND_TO_FRONT){

108

109RAW_CRITICAL_EXIT();

110returnRAW_QUEUE_FULL_OPT_ERROR;

111}

112

113p_q->msg_q.blocked_send_task_numbers++;

114raw_task_active->msg=p_void;

115block_way=p_q->common_block_obj.block_way;

116p_q->common_block_obj.block_way=RAW_BLOCKED_WAY_FIFO;

117/*thereshouldbenoblockedreceivedtaskbeacusemsgexits*/

118raw_pend_object(&p_q->common_block_obj,raw_task_active,wait_option);

119p_q->common_block_obj.block_way=block_way;

120

121RAW_CRITICAL_EXIT();

122

123raw_sched();

124

125error_status=block_state_post_process(raw_task_active,0);

126

127returnerror_status;

128

129}

130

131}

132

133/*Queueisnotfullhere,thereshouldbenoblockedsendtask*/

134/*Ifthereisnoblockedreceivetask*/

135if(is_list_empty(block_list_head)){

136

137p_q->msg_q.current_numbers++;/*Updatethenbrofentriesinthequeue*/

138

139if(opt_send_method==SEND_TO_END){

140

141*p_q->msg_q.write++=p_void;

142

143if(p_q->msg_q.write==p_q->msg_q.queue_end){

144

145p_q->msg_q.write=p_q->msg_q.queue_start;

146

147}

148

149}

150

151else{

152

153if(p_q->msg_q.read==p_q->msg_q.queue_start){

154p_q->msg_q.read=p_q->msg_q.queue_end;

155}

156

157p_q->msg_q.read--;

158*p_q->msg_q.read=p_void;/*Insertmessageintoqueue*/

159

160}

161

162RAW_CRITICAL_EXIT();

163

164returnRAW_SUCCESS;

165}

166

167/*wakeallthetaskblockedonthisqueue*/

168if(opt_wake_all){

169

170while(!

is_list_empty(block_list_head)){

171wake_send_msg(list_entry(block_list_head->next,RAW_TASK_OBJ,task_list),p_void);

172}

173

174p_q->msg_q.blocked_receive_task_numbers=0;

175}

176

177/*wakehignhestprioritytaskblockedonthisqueueandsendmsgtoit*/

178else{

179

180wake_send_msg(list_entry(block_list_head->next,RAW_TASK_OBJ,task_list),p_void);

181p_q->msg_q.blocked_receive_task_numbers--;

182}

183

184RAW_CRITICAL_EXIT();

185

186raw_sched();

187returnRAW_SUCCESS;

188}

189

这里消息发送函数稍显冗长,这主要是因为

程,那么唤醒所有的线程,等待线程总数置为0;

b)如果只是唤起某一个线程,那么唤醒第一个等待线程,等待线程总数自减;

(5)调用系统调度函数,防止有高优先级的线程加入调度队列;

(6)线程再次得到运行的机会,函数返回。

看到上面的代码,我们发现只要梳理好了代码的逻辑,其实消息发送函数也是比较好理解的。

当然,有消息的发送,就必然会存在消息的接受了。

此时肯定也会出现没有消息、有消息两种情况了。

[cpp]viewplaincopy

190RAW_U16raw_queue_receive(RAW_QUEUE*p_q,RAW_U32wait_option,RAW_VOID**msg)

191{

192

193RAW_VOID*pmsg;

194RAW_U16result;

195LIST*block_list_head;

196RAW_TASK_OBJ*blocked_send_task;

197

198RAW_SR_ALLOC();

199

200#if(RAW_QUEUE_FUNCTION_CHECK>0)

201

202if(raw_int_nesting){

203

204returnRAW_NOT_CALLED_BY_ISR;

205

206}

207

208if(p_q==0){

209

210returnRAW_NULL_OBJECT;

211}

212

213if(msg==0){

214

215returnRAW_NULL_POINTER;

216}

217

218#endif

219

220block_list_head=&p_q->common_block_obj.block_list;

221

222RAW_CRITICAL_ENTER();

223

224

225/*ifqueuehasmsgs,justreceiveit*/

226if(p_q->msg_q.current_numbers){

227

228pmsg=*p_q->msg_q.read++;

229

230if(p_q->msg_q.read==p_q->msg_q.queue_end){

231p_q->msg_q.read=p_q->msg_q.queue_start;

232}

233

234*msg=pmsg;

235

236/*ifthereareblocked_send_tasks,justreloadthetaskmsgtoend*/

237if(p_q->msg_q.blocked_send_task_numbers){

238

239blocked_send_task=list_entry(block_list_head->next,RAW_TASK_OBJ,task_list);

240

241p_q->msg_q.blocked_send_task_numbers--;

242

243*p_q->msg_q.write++=blocked_send_task->msg;

244

245if(p_q->msg_q.write==p_q->msg_q.queue_end){

246

247p_q->msg_q.write=p_q->msg_q.queue_start;

248

249}

250

251raw_wake_object(blocked_send_task);

252RAW_CRITICAL_EXIT();

253

254raw_sched();

255returnRAW_SUCCESS;

256

257}

258

259p_q->msg_q.current_numbers--;

260

261RAW_CRITICAL_EXIT();

262

263returnRAW_SUCCESS;

264}

265

266

267

268if(wait_option==RAW_NO_WAIT){/*Callerwantstoblockifnotavailable?

*/

269*msg=(RAW_VOID*)0;

270RAW_CRITICAL_EXIT();

271returnRAW_NO_PEND_WAIT;

272}

273

274if(raw_sched_lock){

275RAW_CRITICAL_EXIT();

276returnRAW_SCHED_DISABLE;

277}

278

279raw_pend_object(&p_q->common_block_obj,raw_task_active,wait_option);

280p_q->msg_q.blocked_receive_task_numbers++;

281

282RAW_CRITICAL_EXIT();

283

284raw_sched();

285

286RAW_CRITICAL_ENTER();

287

288*msg=(RAW_VOID*)0;

289result=block_state_post_process(raw_task_active,msg);

290

291RAW_CRITICAL_EXIT();

292

293returnresult;

294

295}

296

和发送消息函数相比,接受消息的操作还是要少一些,不要紧,大家一起来看一下实现逻辑,

(1)判断参数合法性;

(2)如果当前存在消息,

a)读取循环队列中的消息;

b)判断当前是否存在等待线程,因为之前有可能存在没有压入队列的消息,那么此时压入消息,唤醒该线程即可,调用系统调度函数返回;

c)没有等待线程,消息总数自减,函数返回。

(3)当前没有消息,

a)线程不愿等待,函数返回;

b)系统禁止调度,函数返回;

c)线程将自己pend到等待队列中;

d)调用系统调度函数,切换到其他线程继续运行;

e)线程再次获得运行的机会,从thread结构中获取返回结果,函数返回。

和发送消息、接受消息比较起来,清除消息和删除消息的处理就比较简单了。

为了说明问题,我们不妨放在一起讨论一下,

[cpp]viewplaincopy

297RAW_U16raw_queue_flush(RAW_QUEUE*p_q)

298{

299LIST*block_list_head;

300

301RAW_SR_ALLOC();

302

303RAW_TASK_OBJ*block_task;

304

305#if(RAW_QUEUE_FUNCTION_CHECK>0)

306

307if(p_q==0){

308

309returnRAW_NULL_OBJECT;

310}

311

312#endif

313

314block_list_head=&p_q->common_block_obj.block_list;

315

316RAW_CRITICAL_ENTER();

317

318/*ifqueueisfullandtaskisblockedonthisqueue,thenwakeallthetask*/

319if(p_q->msg_q.current_numbers>=p_q->msg_q.size){

320while(!

is_list_empty(block_list_head)){

321block_task=list_entry(block_list_head->next,RAW_TASK_OBJ,task_list);

322raw_wake_object(block_task);

323block_task->block_status=RAW_B_ABORT;

324

325}

326

327p_q->msg_q.blocked_send_task_numbers=0;

328}

329

330RAW_CRITICAL_EXIT();

331

332raw_sched();

333

334returnRAW_SUCCESS;

335}

336#endif

337

338

339#if(CONFIG_RAW_QUEUE_DELETE>0)

340RAW_U16raw_queue_delete(RAW_QUEUE*p_q)

341{

342LIST*bloc

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 商业计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1