首页> 中国专利> 一种内核态调用用户态函数的方法

一种内核态调用用户态函数的方法

摘要

本发明公开了一种内核态调用用户态函数的方法,包括:把内核态对用户态函数的调用转换为对内核态线程的阻塞和唤醒:在内核态中实现对被调用用户态函数的参数封装、内核态线程阻塞、ioctl消息通信来完成用户态函数的调用,当被调用用户态函数返回调用结果后,通过ioctl消息通信把用户态函数返回结果发送到内核态,再唤醒阻塞的内核态线程,完成函数调用的整个过程。本发明实现了内核态对用户态函数的调用,在不修改内核逻辑的情况下,使用阻塞唤醒方式完成内核态到用户态的透明调用,不修改原函数的逻辑。

著录项

  • 公开/公告号CN111857993B

    专利类型发明专利

  • 公开/公告日2022-07-08

    原文格式PDF

  • 申请/专利号CN202010591531.8

  • 发明设计人 王永强;

    申请日2020-06-24

  • 分类号G06F9/48(2006.01);G06F9/54(2006.01);

  • 代理机构深圳市六加知识产权代理有限公司 44372;

  • 代理人向彬

  • 地址 430000 湖北省武汉市东湖高新技术开发区高新四路6号

  • 入库时间 2022-08-23 13:59:43

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2022-07-08

    授权

    发明专利权授予

说明书

技术领域

本发明属于Linux内核技术领域,更具体地,涉及一种内核态调用用户态函数的方法。

背景技术

在现代操作系统中,为了系统的稳定性,都会实现内核态和用户态两种执行环境,两种环境有不同的执行权限和不同的地址空间,操作系统核心部分一般运行在内核态,用于完成任务调度、内存管理、硬件管理等核心功能,大部分应用层功能都运行在用户态,用户态的线程可通过特殊的系统调用陷入内核态来执行内核函数。而内核态的函数无法反过来调用用户态的函数接口。对于有些分离设计的系统,比如同时有运行在内核态和用户态的模块,这些模块之间存在相互调用的需求。而现有的操作系统则无法满足这种需求。

发明内容

针对现有技术存在的局限性问题,本发明提出一种内核态函数调用用户态函数的方法,解决某些情况下需要内核态调用用户态函数的问题。该方法实现方式通用,无需修改内核逻辑,且实现调用的接口都是内核的标准接口。

为实现上述目的,本发明提供了一种内核态调用用户态函数的方法,包括:

把内核态对用户态函数的调用转换为对内核态线程的阻塞和唤醒:在内核态中实现对被调用用户态函数的参数封装、内核态线程阻塞、ioctl消息通信来完成用户态函数的调用,当被调用用户态函数返回调用结果后,通过ioctl消息通信把用户态函数返回结果发送到内核态,再唤醒阻塞的内核态线程,完成函数调用的整个过程。

本发明的一个实施例中,所述内核态调用用户态函数的调用流程具体为:

内核态线程把需要调用函数的信息,包括参数、用户态函数名以及内核态线程id写入调用队列,将内核态线程阻塞,并唤醒阻塞在内核态的用户态线程,用户态线程被唤醒后读取调用队列,解析调用信息,并执行函数调用,把调用函数的返回结果写入调用队列,并根据内核线程id唤醒内核态线程,内核线程读取返回结果,并填充到函数的数据结构,返回到上层调用者继续执行。

本发明的一个实施例中,所述在内核态中实现对被调用用户态函数的参数封装,包括:

对于每一个需要被调用的用户态函数,在内核态实现一个与用户态函数相同原型的封装函数,在该封装函数中把该用户态函数的名称作为一个参数,该封装函数的参数还应该包括上层调用函数所传递参数以及内核态线程的id信息,并将该封装函数的参数保存到调用队列。

本发明的一个实施例中,通过内核态封装函数调用schedule_timeout_uninterruptible实现内核态线程的阻塞。

本发明的一个实施例中,ioctl的实现具体为:在内核态的proc文件系统中创建一个文件用于ioctl,用户态的线程通过打开该proc文件系统文件,然后使用系统调用ioctl将用户态线程阻塞以等待调用,请求调用的ioctl命令字与返回值的命令字要区分开。

本发明的一个实施例中,当ioctl函数检查调用队列为空时,用户态线程通过内核态ioctl调用schedule_timeout_uninterruptible函数阻塞在内核态,当检查到队列内容不为空时,就读取队列消息并返回用户态解析消息内容,通过函数名查找并调用用户态函数。

本发明的一个实施例中,当被调用用户态函数返回后,用户态线程解析返回参数和返回值,并进行消息封装,再封装请求调用时返回的内核态线程id,然后通过返回值的命令字调用ioctl,返回内核态。

本发明的一个实施例中,当内核态的ioctl函数接收到用户态函数返回的执行结果后,首先从调用队列查找与返回的内核态线程id相同的链表节点,然后拷贝返回结果到链表的返回值数据结构中,完成后ioctl函数通过队列记录的线程id唤醒处于阻塞状态的内核态线程,用户态线程继续执行下一次调用请求。

本发明的一个实施例中,被唤醒的内核态线程继续读取链表返回值数据结构,分析处理返回值和返回参数,把参数内容和返回值解析后填充到上层调用函数的结构中,并把自身分配的链表节点删除,释放内存,调用过程结束,函数返回。

本发明的一个实施例中,允许同时运行多个用户态线程读取内核态的调用队列,多个用户态线程并发执行ioctl陷入内核态检查调用队列是否为空,当调用队列有多个调用请求时,多个用户态线程可以同时获取到调用请求,当调用队列已经被读取完,剩余的未获取到调用请求的用户态线程会阻塞等待,多个用户态线程同时读取调用队列需要互斥锁保护列表。

总体而言,通过本发明所构思的以上技术方案与现有技术相比,具有如下有益效果:

(1)本发明实现了内核态对用户态函数的调用,在不修改内核逻辑的情况下,使用阻塞唤醒方式完成内核态到用户态的透明调用,不修改原函数的逻辑;

(2)实现内核与用户态的双向交互,增加内核态调试的便利性;满足某些内核态与用户态分离设计的应用相互调用需求;

(3)提高内核开发效率,实现内核态与用户态应用的统一部署,既满足用户态的灵活开发,又能满足内核态特殊操作。

附图说明

图1是本发明实施例中内核态调用用户态函数的方法的原理示意图;

图2是本发明实施例中内核态调用用户态函数方法的流程示意图;

图3是本发明实施例中一种内核态调用用户态函数的流程示意图;

图4是本发明实施例中内核态调用用户态函数的信号流示意图。

具体实施方式

为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。

实施例1

本发明提供了一种内核态调用用户态函数的方法,把内核态对用户态函数的调用转换为对内核态线程的阻塞和唤醒:在内核态中实现对被调用用户态函数的参数封装、内核态线程阻塞、ioctl消息通信来完成用户态函数的调用,当用户态函数返回调用结果后,通过ioctl消息通信把用户态函数返回结果发送到内核态,再唤醒阻塞的内核态线程,完成函数调用的整个过程。

图1是本发明实施例中内核态调用用户态函数的方法的原理示意图,包括用户态和内核态两部分设计,内核态的功能为主要部分,用户态部分通过调用内核态实现的接口来完成功能。内核态实现调用线程的阻塞和唤醒、调用队列的维护、返回值的解析以及数据的保护和访问互斥。

调用流程为:内核态线程1把需要调用函数的信息,包括参数,用户态函数名以及内核态线程id写入调用队列,并唤醒阻塞在内核态的用户态线程1,用户态线程1被唤醒后读取调用队列,解析调用信息,并执行函数调用,然后返回内核态,把调用函数的返回结果写入调用队列,并根据内核线程id唤醒内核态线程1,内核线程1读取调用队列,找到返回结果,并填充到函数的数据结构,返回到上层调用者继续执行。

本技术方案的核心思想是把内核态对用户态函数调用转换为对用户态线程的唤醒和对内核调用者的阻塞,通过阻塞和唤醒,保持调用的一致性,对内核的调用者来说,该过程是透明的,与普通的函数调用过程一致;要保持唤醒和阻塞的一致性,需要对线程的属性做一定设定,保证任务不会被各种信号打断;唤醒和阻塞需要做内核任务的队列管理,记录调用者与用户态唤醒线程的关系,保证唤醒和阻塞的一致性;为了保证调用的效率和安全性,使用读写锁以及多队列多线程机制;使用参数封装和解封装的形式传递调用参数。

实施例2

图2是本发明实施例中内核态调用用户态函数方法的流程示意图,如图2所示,本发明内核态调用用户态函数的方法包括如下步骤:

S1、在内核态实现用户态原函数的封装函数,对于每一个需要被调用的用户态函数,首先需要在内核态实现一个与用户态函数相同原型的封装函数,在该封装函数中把该用户态函数的名称作为一个参数,该封装函数的参数还应该包括上层调用函数所传递参数,为了用户态线程能够区分不同的内核态线程的调用,该封装函数的参数还应该加入内核态线程的id信息,并将该封装函数的参数保存到调用队列。调用队列以一个链表数据结构的形式保存在内核态,内核态线程在封装这些参数之前需要分配一个调用队列的节点保存这些参数,并在该调用队列节点加入时增加互斥锁操作,避免出现链表异常。本方案中存在多个内核态线程同时调用该用户态函数的可能,而每个内核态线程的调用都会保存一套自己的参数结构。

S2、在内核态实现的封装函数中调用schedule_timeout_uninterruptible来完成内核态线程的阻塞,在用户态线程返回之前,这个内核态线程一直保持阻塞状态。

S3、实现内核态ioctl函数,这是用户态线程与内核态线程通信的核心接口,用户态函数获取调用参数和返回结果都通过ioctl函数实现。

首先需要在内核态的proc文件系统中创建一个文件用于ioctl,只需要实现该文件ioctl函数就可以,read函数和write函数不需要实现,用户态线程通过打开该proc文件系统文件,然后使用系统调用ioctl将用户态线程阻塞以等待调用,请求调用的ioctl命令字与返回值的命令字要区分开。

当ioctl函数检查调用队列为空时,用户态线程通过内核态ioctl调用schedule_timeout_uninterruptible函数阻塞在内核态,当检查到队列内容不为空时,就读取队列消息并返回用户态解析消息内容,通过函数名查找并调用用户态函数。当被调用用户态函数返回后,用户态线程要解析返回参数和返回值,并进行消息封装,并封装请求调用时返回的内核态线程id,然后通过返回值的命令字调用ioctl,返回内核态。允许同时运行多个用户态线程读取内核态的调用队列以提高调用效率。多个用户态线程并发执行ioctl陷入内核态,检查调用队列是否为空,当调用队列有多个调用请求时,多个用户态线程可以同时获取到调用请求。当调用队列已经被读取完,剩余的未获取到调用请求的用户态线程会阻塞等待。多个用户态线程同时读取调用队列需要互斥锁保护列表。

S4、当内核态的ioctl函数接收到用户态函数返回的执行结果后,首先从调用队列查找与返回的内核态线程id相同的链表节点,然后拷贝返回结果到链表的返回值数据结构中,完成后ioctl函数通过队列记录的线程id唤醒处于阻塞状态的内核态线程,完成后ioctl返回到用户态,用户态线程继续执行下一次调用请求。

S5、被唤醒的内核态线程继续读取链表返回值数据结构,分析处理返回值和返回参数,把参数内容和返回值解析后填充到上层调用的结构中,并把自身分配的链表节点删除,释放内存,然后返回上层调用过程。

步骤S2和S4实现了内核态调用的核心处理,核心思想就是把函数的调用转换为对调用者的阻塞和唤醒,这样内核调用者可以无感知地调用用户态函数,实现函数调用的透明性,整个过程有两次用户态到内核态的ioctl过程,分别完成读取调用参数和返回执行结果。

步骤S2和S3的线程阻塞必须使用uninterruptible模式,不能使用interruptible,保证内核态线程和用户态线程不能被任意信号打断。防止出现不确定的调用参数。

实施例3

以下以一个具体实例演示本发明方案的实施过程,如图3和图4所示,本实例中:内核态线程kprocB调用用户态函数funA,该用户态函数funA的实现在用户态线程procA,用户态线程内的procA函数原型为int procA(int arg),实施过程包括:

S11、在内核态实现用户态函数funA的封装函数kfunA(该函数为封装函数,原型与用户态线程procA相同),封装函数kfunA的内部实现是把参数arg和procA函数名以及kprocB的线程id放到一个数据结构里;

S12、内核态线程kprocB调用内核态封装函数kfunA,完成步骤1的参数封装,kfunA完成参数封装后把参数数据结构加入一个调用队列(该调用队列是一个链表结构的全局队列),并把内核态线程kprocB设置为阻塞状态TASK_UNINTERRUPTIBLE。调用队列中各节点保存的参数包括:用户态函数funA的函数名、arg参数值、内核态线程kprocB的id和返回值空间;

S13、用户态线程procA通过ioctl访问内核态,读取步骤S12的调用队列,解析调用队列中节点的参数,找到要调用用户态函数标识及参数,在本示例中,找到用户态函数funA的函数名以及arg参数,并调用funA,执行结束后,再通过ioctl函数把执行结果返回给内核态ioctl。

另外,如图所示线程procA和线程procA是两个不同被调用函数的用户态线程,可以允许同时运行多个用户态线程读取内核态的调用队列以提高调用效率。

S14、内核态ioctl接收到用户态线程procA返回的执行结果后,首先根据返回的内核态线程id查找到调用队列对应的节点(返回的内核态线程id与链表节点的线程id一致),然后把返回的参数加入到本链表节点的返回值结构中,并唤醒该内核线程。在本示例中,把procA函数的返回值加入到链表节点,然后唤醒该内核态线程kprocB。

S15、内核态线程kprocB被唤醒后,封装函数kfunA继续执行并解析调用队列节点的返回值结构,找到返回值和返回参数,删除本链表节点,然后将返回的执行结果给调用该内核态线程kprocB的上层调用函数。

本领域的技术人员容易理解,以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号