c51如何定义再入函数

c51如何定义再入函数,第1张

重入函数,又叫再入函数,是一种可以在函数体内不直接或间接调用其自身的一种函数。再入函数可被递归调用,无论何时,包括中断函数在内的任何函数都可以调入。再入函数在C51编译时使用的是模拟栈。

再入函数,每次被调用时候使用一个独立堆栈,比如一个f(),刚运行时使用N字节堆栈,运行过程中调用它自身,被调用的f()会另外开辟N字节堆栈,两个f()数据不会出现冲突。但单片机资源有限,调用太深会内存溢出;

函数说明: 函数名(形式参数表) reentrant

例子:void TCPSendTask(void xdata ppdata) REENTRANT _MUL;

注意事项:

1、再入函数不能传递bit类型参数。

2、与PL/M51兼容的函数不能具有reentrant,这样也不能调用再入函数。

3、在编译时:再入函数建立的是模拟堆栈区,small模式下模拟堆栈区位于idata区,compact模式下模拟堆栈区位于pdata区,large模式下模拟堆栈区位于xdata区

4、在同一程序中可以定义和使用不同存储器模式的再入函数,任意模式的再入函数不能调用不同存储器模式的再入函数,但可以调用普通函数。

5、实际参数可以传递给间接调用的再入函数。无再入属性的间接调用函数不能包含调用参数;

代码重入就是内存中同样的两段可执行代码。不会有什么后果,只是会浪费资源。在以前大量使用静态库的时代,代码重入的就是两个或多个程序都要用到同一个功能模块,它们都需要在内存有该模块的一个copy,而不能实现共享——多浪费。

递归不是"代码重入",递归程序一层层调用来调用去,用得都是自己的那段代码,只是它不得不为此设置一个大大的栈空间用于保存返回地址、中间结果,因此也浪费资源,但和代码重入不是一回事。

动态链接库的提出正是为了减少代码重入,这样多个程序可以在内存中只有一个功能模块的copy时,对它进行共享。因此如果程序都用动态链接库,可使用重入度达到最小。

虚拟机完全就像真正的计算机那样进行工作,例如你可以安装 *** 作系统、安装应用程序、访问网络资源等等。对于你而言,它只是运行在你物理计算机上的一个应用程序,但是对于在虚拟机中运行的应用程序而言,它就是一台真正计算机。因此,当你在虚拟机中进行软件评测时,可能系统一样会崩溃;但是,崩溃的只是虚拟机上的 *** 作系统,而不是物理计算机上的 *** 作系统,并且,使用虚拟机的“Undo”(恢复)功能,你可以马上恢复虚拟机到安装软件之前的状态。有朋友在运行虚拟机时候出现死机的现象,强制关闭之后,原来的没有正常关闭的虚拟系统不能正常启动,什么原因能造成虚拟机崩溃呢?针对这种现象。下面我们就来学习下。 解决办法: 到相应的虚拟机目录下删除%虚拟机名字%vmxlck文件夹或者其中的文件即可 我们打开任务管理器,会发现vmwareexe和vmware-vmxexe两个重要的进程。其中vmware-vmxexe是主程序,虚拟机在这个进程下运行;VMwareexe是外壳程序,负责显示vmware-vmxexe中运行的虚拟系统并解释传送各种命令和 *** 作,是我们最常用的 VMware用户界面,该程序可重入即同时打开多个。 因为VMware Workstation是可重入的,为了避免同一个虚拟系统同时被多个VMwareexe打开 *** 作,造成错误,所以每个VMware打开相应的虚拟机选项卡时都会先检查该虚拟机根目录下是否有vmxlck的文件夹并验证其中的文件,如果该文件中包含合法生成的uuid(通用唯一识别码),那么将无法打开该虚拟机的选项卡,并出现下面的错误提示: Take Ownership之后会出现以下提示: 如果没有相应的合法文件,就会在该虚拟机根目录下生成vmxlck文件夹,并在该文件夹下生成一个包含uuid的lck文件,打开虚拟机选项卡,并从主程序接收显示信息。 这个lck文件可以用记事本编辑。里面是uuid={一串字母数字},uuid是通用唯一识别码 (Universally Unique Identifier),它的特点就是唯一性。为的是同时只有一个vmwareexe能接受主程序的显示,并对虚拟机 *** 作。lck是lock的缩写,即对请求资源的锁定。 VMware 虚拟机在运行时会在相应的虚拟机目录下生成三个文件vmxlck,vmdklck,vmemlck文件夹,里面包含以lck命名的文件。 其中的vmxlck是伴随vmwareexe中选项卡的打开时生成的;另外两个是关于虚拟磁盘和内存的使用的,它们伴随着虚拟系统的运行而产生。如果关闭VMwareexe让虚拟机在后台运行,vmxlck文件夹会消失另外两个则不会。

根据摩尔定律,芯片上晶体管的数目每隔18~24个月就会翻一番。如同在过去40年里一样,这个定律现在还是正确的,但是在性能上却并不再呈现一个线性增强的现象。以前,芯片制造商通过提高处理器时钟速度使芯片性能翻番――从100MHz到200MHz,直至近来达到吉赫兹。

然而如今,因为能量消耗和热量发散的限制,通过增加时钟速度来提高性能已经不再可行。芯片制造商开始转向全新的芯片结构,即一个芯片上有多个处理器核。相对于单核,采用多核处理器的程序员们可以完成更多全局工作。然而,要充分利用多核处理器的优点,程序员们必须重新考虑他们该如何开发应用程序。有些程序员,希望在终端客户将他们的电脑简单升级到快速处理器的时候,就能立即获得软件应用程序性能的增强。按照微软的软件工程师HerbSutter的话来说,对这些程序员“已经没有免费的午餐”。简而言之,如今程序员们应当致力于可持续的性能改进。

提高处理器时钟速度,则顺序程序的性能改进;为电脑升级一个更快速的CPU,意味着每一条独立指令的运行速度都会加快。要想使用多核系统以继续提高性能,开发者需要设计应用程序,为每个核分配工作――本质上即是开发一个并行应用程序来取代顺序应用程序。

幸运的是,NI LabVIEW软件非常适合于工程师和科学家们充分利用多核芯片的处理能力,主要原因有下面三个。

1LabVIEW是一种图形化数据流编程语言

开发者可在LabVIEW中简便地实现并行任务,使得开发新的应用程序并更改现存的应用程序以利用多核处理器的优点成为可能。LabVIEW从50版本开始就是多线程的,而现在的85版本更引进了新的功能,以利用多核处理器的优点。

2LabVIEW将多核性能引进嵌入式实时硬件中

LabVIEW 85将桌面 *** 作系统(例如Windows和Linux)的自动多任务处理功能――也就是对称多处理技术(SMP)――引入确定性的实时系统。

3LabVIEW处于“Multicore―Ready”软件层次的顶层

LabVIEW应用程序的每一层(例如:LabVIEW应用程序代码、低层函数、I/O驱动),都是线程安全的,它们可以利用多核处理器的优点。

LabVIEW是一种图形化数据流编程语言

使用LabVIEW开发应用程序的最主要好处就是其直观的、图形化的语言。在LabVIEW中,解决工程问题就如同在纸上画方块图一样简单。由于LabVIEW能够并行表达和执行任务,所以现代的多核处理器使得LabVIEW成为编程工具的一个更有利的选择。

LabVIEW的数据流特性意味着不论何时,只要代码在线上有个分支或在方块图上有个并行序列,潜在的LabVIEW编译器就会尝试并行执行代码。用计算机科学的专有名词来说,这就是“隐并行”,因为你并不需要为了并行执行程序而明确编写代码,LabVIEW的图形化语言将自行实现一定程度的并行性。

从单核到双核计算机,理论上的优势是性能的双倍改进。但是,如何逼近该极限,则与你能多大程度上并行执行程序有关。LabVIEW程序员自然是并行地编写其算法。在普通LabVIEW应用程序的初始基准下,若不考虑多核编程技术,不改变代码,则其性能能够提高15%~20%。

图1是一个简单的应用例子:LabVIEW代码的一个分支用于两个分析任务――滤波 *** 作和快速傅里叶变换(FFT)――在双核机器上并行执行。因为两个任务计算量都很大,所以采用双核执行,相对于单核的效率改进是1省略/multicore上找到所有这些优化方案的例子。

LablVEW为实时嵌入式硬件引入多核性能

一直以来,工程师们使用的工具都不能利用嵌入式多核系统的特性进行最优化的并行式编程。LabVIEW 85软件为确定性实时系统引入了台式机的自动多线程调度器(也被称为SMP)。LabVIEW 85的实时模块加入了一流的多核系统支持,它有着如下特性:

在嵌入式实时系统中,在多个核上自动进行负载均衡。

对于时间关键(time-critical)的代码,可以将定时循环分配到指定的处理器上将定时循环结构中的关键代码与应用程序中的其他代码隔离开。

利用Real-Time ExecutionTrace Toolkit 20工具,用户可以方便地对VI程序运行过程中的线程和处理器核进行图形化的表示,以便更好地调整实时系统,进而获得最佳性能。

LabVIEW处于“Multicore-Ready”软件层次的顶层

Intel公司定义了用户需要评估的四层软件层次来确定多核系统的可用程度。这四层软件层次分别是 *** 作系统、设备驱动、应用程序库和开发工具。如果所用的应用程序库和设备驱动不是为多核而设计的,或者 *** 作系统不能够在多个核上进行负载均衡,那么并行化程序在多核系统上是不能够运行得更快的。

设备驱动软件层的一个例子就是NI-DAQmx驱动软件。传统的NI-DAQ是“线程安全”的,也就是说在一个NI-DAQ函数被调用时,整个程序库会阻塞其他调用的线程。从第一感觉看来,这是非常有逻辑性的,因为NI-DAQ是用来控制硬件的,而硬件通常被认为是单一的源。NI-DAQmx这款重新设计过的新型DAQ驱动程序是可重入的,这意味着多个DAQ任务可以以一种真正并行的方式运行而不再需要阻塞线程。利用这种方法,驱动程序可以使用户的应用程序在同一块电路板上并行地运行多个任务,诸如独立的模拟和数字输入/输出等。

LabVIEW――理想的并行化编程语言

大多数用户将会看到多核系统所带来的好处,它利用改进的性能同时运行多个应用程序(电子邮件、视频、文字处理等),这也被称为多任务。但是,对于试图对单一应用程序进行优化的开发者而言,它所能提供的好处是有限的。

工程师和科学家们正在为测试需要或者在控制应用中改进的闭环速率而寻找更快的测量仪器。他们需要考虑如何实现并行的应用。LabVIEW软件就是这样一种用户可以借助于它所提供的软件环境来实现并行应用的有效工具。语言的数据流特性、LabVIEW Real-Time工具对嵌入式平台开发的多核支持,以及自上而下的为多核而设计的软件层,使得LabVIEW软件成为进行并行化编程的首选。

可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏。可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失。

可重入函数使用的变量有两种情况:

1使用局部变量,变量保存在CPU寄存器中或者堆栈中;

2使用全局变量,但是这时候要注意保护全局变量(防止任务中断后被其它任务改变变量)。

1

2

3

4

5

void strcpy(dest,src)

while( dest++ = src ++){;}

dest = NUL;

分析:上面的函数用于字符串复制,而参数是存放在堆栈中的,故而改函数可以被多任务调用,而不必担心各个任务调用期间会互相破坏对方的指针。

基本上下面的函数都是不可重入的:

1函数内使用了静态的数据。

2函数内使用了malloc()或者free()函数的。

3函数内调用了标准的I/O函数的。

1

2

3

4

5

6

7

int temp;

void swap(int ex1,int ex2)

temp = ex1;//(1)

ex1 = ex2;

ex2 = temp;

分析:该函数中的全局变量temp是的函数变成了一个不可重入的函数,因为在多任务系统中,假如在任务1中调用swap函数,而程序执行到(1)处时被中断,进而执行其它的任务2,而刚好任务2也调用了swap函数,则temp里存的值则会被任务2改变。从而回到任务1被中断处继续执行的时候,temp里存的值已经不再是原来存的temp值了,进而产生了错误。

常用的可重入函数的方法有:

1不要使用全局变量,防止别的代码覆盖这些变量的值。

2调用这类函数之前先关掉中断,调用完之后马上打开中断。防止函数执行期间被中断进入别的任务执行。

3使用信号量(互斥条件)。

总之:要保证中断是安全的

用在只能单线程处理的地方呗,一般来说,如果一个方法被多个线程调用,方法里有修改类变量就需要锁了,因为在线程运行时,类变量被拷贝到线程专用的缓存,然后再拷贝回程序内存,如果同时有多个线程做上述动作,最后一个线程改变后的值就会覆盖其他线程做的修改。

以上就是关于c51如何定义再入函数全部的内容,包括:c51如何定义再入函数、请教各位高手,什么叫“代码重入”、如何解决虚拟机不能启动的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9831556.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存