基于嵌入式Linux操作系统的内核级线程库的实现方法

文档序号:6459901阅读:137来源:国知局
专利名称:基于嵌入式Linux操作系统的内核级线程库的实现方法
技术领域
本发明涉及嵌入式操作系统领域,具体涉及基于嵌入式Linux操作系统的内核级线程库的实现方法。

背景技术
内核是操作系统的内在核心,系统的其他部分必须依靠内核提供的服务,如管理硬件设备、分配系统资源等等。操作系统内核通常由响应中断的中断服务程序、管理多进程的处理器调度程序、管理进程地址空间的内存管理程序和网络、进程间通信等系统服务共同组成。
Linux作为基于GNU规范的操作系统,由于其硬件支持的多样性、内核运行的高效和稳定性、应用程序开发的灵活性、独特的可按需裁剪性以及内核模块的动态可加载性,日益得到嵌入式操作系统领域的重视。随着Li-nux操作系统的不断发展,逐渐由以前的非实时调度内核发展为目前的软实时调度内核(如2.6及以上的内核版本),提供了对事件优先级调度和抢占调度的支持,可以抢占当前正在运行的进程并运行新的优先级更高的可运行进程,能够满足非常严格的实时性要求,极大地扩展了Linux操作系统在嵌入式系统中的使用范围。
软实时调度内核将尽力调度进程,使得在它们的限定时间到来之前运行,但不能够保证总能满足这些进程的时间要求。与此对应的,硬实时调度内核保证在一定条件下,可以满足任何调度的时间要求。为此,出现了一些商用的嵌入式Linux产品,如RT-Linux,大大增强了Linux操作系统的硬实时性。其原理是在Linux的非实时内核上再增加一个小型的实时内核,由该实时内核来控制实时任务,而原来的非实时内核则控制非实时任务,同时将Linux本身的任务以及Linux内核本身作为一个优先级最低的任务,而实时任务作为优先级最高的任务,即在实时任务存在的情况下运行实时任务,否则才运行Linux本身的任务。由于实时内核的实现比较简单,且L-inux本身的非实时内核作为实时内核可抢占的一个任务,因此在任务运行和调度的效率上完全可以达到硬实时的要求。
在Linux操作系统中,内核是独立于普通应用程序的,它一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限,这种系统态和被保护起来的内存空间,统称为内核空间。相对的,应用程序在用户空间执行,它们只能够看到允许它们使用的部分系统资源,并且不能够使用某些特定的系统功能,不能够直接访问硬件,此外还有一些使用限制。当内核运行时,系统以内核态进入内核空间,相反,普通用户程序以用户态进入用户空间,应用程序通过系统调用(如访问文件系统、分配系统资源、建立网络连接等)与内核通信,访问内核提供的系统服务。系统调用是应用程序访问系统服务的唯一手段。
由上述分析可知,现有的嵌入式Linux操作系统主要是从内核运行的角度提高了任务调度的效率和实时性。但是从应用程序运行的角度来看,每当进行系统调用时,必须通过一次从用户态到内核态的切换,进入到内核态后才能够访问操作系统的服务。当使用完系统调用后,又必须通过一次从内核态到用户态的切换,返回到用户空间后才能够继续执行应用程序。应用程序每进行一次系统调用,必须进行两次切换。此外,每当系统中有中断发生时,应用程序也要进行两次切换,从用户态进入到内核态处理中断,然后从内核态返回到用户态继续应用程序的执行。因此,嵌入式Linux应用系统的主要瓶颈在于应用程序从用户态进入到内核态以及从内核态返回到用户态的反复切换上。
为了减少反复切换带来的开销,提高应用系统的整体性能,目前存在使用用户级线程库的方式,它是通过在用户空间中增加运行库来实现的。这种实现方式由用户级线程库自身进行用户线程的调度,各用户线程之间是非抢占式,一个用户线程会一直运行,直至它主动放弃CPU(线程退出、等待同步对象或执行阻塞式系统调用)或是整个进程被内核重新调度。用户级线程库的优点在于,用户线程调度时不需要切换到内核态,免去了切换的开销。然而这种实现方式的缺点也是非常明显的,它不能够利用内核中的实时调度机制,因此不适应对实时性要求较高的嵌入式应用。
另一种方式是将应用程序以内核模块的形式动态加载到Linux操作系统内核中,直接在内核空间中以内核线程的方式运行。但是涉及到的内核API接口非常多,内核模块编程非常复杂,需要编程人员对Linux内核非常了解,加重了应用程序的开发和移植难度。
为了解决现有技术的不足,本发明提供了基于嵌入式Linux操作系统的内核级线程库的实现方法,提供了内核线程的管理、信号量同步机制、内存的动态分配和回收和日志管理功能,如内核线程的创建、终止和延时,互斥信号量的申请和释放,按照优先级记录日志信息等,并且还提供标准C库的功能子集,如基本输入输出,字符串操作,文件操作和网络套接字等。本发明提供的方法的优势在于第一,对内核进行较小的改动就可以支持现有嵌入式Linux操作系统内核中的软实时或者硬实时调度机制,能够保证应用的实时性需求;第二,能够彻底消除应用进程在用户态和内核态之间反复切换带来的开销,显著提高嵌入式Linux应用系统的整体性能;第三,屏蔽了内核模块编程的复杂性,提供了一个供编程人员使用的开发框架以及一套编程接口(API),能够降低应用开发的复杂度,提高开发效率。


发明内容
本发明的目的在于提供基于嵌入式Linux操作系统的内核级线程库的实现方法,提供了内核线程的管理、信号量的管理、内存的管理和日志的管理等功能,内核线程的管理实现了一个比较完整的内核线程管理体系,包括线程的创建、中止和延迟等功能;信号量的管理提供了2种信号量机制,包括互斥信号量(Mutex Semaphore)和计数信号量(Counting Semaphore),在信号量的获取、释放和删除上使用了统一的接口,每种信号量都包括阻塞和非阻塞2种形式;内存的管理提供了灵活高效的内存分配/回收、释放和查看;日志的管理实现了信息记录功能,提供了按照日志优先级的过虑机制方便定位用户关注的信息。此外,还提供标准C库的功能子集,如基本输入输出,字符串操作,文件操作和网络套接字等AIP函数接口。
本发明基于嵌入式Linux操作系统的内核级线程库的实现方法,其步骤包括 (1)按照下述步骤修改Linux内核源代码,以提供对Linux内核级线程库LKTL底层运行环境的支持,完成后进入步骤(4) (1.1)在代表进程描述符的task_struct数据结构中增加一个新的vo-id类型的指针lktl并且初始化为NULL。
(1.2)在进程的内核堆栈中增加一个int类型的指针lktl_esp_stack并且初始化为NULL,由该指针指向通过LKTL运行在内核空间中的应用程序的堆栈地址,堆栈大小和堆栈地址则以参数的形式通知LKTL的线程创建函数。通过lktl_esp_stack指针,可以动态扩展进程的内核堆栈的大小,突破进程的内核堆栈固定为8K字节或者4K字节的限制; (1.3)根据不同的硬件体系结构,对获取当前运行进程的task_stru-ct指针的实现进行相应地修改。内核是通过current宏查找到当前正在运行进程的task_struct指针,不同的硬件体系结构下current宏的实现也不同。有些硬件体系结构如PowerPC,使用一个专门的寄存器来存取指向当前进程task_struct的指针,current宏只需将寄存器中的值返回即可,在这种硬件体系结构下,直接进入步骤(3)。有些硬件体系结构如x86,本身的寄存器并不多,只能通过计算进程的内核堆栈偏移间接地查找task_struct指针,由current宏提取并返回task_struct指针的地址,计算进程的内核堆栈偏移是在内核堆栈固定为8K字节或者4K字节的条件下完成的,在这种硬件体系结构下,进入步骤(2); (2)修改获取当前的通过KTL运行内核空间中的应用程序的task_struct指针的实现方式,同时不影响其他的普通应用程序的运行,即普通应用进程的内核堆栈仍然固定为8K字节或者4K字节。按照下述步骤进行,完成后进入步骤(3) (2.1)修改current的宏定义的方式,将current宏修改为task_stru-ct指针类型的全局变量并且初始化为NULL; (2.2)在计算进程的内核堆栈偏移的函数中进行判断,如果current为NULL,则通过原来的计算堆栈偏移的方式返回task_struct指针;否则直接返回current; (2.3)修改计算进程的内核堆栈偏移的宏定义,将current指针直接传送到寄存器中; (2.4)在内核启动函数的开始处对current指针进行赋值,使current的值为通过计算进程的内核堆栈偏移返回的task_struct指针,即内核中的0号进程仍然按照原来的获取进程的task_struct指针的方式进行获取; (2.5)在进程调度程序中对进程上下文进行切换之前增加对current指针的赋值,使得current的值为调度程序经过选择并且准备投入运行的进程的task_struct指针; (3)在进程创建函数中将lktl_esp_stack指针赋值为LKTL创建的应用程序的堆栈地址,然后进入步骤(4); (4)编译修改后的Linux内核源代码,生成新的内核映像并且启动新内核映像,然后进入步骤(5); (5)加载LKTL内核模块,按照下述步骤执行LKTL各功能模块的初始化,完成后进入步骤(6) (5.1)加载标准C库的功能子集的功能模块,提供内核级的基本输入输出、字符串操作、文件操作和网络套接字等API函数接口,应用程序在需要时可直接调用这些API函数接口; (5.2)进行内存管理功能模块的初始化,设定分配的内存块的大小、初始化内存块链表以及注册内存回收的回调函数lktl_kmem_reap(); (5.3)进行信号量管理功能模块的初始化,注册信号量的获取函数、信号量的释放函数以及信号量的删除函数,并且初始化等待信号量的任务队列; (5.4)进行日志管理功能模块的初始化,设置需要记录的事件类型以及各自的优先级; (5.5)进行线程管理功能模块的初始化,创建LKTL线程的工作队列l-ktl_thread_workqueue、注册LKTL线程退出时的回调函数lktl_thread_ex-it_callback()、通知Linux内核的后台线程kevent创建一个master_thread主线程、设置master_thread的优先级为最高的实时优先级并且进入睡眠状态,然后设置master_thread主线程的SIGCHLD信号; (5.6)当master_thread主线程创建完成之后,设置它的SIGCHLD信号,处理其子线程执行完毕退出时发送的SIGCHLD信号; (6)将需要创建LKTL线程的任务加入到lktl_thread_workqueue工作队列的尾端,一旦master_thread线程被唤醒时,就由它将工作队列中的任务一个个取出,依次完成每个需要创建LKTL线程的任务,被创建的LKTL线程是master_thread主线程的子线程,当lktl_thread_workqueue工作队列中没有需要处理的任务时master_thread进入睡眠状态; (7)新创建的LKTL线程的优先级设置为较高的实时优先级,使得LKTL线程的优先级小于master_thread主线程的实时优先级并且大于Linux的普通内核线程的优先级; (8)当LKTL线程创建完成之后,设置它的SIGKILL信号,处理master_thread主线程发送的强制LKTL线程终止的SIGKILL信号; (9)master_thread主线程、代表应用程序的LKTL线程以及Linux的普通内核线程由Linux内核调度器统一调度执行; (10)等待应用程序的执行,应用程序以内核模块的方式加载到Linux内核,由代表应用程序的LKTL线程来执行; (11)应用程序执行完毕退出时,由代表应用程序的LKTL线程向mast-er_thread主线程发送SIGCHLD信号,master_thread主线程收到信号后等待LKTL线程的退出,然后进入睡眠状态; (12)重复上述步骤(6)-(11),直至LKTL内核模块卸载; (13)按照下述步骤执行LKTL内核模块的卸载 (13.1)终止线程管理功能模块,当master_thread主线程处于睡眠状态时,等待被调度运行,向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出;当mast-er_thread主线程处于运行状态时直接向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出; (13.2)终止日志管理功能模块,注销需要记录的事件类型和各自的优先级; (13.3)终止信号量管理功能模块,释放等待信号量的任务队列; (13.4)终止内存管理功能模块,回收分配的内存并且释放内存块链表; (14)内核级线程库LKTL停止运行。
本发明基于嵌入式Linux操作系统的内核级线程库的实现方法的优点是第一,对内核进行较小的改动就可以支持现有嵌入式Linux操作系统内核中的软实时或者硬实时调度机制,能够保证应用的实时性需求;第二,能够彻底消除应用进程在用户态和内核态之间反复切换带来的开销,显著提高嵌入式Linux应用系统的整体性能;第三,屏蔽了内核模块编程的复杂性,提供了一个供编程人员使用的开发框架以及一套编程接口(API),能够降低应用开发的复杂度,提高开发效率。



图1为本发明方法的流程示意图; 图2为修改Linux内核源代码以提供对Linux内核级线程库LKTL底层运行环境支持的过程; 图3为执行内核线程库LKTL各功能模块的初始化示意图; 图4为master_thread主线程管理LKTL线程创建的工作流程示意图; 图5为LKTL内核模块卸载的执行流程示意图。

具体实施例方式 下面结合附图对本发明作进一步详细的说明。
如图1所示,本发明方法包括以下步骤 (1)修改Linux内核源代码,以提供对Linux内核级线程库LKTL底层运行环境的支持。如图2所示,修改Linux内核源代码按照以下步骤进行,完成后进入步骤(4) (1.1)在代表进程描述符的task_struct数据结构中增加一个新的vo-id类型的指针lktl并且初始化为NULL。如果lktl不为NULL,表明应用程序通过LKTL运行在内核空间中,否则,表明应用程序即为普通的应用程序。通过对lktl的判断,内核可以在提供LKTL运行环境的同时不影响其他的普通应用程序的运行; (1.2)在进程的内核堆栈中增加一个int类型的指针lktl_esp_stack并且初始化为NULL,由该指针指向通过LKTL运行在内核空间中的应用程序的堆栈地址。内核空间只有进程的内核堆栈,而应用程序的堆栈中存放了应用程序的调用函数、参数、返回值和局部变量等。通过lktl_esp_stack指针,可以动态扩展进程的内核堆栈的大小,突破进程的内核堆栈固定为8K字节或者4K字节的限制。应用程序的堆栈大小和堆栈地址则由LKTL在创建进程时以参数的形式通知内核; (1.3)根据不同的硬件体系结构,对获取当前运行进程的task_stru-ct指针的实现进行相应地修改。在内核中,访问进程通常需要获取指向其task_struct指针,实际上,内核是通过current宏查找到当前正在运行进程的task_struct指针,不同的硬件体系结构下current宏的实现也不同。有些硬件体系结构如PowerPC,使用一个专门的寄存器来存取指向当前进程task_struct的指针,current宏只需将寄存器中的值返回即可,在这种硬件体系结构下,直接进入步骤(3)。有些硬件体系结构如x86,本身的寄存器并不多,只能通过计算进程的内核堆栈偏移间接地查找task_struct指针,由current宏提取并返回task_struct指针的地址,在这种硬件体系结构下,进入步骤(2); (2)对于通过计算进程的内核堆栈偏移间接地返回task_struct指针的硬件体系结构,如x86,是在进程的内核堆栈固定为8K字节或者4K字节的条件下完成的。而通过LKTL运行在内核空间中的应用程序的堆栈需要突破这个限制,因此需要修改获取当前的通过LKTL运行在内核空间中的应用程序的task_struct指针的实现方式,同时不影响其他的普通应用程序的运行,即普通应用进程的内核堆栈仍然固定为8K字节或者4K字节。按照下述步骤进行,完成后进入步骤(3) (2.1)修改current的宏定义的方式,将current宏修改为task_stru-ct指针类型的全局变量并且初始化为NULL; (2.2)在计算进程的内核堆栈偏移的函数中(如2.6内核版本中的cu-rrent_thread_info(void)函数)进行判断,如果current为NULL,则通过原来的计算堆栈偏移的方式返回task_struct指针;否则直接返回current; (2.3)修改计算进程的内核堆栈偏移的宏定义,将current指针直接传送到寄存器中(如2.6内核版本中的GET_THREAD_INFO(reg)宏定义,将current直接传送到reg中); (2.4)在内核启动函数(如2.6内核版本中的start_kernel(void)函数)的开始处对current指针进行赋值,使current的值为通过计算进程的内核堆栈偏移返回的task_struct指针,即内核中的0号进程仍然按照原来的获取进程的task_struct指针的方式进行获取; (2.5)在进程调度程序中对进程上下文进行切换之前(如2.6内核版本中的context_switch函数),增加对current指针的赋值,使得current的值为调度程序经过选择并且准备投入运行的进程的task_struct指针; (3)在进程创建函数(如2.6内核版本中的copy_process()函数)中将lktl_esp_stack指针赋值为LKTL指定的应用程序的堆栈地址,然后进入步骤(4); (4)编译修改后的Linux内核源代码,生成新的内核映像并且启动新内核映像,然后进入步骤(5); (5)加载LKTL内核模块,执行LKTL各功能模块的初始化。如图3所示,各功能模块的初始化按照以下步骤进行,完成后进入步骤(6) (5.1)加载标准C库的功能子集的功能模块,提供内核级的基本输入输出、字符串操作、文件操作和网络套接字等API函数接口,应用程序在需要时可直接调用这些API函数接口; (5.2)进行内存管理功能模块的初始化,设定分配的内存块的大小、初始化内存块链表以及注册内存回收的回调函数lktl_kmem_reap(); (5.3)进行信号量管理功能模块的初始化,注册信号量的获取函数、信号量的释放函数以及信号量的删除函数,并且初始化等待信号量的任务队列; (5.4)进行日志管理功能模块的初始化,设置需要记录的事件类型以及各自的优先级; (5.5)进行线程管理功能模块的初始化,创建LKTL线程的工作队列l-ktl_thread_workqueue、注册LKTL线程退出时的回调函数lktl_thread_ex-it_callback()、通知Linux内核的后台线程kevent创建一个master_thread主线程、设置master_thread的优先级为最高的实时优先级并且进入睡眠状态,然后设置master_thread主线程的SIGCHLD信号; (5.6)当master_thread主线程创建完成之后,设置它的SIGCHLD信号,处理其子线程执行完毕退出时发送的SIGCHLD信号; (6)由master_thread主线程管理LKTL线程的创建。如图4所示,mas-ter_thread主线程管理LKTL线程的创建按照以下步骤执行 (6.1)将需要创建LKTL线程的任务加入到lktl_thread_workqueue工作队列的尾端; (6.2)判断master_thread是否处于运行状态,如果master_thread不是处于运行状态,则继续睡眠;否则进入步骤(6.3); (6.3)判断lktl_thread workqueue工作队列是否为空,如果为空,则master_thread由运行状态转入睡眠状态;否则进入步骤(6.4); (6.4)从lktl_thread_workqueue工作队列中头部取出一个任务并且完成创建LKTL线程的创建,被创建的LKTL线程是master_thread主线程的子线程; (7)新创建的LKTL线程的优先级设置为较高的实时优先级,使得LKTL线程的优先级小于master_thread主线程的实时优先级并且大于Linux的普通内核线程的优先级; (8)当LKTL线程创建完成之后,设置它的SIGKILL信号,处理mast-er_thread主线程发送的强制LKTL线程终止的SIGKILL信号; (9)master_thread主线程、代表应用程序的LKTL线程以及Linux的普通内核线程由Linux内核调度器统一调度执行; (10)等待应用程序的执行,应用程序以内核模块的方式加载到Linux内核,由代表应用程序的LKTL线程来执行; (11)应用程序执行完毕退出时,由代表应用程序的LKTL线程向mast-er_thread主线程发送SIGCHLD信号,master_thread主线程收到信号后等待LKTL线程的退出,然后进入睡眠状态; (12)重复上述步骤(6)-(11),直至LKTL内核模块卸载; (13)执行LKTL内核模块的卸载。如图5所示,按照下述步骤执行LKTL内核模块的卸载 (13.1)终止线程管理功能模块,当master_thread主线程处于睡眠状态时,等待被调度运行,向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出;当mast-er_thread主线程处于运行状态时直接向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出; (13.2)终止日志管理功能模块,注销需要记录的事件类型和各自的优先级; (13.3)终止信号量管理功能模块,释放等待信号量的任务队列; (13.4)终止内存管理功能模块,回收分配的内存并且释放内存块链表; (14)内核级线程库LKTL停止运行。
实施例 测试了LKTL线程库对嵌入式Linux系统性能的提升,分别评价在不使用LKTL线程库时和使用LKTL线程库时,嵌入式Linux系统的响应时间。测试环境使用的是虚拟机的模拟环境,进行了如下的3种测试 (1)分别创建10和100个线程时的创建延时; (2)文件系统的系统调用open和close循环执行1000时的响应延时; (3)C/S模式下的典型客户端应用程序的执行延时,客户端和服务器进行简单的信息交互。
通过模拟实验,得出如下的测试结果 实验结果表明本方法能够显著提高嵌入式Linux应用系统的性能,在需要创建大量线程和频繁进行系统调用的工作负载的情况下,本方法所带来的性能提升是非常巨大的。
权利要求
1.一种基于嵌入式Linux操作系统的内核级线程库的实现方法,其特征在于
(1)按照下述步骤修改Linux内核源代码,以提供对Linux内核级线程库LKTL底层运行环境的支持,完成后进入步骤(4)
(1.1)在代表进程描述符的task_struct数据结构中增加一个新的void类型的指针lktl并且初始化为NULL;
(1.2)在进程的内核堆栈中增加一个int类型的指针lktl_esp_sta-ck并且初始化为NULL,由该指针指向通过LKTL运行在内核空间中的应用程序的堆栈地址,堆栈大小和堆栈地址则以参数的形式通知LKTL的线程创建函数;通过lktl_esp_stack指针,可以动态扩展进程的内核堆栈的大小,突破进程的内核堆栈固定为8K字节或者4K字节的限制;
(1.3)根据不同的硬件体系结构,对获取当前运行进程的task_st-ruct指针的实现进行相应地修改;内核是通过current宏查找到当前正在运行进程的task_struct指针,不同的硬件体系结构下current宏的实现也不同;有些硬件体系结构如PowerPC,使用一个专门的寄存器来存取指向当前进程task_struct的指针,current宏只需将寄存器中的值返回即可,在这种硬件体系结构下,直接进入步骤(3);有些硬件体系结构如x86,本身的寄存器并不多,只能通过计算进程的内核堆栈偏移间接地查找task_struct指针,由current宏提取并返回task_struct指针的地址,计算进程的内核堆栈偏移是在内核堆栈固定为8K字节或者4K字节的条件下完成的,在这种硬件体系结构下,进入步骤(2);
(2)修改获取当前的通过LKTL运行在内核空间中的应用程序的task_s-truct指针的实现方式,同时不影响其他的普通应用程序的运行,即普通应用进程的内核堆栈仍然固定为8K字节或者4K字节;按照下述步骤进行,完成后进入步骤(3)
(2.1)修改current的宏定义的方式,将current宏修改为task_st-ruct指针类型的全局变量并且初始化为NULL;
(2.2)在计算进程的内核堆栈偏移的函数中进行判断,如果curre-nt为NULL,则通过原来的计算堆栈偏移的方式返回task_struct指针;否则直接返回current;
(2.3)修改计算进程的内核堆栈偏移的宏定义,将current指针直接传送到寄存器中;
(2.4)在内核启动函数的开始处对current指针进行赋值,使curr-ent的值为通过计算进程的内核堆栈偏移返回的task_struct指针,即内核中的0号进程仍然按照原来的获取进程的task_struct指针的方式进行获取;
(2.5)在进程调度程序中对进程上下文进行切换之前增加对curre-nt指针的赋值,使得current的值为调度程序经过选择并且准备投入运行的进程的task_struct指针;
(3)在进程创建函数中将lktl_esp_stack指针赋值为LKTL创建的应用程序的堆栈地址,然后进入步骤(4);
(4)编译修改后的Linux内核源代码,生成新的内核映像并且启动新内核映像,然后进入步骤(5);
(5)加载LKTL内核模块,按照下述步骤执行LKTL各功能模块的初始化,完成后进入步骤(6)
(5.1)加载标准C库的功能子集的功能模块,提供内核级的基本输入输出、字符串操作、文件操作和网络套接字等API函数接口,应用程序在需要时可直接调用这些API函数接口;
(5.2)进行内存管理功能模块的初始化,设定分配的内存块的大小、初始化内存块链表以及注册内存回收的回调函数lktl_kmem_reap();
(5.3)进行信号量管理功能模块的初始化,注册信号量的获取函数、信号量的释放函数以及信号量的删除函数,并且初始化等待信号量的任务队列;
(5.4)进行日志管理功能模块的初始化,设置需要记录的事件类型以及各自的优先级;
(5.5)进行线程管理功能模块的初始化,创建LKTL线程的工作队列lktl_thread_workqueue、注册LKTL线程退出时的回调函数lktl_thread_e-xit_callback()、通知Linux内核的后台线程kevent创建一个master_thre-ad主线程、设置master_thread的优先级为最高的实时优先级并且进入睡眠状态,然后设置master_thread主线程的SIGCHLD信号;
(5.6)当master_thread主线程创建完成之后,设置它的SIGCHLD信号,处理其子线程执行完毕退出时发送的SIGCHLD信号;
(6)将需要创建LKTL线程的任务加入到lktl_thread_workqueue工作队列的尾端,一旦master_thread线程被唤醒时,就由它将工作队列中的任务一个个取出,依次完成每个需要创建LKTL线程的任务,被创建的LKTL线程是master_thread主线程的子线程,当lktl_thread_workqueue工作队列中没有需要处理的任务时master_thread进入睡眠状态;
(7)新创建的LKTL线程的优先级设置为较高的实时优先级,使得LKTL线程的优先级小于master_thread主线程的实时优先级并且大于Linux的普通内核线程的优先级;
(8)当LKTL线程创建完成之后,设置它的SIGKILL信号,处理master_thread主线程发送的强制LKTL线程终止的SIGKILL信号;
(9)master_thread主线程、代表应用程序的LKTL线程以及Linux的普通内核线程由Linux内核调度器统一调度执行;
(10)等待应用程序的执行,应用程序以内核模块的方式加载到Linux内核,由代表应用程序的LKTL线程来执行;
(11)应用程序执行完毕退出时,由代表应用程序的LKTL线程向mast-er_thread主线程发送SIGCHLD信号,master_thread主线程收到信号后等待LKTL线程的退出,然后进入睡眠状态;
(12)重复上述步骤(6)-(11),直至LKTL内核模块卸载;
(13)按照下述步骤执行LKTL内核模块的卸载
(13.1)终止线程管理功能模块,当master_thread主线程处于睡眠状态时,等待被调度运行,向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出;当maste-r_thread主线程处于运行状态时直接向所有的LKTL线程发送强制终止信号SIGKILL,等待这些LKTL线程的退出,然后master_thread主线程自身退出;
(13.2)终止日志管理功能模块,注销需要记录的事件类型和各自的优先级;
(13.3)终止信号量管理功能模块,释放等待信号量的任务队列;
(13.4)终止内存管理功能模块,回收分配的内存并且释放内存块链表;
(14)内核级线程库LKTL停止运行。
全文摘要
本发明一种基于嵌入式Linux操作系统的内核级线程库的实现方法,实现了一个完整的内核线程管理体系,提供了内核线程的管理、信号量的管理、内存的管理和日志的管理等功能,还提供标准C库的功能子集的AIP函数接口。其优点在于第一,对内核进行较小的改动就可以支持现有嵌入式Linux操作系统内核中的软实时或者硬实时调度机制,能够保证应用的实时性需求;第二,能够彻底消除应用进程在用户态和内核态之间反复切换带来的开销,显著提高嵌入式Linux应用系统的整体性能;第三,屏蔽了内核模块编程的复杂性,提供了一个供编程人员使用的开发框架以及一套编程接口(API),能够降低应用开发的复杂度,提高开发效率。
文档编号G06F9/46GK101226487SQ200810046848
公开日2008年7月23日 申请日期2008年1月30日 优先权日2008年1月30日
发明者斌 蔡, 邓广宏, 毅 刘, 池志强, 黄志华, 雄 程 申请人:中国船舶重工集团公司第七〇九研究所
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1