zoukankan      html  css  js  c++  java
  • nucleus plus学习总结(后续)

    前言:
        刚刚抽筋点了保存发布,结果要审核,那就分开写个续好了。
    内容:
    signal
        信号是异步通知task的一种机制,HISR是不可以接收信号的,但是可以发送信号。
        TCB中与signal相关数据结构包括active_signal,enable_signal(这是一个掩码,如果为0则不执行signal_handler),(*signal_handler),主要有两个函数,一个是send_signals()和signal_shell(),其中send_signals()函数主要是区分发送信号给自己还是给其他的task,如果发给自己就直接执行signal_shell(),如果发送至其他task(处于suspend或ready但没有占用处理器的状态),target task必须要释放占用的protect,因为在signal_handler中可能会去请求protect资源,这样就会发生死锁,当前task执行TCT_protect_switch()函数,与请求protect()函数前半部分一致,调用schedule_protect()让target task释放占用的protect资源。
        在target stack处建立solicited stack,其中PC = &signal_shell,保存target task的status和tc_statck_ptr,根据当前的状态,如果是ready或pure_suspend,则返回,否则就resume_task()唤醒target task,根据返回值确定是否进入schedule()。
        在send_signal中应用protect来保护共享数据,而到了protect_switch中应用关中断来保护,中间有一个数据保护的真空期,因此要两次确认target task没有再占用protect资源

    suspend/resume
    对于task状态改变的操作主要有suspend和resume函数,其中suspend将一个task挂起,当挂起自己时会control_to_system,finished和terminated状态的转变也是利用suspend函数,resume函数用来将task唤醒,并返回一个标志是否需要context switch

    线程同步
    应用里可以使用到的线程同步有两种方式,semaphore和event groups,semaphore与linux中的一直,但是NU中并没有对优先级反转有处理
    event groups是一个32bit的数据结构,可以标记32个事件,操作包括set和retrieve,set event时会唤醒suspend list上的所有task,最后在对相应bit consume,retrieve去请求event,如果失败则挂起在suspend list上,只有拿到event后才会对consume

    线程通信
    NU中支持的线程通信方式包括queue,pipe,mailbox,这里queue和pipe的机制基本相同,只是queue是按32bit操作,pipe是按照字节访问,但是代码里也做了对齐,mailbox是一种信箱机制,信箱的大小为4*32bit,使用的好处就是执行速度快

    内存管理
    NU并没有使用到虚拟内存管理,直接访问物理地址,有两种建立内存池的方法,动态内存管理和静态内存管理,动态内存管理采用的分配策略是first-fit和释放后内存融合,静态内存管理是每次分配固定大小的内存块,这样可能会引起内存的利用率降低,但是不会引起内存外部碎片
        

    1. 中断向量表的reset地址为0x0,直接跳转至INT_Initialize()

    2. Low_bit_set[256]用来快速计算优先级的表,其中放的是对应优先级数值第一个不为0的数,例如当前最高priority=17,则low_bit_set[17] = 0,17 = 0x11第一个不为0的位是第0位

    3. HISR不会suspend,没有time slice即同优先级的HISR依次执行,不会接收信号,只可以被中断,如果激活了更高优先级的HISR则当前HISR被抢占。

    4. 当中断发生时,ARM硬件完成的工作包括:
       i. 保存中断前的CPSR至SPSR_irq_mode
       ii.保存中断时PC值至lr_irq_mode
       iii.切换至irq mode,屏蔽irq bit,set arm mode
       iv. 将PC指向irq_entry(0x18)
    5. time slice只有在被中断里才会保存下来,即一个task被中断后执行了LISR和HISR后,重新schedule到task,其time slice是之前剩下的时间片,当task主动让出处理器时,比如self-suspend,send_signal,resume高优先级的task时,会将time slice重新置为预设值

    6. 在control_to_system里有clear protect的动作

    7. TMD_Timer_Start记录的是当前timer_active_list上顶端timer的remaining_time,当发生start_timer,stop_timer或timer expired时都会去更新这个值

    8. 所有的system call都要用system_protect来保护,因为其中有对于重要全局变量的访问

    9. TCB中有一个suspend_protect,用来记录task在suspend前拥有的是什么样类型的protect,例如一个请求Dynamic memory的task suspend在dm_suspend_list上,在挂起前将dm_protect保存至suspend_protect中,因为一个task在suspend前必须释放所持有的protect,所以只能利用suspend_protect标记之前占有的是dm_protect,当timeout发生时,重新获得dm_protect去执行cleanup函数,做清理工作将task从dm_suspend_list上移除,resume一个task时会将suspend_protect清空。

    10. 一个HISR中可以send_signal,suspend其他task,请求protect资源,这些动作都有可能使HISR让出处理器给低优先级的task去执行,都是调用TCC_schedule_protect(),目的是避免deadlock

    11. deadlock产生的四个必要条件 (必考)
        i.互斥条件:资源同一时间只可以被一个进程访问
        ii.请求与保持条件:当进程请求新资源阻塞时,不释放已经占有的资源
        iii.不剥夺条件:进程在占有资源时,未使用完之前,不可以被强行剥夺
        iv. 循环等待条件:若干进程形成一种头尾相接的循环等待资源关系
     
    12. 优先级反转(priority inversion)(必考)
    产生原因:三个task,优先级关系是taskA>taskB>taskC,taskC占有互斥sem,当taskA执行时申请sem,suspend,此时taskB被唤醒,继续执行,则taskC无法释放sem,导致高优先级的taskA无法执行,而低优先级的taskB一直执行下去
    解决方法:
        i.disable interrupt (影响OS的实时性)
        ii.disable preemption (影响实时性)
        iii.优先级继承
        在运行时,taskA请求低优先级taskC已经占有的sem,则将taskC的优先级提升至taskA相同
        iv. 优先级天花板
        在未运行的情况下,首先估计会使用到sem的task,然后将所有的task优先级升高至这些task中的最高     优先级。

    13. 在TCT_schedule_Protected的代码中,在control_to_thread前开关了一次中断,这样可以节省一次上下文切换,让中断在当前task上发生,而不是切换至占有protect的task在发生中断。

    14. 当task被中断后抢占,不会释放protect资源,因此在LISR中不可以使用与Protect相关的系统调用,只可以使用activate_HISR(),它是用中断来保证原子访问的。

    15. protect的嵌套利用unprotect_specific()和set_current_protect()来实现,同时system_protect一般作为第二个protect去申请,因为system_protect保护了内核中全局的数据结构,粒度较大,因此要尽量减少持有的时间

    16. 第一次中断的上下文保存在task stack,嵌套的中断上下文保存在system stack,因为中断嵌套发生在LISR中,此时sp值已经更新为system stack ptr

    17. protect() send_signal(), suspend()都有为了防止deadlock让持有protect的task执行,直到释放protect的机制

    18. 在调用terminate task时,如果task是suspend要调用cleanup函数,要利用suspend_protect保护,同时不会与system_protect形成死锁

    19. queue和pipe,按照FIFO的模式发送message,在变长模式下,如果taskA的message较大suspend,则taskB即使有空间也必须suspend在taskA后面。

    20.resume返回true的条件
        i.当前priority_list上只有target_task一个
        ii.target_task的优先级高于TCD_Highest_priority
        iii.确定当前task是可抢占的
        iv. 当前线程是一个task,如果是NULL则是在初始化里面,初始化还未完成不应该schedule,如果在           HISR里,因为HISR的优先级总是高于task的,因此也不会发生抢占

    21. Dynamic memory的数据结构使用双向链表是为了可以进行融合操作

    22. first-fit策略必须使用相邻融合的内存管理方法,但是仍会造成50%的浪费

    23. TCD_current_thread == NULL,如果当前开着中断则是schedule,如果是关中断则是INT_initialize

    24. 如果申请protect,TCD_current_thread == NULL,protect中直接跳过,因为这是在初始化中,初始化使用关中断来保护的

    25.如果一个HISR suspend了,则下一次LISR触发HISR时,就无法处理
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    面试问题整理Andorid版本 date: 2017-1-12 21:14:36 categories: 技术
    轻量级的C++插件框架
    C++程序在Windows平台上各种定位内存泄漏的方法,并对比了它们的优缺点
    Facebook App 的头文件会有更多的收获
    合并Excel工作薄中成绩表的VBA代码,非常适合教育一线的朋友_python
    使用python在校内发人人网状态(人人网看状态)_python
    使用PYTHON创建XML文档_python
    优秀的缓存请求库,快速请求接口和图片:WTRequestCenter
    让读者快速了解RocketMQ消息中间件需要解决哪些问题
    编绎调试HotSpot JVM及在Eclipse里调试HotSpot一些步骤
  • 原文地址:https://www.cnblogs.com/ch122633/p/7363279.html
Copyright © 2011-2022 走看看