你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

自制简单OS(仅任务调度) 精华  

[复制链接]
qianfan 发布时间:2015-6-28 15:36
阅读主题, 点击返回1楼
收藏 8 评论93 发布时间:2015-6-28 15:36
93个回答
小小超 回答时间:2015-6-29 13:46:46
多谢分享,学习一下
Mandelbrot_Set 回答时间:2015-6-29 14:18:46
QianFan 发表于 2015-6-29 10:46
- c3 x& `8 v$ s5 W如果是这样呢?

# ]% C; k# x3 c$ P. g) o我觉得还有一个可能怀疑的就是malloc与free本身., H9 k5 X0 M8 C& f( G5 l# t
设计上本身并不排除malloc,free执行一半调度到另一任务的malloc,free.0 q" t3 x+ c4 U
examples:  f. j5 X6 ]6 B0 l  @+ n: I
A delete B  free了一半 调度到 B delete B
' n4 I  E8 y* _% P, |) k7 mA delete B  free了一半 调度到 C create D
  l$ U. m! T# }2 ^; T. ]。。。(这概率!)这总是让人不安,谁没用过malloc(应该包括new delete吧?)。. ?: ^$ A- Q+ y0 i: t
(malloc不局限于嵌入式平台)于是有了下文先。
9 S6 v' L: ]: ^1 b9 ]暂时还没完全搞清楚,有点晕。有点简单问题复杂化的感脚。
  f9 I$ a- @& ^+ L1 L& N(引用的帖子与博客不代表个人观点。。。)
8 w) P) P) {6 i% F8 M* c2 w
malloc free 的实现看上去好像不太靠普(其实没仔细看,不直观,看个大概..关键手册不详细,或没找到。)
! z4 u+ y* L4 T4 U2 P# l$ r9 V- oida F5生成(其中一个QSys.axf),仅供参考。
- I5 _# c% R9 T8 J. [+ uint __fastcall malloc(int a1)& F: B5 b2 D+ `" x
{
' _* H5 x2 b& ]7 e( c4 w* {2 \3 A6 R  int v1; // r1@1  f! F/ y4 ~: b
  int i; // r2@29 F* X3 E+ d& V$ `# @
  unsigned int v3; // r3@3
4 I* {+ O) }6 U2 m% S9 f  __int64 v4; // r6@54 U! E. u7 K2 t5 c, A: Q" j. q
  int v5; // r3@5" o; U) P( y  G, Z
  int result; // r0@7
) S- W% H' k  f, d" W" r  U7 \  int v7; // r0@90 n6 r/ S0 Z. {" |

* }8 D4 p, D! E  v1 = (a1 + 11) & 0xFFFFFFF8;' ~+ a# s6 C. C
  while ( 1 ): G' q) Q1 Y8 l/ q
  {
0 C7 ~" a! `9 z  [    for ( i = (int)&_microlib_freelist; ; i = v7 + 4 )& a3 t. f1 M# o# P% t0 J
    {$ @5 u' t$ V/ A
      v7 = *(_DWORD *)i;" |( K5 [* y9 K0 P2 {8 z+ _
      if ( !*(_DWORD *)i )7 n7 A; q% _* y# p4 h6 N
      {$ u: }8 c% c! u2 w( o% C
        result = 0;3 ~" N2 n% n; U
        goto LABEL_11;
' @: Q$ y( l' T      }
. b; j2 J" Y; q. t9 B7 x      v3 = *(_DWORD *)v7;9 E( J& I* d4 X! ]3 c: B8 y
      if ( *(_DWORD *)v7 >= (unsigned int)v1 )% S$ d9 L: N# d
        break;. ~# w& L3 R2 F3 B6 f
    }) P: S, u! M% J) e( P9 S
    if ( v3 <= v1 )1 w& s8 D, ]2 W7 d
    {
+ d5 M7 b( p, g# d0 ]      v5 = *(_DWORD *)(v7 + 4);
8 O) B3 r6 K2 g- G) o    }
+ C& u+ ?, ?9 }    else, F3 n& j" M. `8 C0 d
    {8 i) M& j" \2 D
      LODWORD(v4) = v3 - v1;
& M- J6 x* D8 y9 v" d  `9 V, B- X, Y) e      v5 = v7 + v1;
# ~7 n; G* a6 \1 @2 _6 m' i      HIDWORD(v4) = *(_DWORD *)(v7 + 4);
0 J- O' @6 c* r1 R2 p      *(_QWORD *)(v7 + v1) = v4;
. W( V5 J9 E, |' s2 h% f* B    }! h! _. u. @& Y, j7 K6 A
    *(_DWORD *)i = v5;
. d# C0 X6 h. J5 X    *(_DWORD *)v7 = v1;. K  H0 ~+ L' X$ i
    result = v7 + 4;
+ C1 f5 P7 T- \( O  Q% U) ?6 FLABEL_11:- X9 s9 {" `1 f! c. d) l+ J
    if ( result )
+ [8 `2 R; j/ R5 G! g& u% N0 G      return result;- [1 E6 l, h( \+ G  }4 f- g
    if ( _microlib_freelist_initialised )8 C! ~# j# h% d3 V* w
      return 0;
5 c4 c6 O% r  k4 G3 @  e    _microlib_freelist = (int)&unk_200000EC;8 {! K/ I$ z9 V
    unk_200000EC = 0x27FC & 0xFFFFFFF8;
7 A; Q3 ^3 H  J! }1 g% u* f- A    unk_200000F0 = 0;' I0 W0 @8 H8 _9 X) u3 j- I: o
    _microlib_freelist_initialised = 1;
4 `" v. g% C0 y- G4 Z$ X6 l: L  }# s( [, i* v: d9 R1 ^6 P$ O" ?
}
. u' j5 [6 q+ L​int __fastcall free(int result). N# p. i/ l" O9 c  W2 G% F
{! f5 M$ d1 B3 i; c
  int v1; // r2@2
" L4 u7 S, n1 f: F8 T  int i; // r1@26 p7 x5 O3 M* u1 e# z

9 ]7 s% E9 G" U. n  if ( result )
( r9 \) |) F8 V  p$ h; E; I/ y& j3 E: R  {
9 A7 F+ z- C4 Z0 n* f    v1 = 0;+ ^6 e( \. T' B
    result -= 4;. X/ _! }8 X9 e7 p
    for ( i = _microlib_freelist; i && i <= (unsigned int)result; i = *(_DWORD *)(i + 4) )
0 P" z& W5 W+ {      v1 = i;1 Z' D3 X+ T' U$ M, n) W$ K2 M: g
    if ( v1 ), N7 F0 J$ {6 S- E5 q% |& u& v% |
    {- a  e& p9 O; J" y
      if ( result - v1 == *(_DWORD *)v1 )1 U3 \2 e% p( A6 [8 @- V
      {
, U* V; _! X1 E& J* ^. H        *(_DWORD *)v1 += *(_DWORD *)result;" a1 [) f' l! t# a& v1 H3 t  b
        result = v1;
4 \  A: X2 i; D2 R: p      }
9 R; r( `- h) P6 p' m      else
8 ?9 C7 L) {" z, H  z      {4 G; {3 n$ `+ q$ ]+ }
        *(_DWORD *)(v1 + 4) = result;, _$ v& d6 ^1 e
      }" a/ p4 U! t8 _+ m
    }
" `( b# ^7 j4 m" e! T    else% W" \. p/ M" d8 y9 e
    {2 T( \& |6 J* u8 _
      _microlib_freelist = result;
9 f# Y5 F  V. K. _    }
6 b! b7 w: K8 c& j- Z+ K    if ( i )- A# A6 l: `' @2 w. O
    {  M% C- }/ f! l& F1 l! i9 z
      if ( i - result == *(_DWORD *)result )0 ^3 R8 }/ l8 u0 \" U8 W6 l
      {& w+ J; E. n, }1 Y1 F# f$ d4 Z# V/ p4 y
        *(_DWORD *)result += *(_DWORD *)i;
0 r9 X% A5 [0 [2 {5 ^  Z/ R        i = *(_DWORD *)(i + 4);
7 R0 J/ I; A5 o( G  N6 J0 m      }& ]$ v8 `( g$ s1 w* s) c4 _" x
    }4 c5 q* V8 S+ Q  z: F. E9 K
    *(_DWORD *)(result + 4) = i;
: r$ @- P' F! t8 i+ g4 t9 y& b+ b  }
& Y6 ?8 U# J. E$ s" q3 y7 R  return result;
) z7 w: ~* N5 N- K7 b2 n$ X" \}5 E, s; [! `4 F8 z

参考1MDK4.54 hlp下的某个.chm,好吧我落伍了...)0 I- M0 }( z" Y& {! _; P: i
calloc(),& q( _) }* z$ M+ z3 U* }
free(),
# P1 d2 r% d2 m, vmalloc(),: O  O: L( u! H8 N# e, X& c9 K
realloc()
/ F/ u1 e- s- \2 R/ P* @/ `, {The heap functions are thread-safe if the _mutex_* functions are implemented.
3 r6 f0 H: u% d; t) y2 Q- N3 O$ N7 ?) b
A single heap is shared between all threads, and mutexes are used to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine-grained locking if required, rather than protecting the entire heap with a single mutex (coarse-grained locking).6 j% t7 w; C, p* D& g, C* c

. T; j, i9 H6 w% E! m0 y# S
参考2:(FROM amobbs)' N/ P# Q( ?4 M9 H- m& v
9 O8 C. F% X7 Q1 L# g  M1 c
在ARM上移植ucos (RVDS环境),关于MALLOC的问题bottom↓
( K% k: N: a- v1 ^- a看3652|回7|收藏
2 E. ?* a# m0 {! v1 Q0 ]) g3 `" \1楼 chinatf 只看他
. r: k  J; [! a2009-3-31 16:51:19. Q8 I/ G/ \) t! t: d# D
使用RVDS集成开发环境,ARM平台。; J/ c" V5 r: H  |: p
设置好系统堆栈,使得malloc()函数能够正常使用。4 Q4 M4 F, w" ~' S- W8 [

9 ?5 O, X: d4 J6 H- x* @问题:
0 W# e+ u9 n3 [& e- d: e, a) D====
9 D* q0 J, t9 ^8 n我运行uCosII系统,在多个同时运行的任务中调用malloc()函数。
# X  ?% {, ]2 ^* y4 e由于多个任务可能同时在调用malloc()函数,而malloc()是RVDS提供的库函数,
! T% j8 C9 R7 O并没有考虑多任务调度的情况,所以多个任务可能同时在调用malloc()函数有可能2 @( K4 L5 i$ c  M! W" y# `
会造成冲突。
( T" G+ y5 c( S+ `) c* _" N3 K5 V6 D+ S  J/ N0 h7 h
解决方法:4 A  }! U! o" j4 B- x
====
4 ?4 l- f% M* {' l5 b$ r% |* e在任务中调用malloc()的地方使用互斥量,使得malloc()在某个时候只能被一个任务
6 |9 u. n2 R! _4 b7 Z3 G调用。7 _8 y2 B7 h9 O0 f8 h4 x3 i
4 H  D! C' S  P3 C- G: I
欢迎大家各抒己见!. Z# B" ?6 z8 S- N! q
2楼 dr2001 只看他 / u7 k+ z9 ^& U
2009-3-31 17:37:582 \  r) X/ f! t3 q
malloc用的是C Run Time Library的堆[Heap],和堆栈没关系。不给CRTL初始化堆,再多的堆栈也没什么用。
5 b# Z% V$ A1 i3 e/ d6 t" `5 v8 {  S; z4 M6 T) j, D8 h1 b/ E
malloc可重入与否请参考使用的CRTL的说明,有的也许可重入。不过这类库还是程序加锁比较安全。
# L5 q$ `8 X% P) e" O; l
$ p1 X( I: H- x' q7 C5 G6 B具体使用什么锁看需求吧。MCU环境,单核心,能够引发调度的除了程序主动释放时间片,就是中断,理论上这类操作屏蔽中断的方法效率更高。用mutex,sem,queue都是可以实现的,根据程序结构定了。  V" L' w( V7 [* n2 u
3楼 akin 只看他
' y9 m5 G  D3 i: t; e3 w2009-3-31 20:30:172 e/ d( r4 ]8 n, w! J& D- m; b, J
我一直担心单片机上用malloc和free会产生碎片,
5 z2 y* h0 Z' L- E6 u以前在RVDS下测试过能用,但有时候又不能,& s6 N/ H0 i9 f) i$ l* {
所以到目前都是几乎不用这对函数。
3 r( p$ ~0 q0 _, x6 v- ~0 j; F0 {4楼 akin 只看他 5 |; w6 x5 G" f) C# h
2009-3-31 20:32:08% ]- j9 u. {* Q3 H- v  r8 k
太多的不确定性总让人用得不放心,睡不着觉。% i  m+ o! `+ w
5楼 armrtems 只看他 % C4 u$ q. v6 o4 |: x4 J3 r7 h
2009-3-31 21:56:19' O5 L3 s" d/ `# @* l
RVDS  4.0么? 怎么调试?
2 \3 r( i7 l) X+ C3 f4 A% `5 X6 imalloc有一个配置选项,可配置为oe模式(保证实时性)和普通模式.
, _& n2 J0 e' ^, `- k" N  o7 Q针对多线程,runlibc有几个函数需要实现,armlink文档里面有说明。实现几个函数,线程切换时切换一个结构体,否则可能会有问题。. C: [4 N8 ^6 w8 a% s
runlibc的c库比较稳定,一般不会出问题。
  I; W, y# u2 V& B: y' n事实上网络上流传的移植包不是完美的,大都没有考虑这个问题,楼主还是比较细心的。
/ w' F% m, X8 x4 @& g" c0 i2 x( Z6楼 chinatf 只看他
/ v2 c( C3 [7 Q- a" l( [2009-4-1 09:46:46
* i7 j0 E6 _- x, z; Pto armrtems' b/ N6 n1 O: L. _  ^: p! ^: ?
我现在用RVDS2.2,我看看这个版本有没有malloc的配置选项。
0 A) w) P) g  |2 ], f7 `: A( R( ?+ r7楼 dr2001 只看他 9 E" _. h# C4 A+ a" D6 ^- P) x5 V
2009-4-1 10:03:17! s' K' D) Q# W+ t
To 2# akin
8 A4 g6 s+ }& }$ d' H如果正确初始化堆,用起来是没有问题的,如果你用了printf之类的库,这些东西比较吃堆空间,堆小了不一定剩下那么多给你用。具体的需要看看CRTL的手册,专门有章节说内存管理的。
) i& N% w# [+ F5 q7 O0 P+ }7 Y( m6 F
; G" j9 q) g5 @  v; OMalloc和Free导致的碎片问题确实讨厌,不过这个要看具体的分配策略了,CRTL发展了这么多年,嵌入式环境下应该有基于页的算法了吧。浪费是浪费些,毕竟还有的用。  [" w9 ?; z: t% r

. E2 S( ^/ M% z) }( o0 Y+ \  XTo 4# armrtems
) V3 K$ N+ r* E! q& GRV4 调试只能用ARM ICE;如果要调试,只能用这个的编译器,得到axf,加载到别的支持axf的调试环境来用。RVDS本身还是不要想了,米人除外。-_-!5 v7 N7 h% m0 n! D4 f+ J8 J
8楼 chinatf 只看他 - A- a) M2 n! y7 n
2009-4-1 16:18:26+ i# u* r) ]7 m8 ~- ~
to 4# armrtems 6 V7 y5 U; k; m& ?1 s6 |
你说的malloc的配置选项是RVDS 4.0的新功能吗?
6 q% z/ U( c  z: R  Wup↑
* E; V( c$ D, P2 o* [阿莫电子论坛(原ourAVR/ourDEV)* j- y7 c* s1 t, d
© 2004-2014 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com  {3 k+ q2 J1 z; u2 w/ @7 K& M
首页|标准版|触屏版|电脑版3 X" [3 K. h2 C- Z6 r

参考3:1 |' i- \  O, ]# A
对于可重入、线程安全、异步信号安全几个概念的理解 0 C7 n" \. V, u( Q& I# \- }/ F

& s1 h6 e& n5 ^http://blog.chinaunix.net/uid-293474-id-2134181.html+ f& t! {, v. P

/ b6 n8 z9 R8 R5 `4 L6 B, b, m* r

+ E* W4 h- a2 a- X0 }
qianfan 回答时间:2015-6-29 16:17:03
Mandelbrot_Set 发表于 2015-6-29 14:18. y6 _  T4 M2 s0 _
我觉得还有一个可能怀疑的就是malloc与free本身.
* ^5 o8 J2 m2 h- x% |  X: ]# M设计上本身并不排除malloc,free执行一半调度到另一任务 ...

7 l! J! X: T; \6 [' {之前只觉得malloc,free导致的内存碎片的问题,没考虑这么多。那你觉得是将所有的malloc,free关中断保护好,还是直接拒绝使用malloc,free好呢?
qianfan 回答时间:2015-6-29 16:35:51
Mandelbrot_Set 发表于 2015-6-29 14:18; i( m' F, ^; r) g, G3 A2 P
我觉得还有一个可能怀疑的就是malloc与free本身.
3 C/ Y* s) y' m/ ]9 X/ h2 p' i设计上本身并不排除malloc,free执行一半调度到另一任务 ...

5 `% s3 ^) B4 w& B( c$ q8 q我觉得你可以发一篇ida反编译的教程,让我们学习一下。
Mandelbrot_Set 回答时间:2015-6-29 17:10:04
QianFan 发表于 2015-6-29 16:35
" `: _. ~* {0 f, \0 Q- g我觉得你可以发一篇ida反编译的教程,让我们学习一下。

7 m% L) ^+ B# K1 e0 b& F* k  v* {用的不好,我这是插件生成的。
7 l7 D' A. H, e- N- N* A7 b+ U{! \3 y1 i0 {' n9 a4 E2 U: z
.o .axf是elf格式的,mdk默认工程配置是保留调试信息的。0 l, m1 a. A9 x9 c, k' W
打开ida,.axf托进去,弹出的对话框凭感觉点掉。。。
. `- Q, {# E  t: j- `" L( j点要看的函数(有调试信息,一般该有的符号(函数)都有),会看到汇编代码。
& m! I9 |7 s' g  q按下F5,反编译(前提是要下载带arm F5 插件的和谐版)# G7 ?. c% l6 \8 A
(.hex就不太好弄了,我又不玩破解...)! m0 L4 x9 r3 N5 c! ^$ z
}
安臣 回答时间:2015-6-29 17:36:36
纯支持一次啊   我后面再学  认识你们几个真好
qianfan 回答时间:2015-6-29 18:01:24
安臣 发表于 2015-6-29 17:36+ G0 _. _! _4 ^
纯支持一次啊   我后面再学  认识你们几个真好

+ [  J$ u5 ^1 s感谢支持啊,话说这个头像和你QQ头像差距好大啊
qianfan 回答时间:2015-6-29 20:45:07
qianfan 回答时间:2015-6-29 21:40:30
Update:0.0.2
) q. m5 R& i/ ^; f$ X7 A* D2 O/ }+ O2 a/ X
    改进taskCreate,不再使用malloc和free进行自动内存分配。
6 k5 H  E$ L! L! M9 N% v+ U: O9 Q    删除void delay(unsigned int pid,unsigned int ticks);
8 T$ t  a* x  I+ x$ Y1 u4 e    新增函数void suspend(void),用于挂起任务本身。
# ~, @6 ~/ e  y    新增函数void resume(unsigned int pid),用于恢复已经被挂起的任务或者被sleep阻塞的任务。
wyxy163@126.com 回答时间:2015-6-29 22:16:59
提示: 作者被禁止或删除 内容自动屏蔽
Mandelbrot_Set 回答时间:2015-6-30 10:50:48
QianFan 发表于 2015-6-29 21:40
! P4 n* h/ N+ [8 cUpdate:0.0.2& o7 K; I! i3 f" p" u

4 l) m( L5 c  W! D0 P    改进taskCreate,不再使用malloc和free进行自动内存分配。
! x$ G3 j) x3 z& I5 c/ ]: s/ G! W
我又来了哈...
9 y7 l- i6 f. L7 q$ ?8 w- Eexample1:- `) D5 K5 ?2 g
void sleep(int delayTicks)中
% |# a9 z( c, H# W# V; ]) L7 J% H在if((taskList[pid]==NULL)||(pid==IDLE_PID)||(delayTicks==0))& h/ l1 q: m9 e8 l8 l( d0 k$ U
                return ;& l& e* j2 m$ r) {
之前taskSwOn();之后产生调度
' ^- O; h; k$ b/ U7 d) K3 Z并不能确保taskList[pid]不是NULL(taskList[curpid]本不应该NULL.)
! i6 I8 u; u" y5 _(调度后来了个changePid).
) H8 {) z9 L! @5 |% @, E2 Rexample2:
0 B3 u* a" S; t! @$ K7 M$ |9 p: tupdateNextTask执行中产生调度,
2 ^! ]) D9 x6 M0 o- F每一个taskList[pid]都有被其它任务修改的可能,应该有风险.
  j# n8 @! s$ s  f. k: `) P4 b
, p4 E5 D& ^* A
- F( o& y3 Z3 `6 ^% K" U
星辰一方 回答时间:2015-6-30 11:19:26
路过……帮顶~
qianfan 回答时间:2015-6-30 11:54:01
Mandelbrot_Set 发表于 2015-6-30 10:507 x2 }$ O& b" f, O
我又来了哈...; ^' _4 Q0 p/ E
example1:
4 L$ b% T3 L0 J* i, G% e& a8 q4 xvoid sleep(int delayTicks)中

, ~1 w; m, {0 \/ f  @, y看来确实有问题,changePid和sleep能够产生冲突。
! Z( J5 |, ]: I8 ^6 G) `" W
: x* |' z3 K: b7 o  u比如有一任务Task1,task1Pid==1.9 j$ P- K8 V/ [4 B* B6 F' h
如果Task1调用了sleep将自己阻塞,而之后另一个任务(Task2)中使用了changePid(task1Pid,10)将task1的优先级改了,这样会立即发生新的任务调度。而之后的某一个时刻,由sleep导致Task1的阻塞被解除,这样也没法恢复了。应该是changePid惹的祸吧。- i: d; x. `* ^! N; T: [8 w

. Q. @8 ?1 a# N/ U8 U
3 ?# j  v& L. S9 R( O* Q好多问题需要解决。。。思维不行啊,很多问题想不到。+ F+ N1 c+ X: A' Y# G
感谢指正啊,非常感谢,你之前是不是做到这方面的东西呢?感觉想的好全面。
4 ?1 n2 S: f; W* p1 G- {
qianfan 回答时间:2015-6-30 12:45:21
Mandelbrot_Set 发表于 2015-6-30 10:50+ z5 {4 T( _) B, X! e+ g
我又来了哈...) `+ j6 j; R% {& O
example1:
2 u( C8 \7 y0 I* Evoid sleep(int delayTicks)中

. E& B! p: f7 C4 e& z' Z请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。也就是到1100个节拍的时候这个任务应该被唤醒。
  R4 K2 Z4 B" d3 d; [+ F6 t
( y! D/ }9 T3 S8 K假设到了第200个OS节拍的时候,另一个任务Task2更改了Task1的优先级,将他的优先级提高了。你说这个时候是应该让Task1立即执行呢,还是到1100个节拍的时候才能再次执行?
Mandelbrot_Set 回答时间:2015-6-30 13:23:06
QianFan 发表于 2015-6-30 12:450 i  V* ?1 c, O+ u- f
请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。 ...

0 {# ?  a# Y! ~3 d我觉得Task1既然sleep(1000)了,那就应该有sleep(1000)的样子,在1100节拍之前就不应该是就绪状态吧...4 M( \' N; a; ]; N
; x5 t! C0 l6 {" \

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版