皮皮网

【java源码查看器】【美到家1.5源码】【活码网站源码】require 源码

来源:服务号源码 时间:2024-11-15 01:38:52

1.Lua5.4 源码剖析——虚拟机2 之 闭包与UpValue
2.require的用法?
3.require和include的区别

require 源码

Lua5.4 源码剖析——虚拟机2 之 闭包与UpValue

       故事将由我们拥有了一段 Lua 代码开始,我们先用 Lua 语言写一段简单的打印一加一计算结果的 Lua 代码,并把代码保存在 luatest.lua 文件中:

       可执行的一个 Lua 文件或者一份单独的文本形式 Lua 代码,在 Lua 源码中叫做 "Chunk"。无论我们通过什么形式去执行,或者用什么编辑器去执行,java源码查看器最终为了先载入这段 Lua 的 Chunk 到内存中,无外乎会归结到以下两种方式:1)Lua 文件的载入:require 函数 或 loadfile 函数;2)Lua 文本代码块的载入:load 函数;这两种方式最终都会来到下面源码《lparse.c》luaY_parser 函数。该函数是解析器的入口函数,负责完成代码解析工作,最终会创建并返回一个 Lua 闭包(LClosure),见下图的红框部分:

       另外,上图中间有一行代码最终会调用到 statement 函数,statement 函数是 Chunk 解析的核心函数,它会一个一个字符地处理我们编写的 Lua 代码,完成词法分析和语法分析工作,想要了解字符处理整个状态流程的可以自行研读该部分源码,见源码《lparse.c》statement 函数部分代码:

       完成了解析工作之后,luaY_parser 函数会把解析的所有成果放到 Lua 闭包(LClosure)对象之中,这些存储的美到家1.5源码内容能保证后续执行器能正常执行 Lua 闭包对应的代码。

       Lua 闭包由 Proto(也叫函数原型)与 UpValue(也叫上值)构成,见源码《lobject.h》LClosure 定义,我们下面将进行详细的讲解:

       UpValue 是 Lua 闭包数据相关的,在 Lua 的函数调用中,根据数据的作用范围可以把数据分为两种类型:1)内部数据:函数内部自己定义的数据,或者通过函数参数的形式传入的数据(在 Lua 中通过参数传入的数据本质上也是先赋值给一个局部变量);2)外部数据:在函数的更外层进行定义,脱离了该函数后仍然有效的数据;外部数据在我们的 Lua 闭包中就是 UpValue,也叫上值。

       既然 Lua 支持函数嵌套,也知道了 UpValue 本质就是上层函数的内部数据。那么 UpValue 有必要存储于 Lua 闭包(LClosure)结构体当中吗?是为了性能考虑而做的一层指针引用缓存吗?回答:并不是基于性能的考虑,因为在实际的 Lua 运用场景中,函数嵌套的层数通常来说不会太多,个别函数多一层的查询访问判断不会带来过多的性能开销。需要在闭包当中存储 UpValue 主要原因是因为内存。Lua 作为一门精致小巧的脚本语言,设计初衷不希望占用过多的系统内存,它会尽量及时地清理内存中用不到的对象。在嵌套函数中,活码网站源码内层函数如果仍然有被引用处于有效状态,而外层函数已经没有被引用了已经无效了,此时 Lua 支持在保留内层函数的情况下,对外层函数进行清除,从而可以清理掉外层函数引用的非当前函数 UpValue 用途以外的大量数据内存。

       尽管外层函数被清除了,Lua 仍然可以保持内层函数用到的 UpValue 值的有效性。UpValue 如何能继续保持有效,我们在之前的基础教程《基本数据类型 之 Function》里面学习过,主要是因为 UpValue 有 open 与 close 两种状态,当外层函数被清除的时候,UpValue 会有一个由 open 状态切换到 close 状态的过程,会对数据进行一定的处理,感兴趣的同学可以回到前面复习一下。

       UpValue 有效性例子

       接下来我们举一个代码例子与一个图例,表现一下 UpValue 在退出外层函数后仍然生效的情况,看一下可以做什么样的功能需求,加深一下印象,请看代码与注释:

       上述代码在执行 OutFunc 函数后,皮皮炸金花源码外层的 globalFunc 函数变量完成了赋值,每次对它进行调用,都将可以对它引用的 UpValue 值即 outUpValue 变量进行正常加 1。

       函数的内部数据属于函数自身的内容,外部其它函数无法通过直接的方式访问其它函数的内部数据。函数自身的东西会存在于 LClosure 结构体的 Proto*p 字段中。Proto 全称 "Function Prototypes",通常也可以叫做 "函数原型",我们来看一下它的定义,见源码《lobject.h》Proto 结构体:

       结构体字段比较多,我们先不细看,后面用到哪个字段会再进行补充说明。函数的内部数据分为常量与变量(即函数局部变量),分别对应上图的如下字段:

       1)常量:TValue* k 为指针指向常量数组;int sizek 为函数内部定义的常量个数,也即常量数组 k 的元素个数。

       2)局部变量:LocVar* locvars 为指针指向局部变量数组;int sizelocvars 为函数定义的局部变量个数,也即局部变量数组 locvars 的元素个数。

       UpValue 的描述信息会存储在 Proto 结构体中的 Upvaldesc* upvalues 字段,解析器解析 Lua 代码的老师机导航源码时候会生成这个 UpValue 描述信息,并用于生成指令,而执行器运行的时候可以通过该描述信息方便快速地构建出真正的 UpValue 数组。

       至此,我们知道了函数拥有 UpValue,有常量,有局部变量。外部数据 UpValue 也讲完,内部数据也讲完。接下来,我们开始学习函数运行的逻辑指令相关内容。

       函数逻辑指令存储于函数原型 Proto 结构体中,这些函数逻辑是由一行行的 Lua 代码构成的,代码会被解析器翻译成 Lua 虚拟机能识别的指令,我们把这些指令称为 "OpCode",也叫 "操作码"。Proto 结构体存储 OpCode 使用的是下图中红框部分字段,见源码《lobject.h》Proto 结构体:

       至此,我们可以简单提前说一下 Lua 虚拟机的功能了,本质上来看,Lua 虚拟机的工作,就是为当前函数(或者当前一段 OpCode 数组)准备好数据,然后有序执行 OpCode 指令。

       对 OpCode 有了一定的认识了,接下来我们要补充一个 OpCode 相关的 Lua 闭包相关的内容,就是 Lua 闭包的运行环境。

       一个 Lua 文件在载入的时候会先创建出一个最顶层(Top level)的 Lua 闭包,该闭包默认带有一个 UpValue,这个 UpValue 的变量名为 "_ENV",它指向 Lua 虚拟机的全局变量表,即_G 表,可以理解为_G 表即为当前 Lua 文件中代码的运行环境 (env)。事实上,每一个 Lua 闭包它们第一个 UpValue 值都是_ENV。

       ENV 的定义在我们之前提到的解析器相关函数 mainfunc 中,见源码《lparser.c》:

       如果想要设置这个载入后的初始运行环境不使用默认的 _G 表,除了直接在该文件代码中重新赋值_ENV 变量这种粗暴且不推荐的方式以外,通常是通过我们前面提到的加载 Lua 文件函数或加载 Lua 字符串代码函数传入 env 参数(Table 类型),就可以用自定义的 Table 作为当前 Lua 闭包的全局变量环境了,env 参数为上面两个函数的最末尾一个参数,'[' 与 ']' 字符中的内容表示参数可选,函数的定义摘自 Lua5.4 官网文档:

       所以我们可以在 Lua 代码通过 _ENV 访问当前环境:

       在 Lua 的旧版本中,变量的查询最多会分为 3 步:1)先从函数局部变量中进行查找;2)找不到的话就从 UpValue 中查找;3)还找不到就从全局环境默认 _G 表查找。而在 Lua5.4 中,把 UpValue 与全局 _G 表的查询统一为 UpValue 查询,并把一些操作判断提前到了解析器解析阶段进行,例如函数内部使用的某个 UpVaue 变量在代码解析的时候就可以通过 UpValue 描述信息知道存储于 Lua 闭包 upvals 数组的哪个下标位置,在执行器运行的时候只需要直接在数组拿取对应下标的这个 UpValue 数据即可。

       从 OpCode 的层面来看,Lua 除了支持通过一个 UpValue 数组下标访问一个 UpValue 变量,在把 _G 表合并到 UpValue 之后,Lua 为此实现了通过一个字符串 key 值从某个 Table 类型的 UpValue 中查询变量的操作。

       至此,我们了解了 Lua 闭包的结构与运行环境,以及 OpCode 的基本概念。接下来,我们将深入学习 OpCode,掌握 OpCode 就掌握了整个 Lua 虚拟机数据与逻辑的流向。

require的用法?

       require的用法

       在编程中,require是一个常见的函数或方法,主要用于导入或加载其他模块、库或文件。其具体用法根据不同的编程语言和上下文环境有所不同。以下是关于require用法的一般解释:

       基本用法

       1. 作为模块导入: 在许多编程语言中,如JavaScript、Python等,require通常用于导入模块。这意味着你可以使用其他开发者编写的代码,而不必重新编写所有功能。通过require,你可以将其他文件或库中的功能集成到你的项目中。

       2. 指定路径: 使用require时,通常需要指定要导入模块的路径。这个路径可以是相对路径或绝对路径,具体取决于你的项目结构和需求。

       3. 返回值处理: require通常会返回所请求模块的导出内容。这意味着你可以在你的代码中直接使用这些导出的函数、变量或类等。

       详细解释

       模块导入的概念:

       在模块化编程中,代码被划分为独立的模块,每个模块都有其特定的功能。通过require这样的函数,可以将其他模块的功能集成到当前文件中,从而实现代码的重用和模块化。这不仅提高了代码的可维护性,还使得不同的开发者可以协同工作,共同开发复杂的项目。

       路径指定的重要性:

       在指定模块路径时,需要确保路径的正确性。如果路径错误,可能会导致模块加载失败,进而影响项目的运行。相对路径和绝对路径的选择取决于项目的结构。在小型项目中,相对路径更为常见;而在大型项目中,为了代码的清晰和可维护性,可能会使用绝对路径。

       返回值处理的方式:

       不同的模块可能会有不同的导出内容,因此在使用require导入模块后,需要查看模块的文档或源代码,了解导出的内容和如何正确使用这些导出内容。通常,这些导出内容可以直接在当前文件中使用,从而实现模块间的交互和功能的扩展。

       总之,require的用法是模块化编程中的基础操作之一,对于提高代码的重用性和可维护性至关重要。掌握其用法并根据项目需求正确应用,是编程过程中的重要技能之一。

require和include的区别

       nclude与require的区别

       PHP中的require,require_once,include,include_once的区别

        “include”与“required”的作用都是相同的,唯一不同的是PHP在遇到“include”命令时,它就必须重新解释一次。如果在同一个PHP网页中出现次“include”命令时,它便会被重新解释次。不过当PHP遇到“require”命令时,不管它在同一个PHP网页中出现过几次,PHP只会解释一次而已。

        “require”的工作方式是为了让PHP程序得到更高的效率,所以当它在同一个PHP网页中解释过一次后,第二次出现便不会再解释,这是它的优点。不过严格来说,这也是它的唯一 的缺点,因为它不会重复解释引入的文件,所以当PHP网页中使用循环或条件语句来引入文件时,“require”则不会做任何的改变。当有类似这样的情形时,就必须使用“include”命令来引入 文件了。

        当PHP遇到一个利用“include”方式引入的文件,它就会解释一次;遇到第二次时,PHP还是会重新解释一次。与“require”相比,“include”的执行效率则会下降许多;而且当引入文件中包含了用户自定义的函数时,PHP在解释的过程中会发生函数重复定义的问题。不过“include”也不是没有优点的,因为在PHP网页中,它会每遇到一次“include”命令就会重复解释一次,所以非常适合使用在循环或条件判断的语句里。

        “include_once()”函数和“require_once()” 函数功能完全相同,会先检查目标档案的内容是不是在之前就已经导入过了,如果是的话,便不会再次重复导入同样的内容。

       çŽ°åœ¨æ¥è¯´include和require的区别:

       require()函数包含进来的内容被当成当前文件的一个组成部分,所以当包含进来的文件有语法错误或者文件不存在的时候,那当前文件的PHP脚本都不再执行. include()函数相当于指定这个文件的路径,当被包含的文件有错时,不会影响到本身的程序运行.

       include函数可以进行判断是否包含,而require则是不管任何情况都包含进来.所以这点值得注意!

       å»ºè®®å¤§å®¶åœ¨åŒ…含动态文件,也就是有变量,函数,已经类的时候用include.不过前段时间有人在分析两个函数的执行效率.这个我没自己测试过,等亲自测试了再进行补充

       www.w3school.com

       é€šè¿‡ include() 或 require() 函数,您可以在服务器执行 PHP 文件之前在该文件中插入一个文件的内容。除了它们处理错误的方式不同之外,这两个函数在其他方面都是相同的。include() 函数会生成一个警告(但是脚本会继续执行),而 require() 函数会生成一个致命错误(fatal error)(在错误发生后脚本会停止执行)。

       è¯¦ç»†ä»‹ç»

       äºŽPHP具有快速、可靠、跨平台应用、源代码开放等特点,使得PHP成为最受欢迎的服务器端Script语言之一。我根据自己在工作中体会到的,向大家介绍PHP使用的心得,希望对大家有所帮助。

        利用PHP的Include files维护你的网站

        不管你所开发的网站的规模是大是小,你都应该要认识到重复使用程序代码的重要性,不论你重复使用的是 PHP 程序或者是 HTML 原始码。举个例子来说,网站页尾的版权宣告至少每年都得修改一次,如果你的网站有许多个页面,该怎么办呢?动手一个一个修改这些页面肯定是一件头痛的事 情。通过 PHP 我们可以用几个不同的方式来重复使用程序代码。要使用哪些函数端视你要重复使用的是怎样的内容而定。

        这些主要的函数包括:

        * include() 与 include_once()

        * require() 与 require_once()

        1.include() 函数会将指定的档案读入并且执行里面的程序。

        例如:include('/home/me/myfile');

        被导入的档案中的程序代码都会被执行,而且这些程序在执行的时候会拥有和源文件中呼叫到 include() 函数的位置相同的变量范围(variable scope)。你可以导入同一个服务器中的静态档案,甚至可以通过合并使用 include() 与 fopen() 函数来导入其它服务器上面的档案。

        2.include_once()函数的作用和 include() 是几乎相同的

        唯一的差别在于 include_once() 函数会先检查要导入的档案是不是已经在该程序中的其它地方被导入过了,如果有的话就不会再次重复导入该档案(这项功能有时候是很重要的,比方说要导入的档 案里面宣告了一些你自行定义好的函数,那么如果在同一个程序重复导入这个档案,在第二次导入的时候便会发生错误讯息,因为 PHP 不允许相同名称的函数被重复宣告第二次)。

        3.require()函数会将目标档案的内容读入,并且把自己本身代换成这些读入的内容。

        这个读入并且代换的动作是在 PHP 引擎编译你的程序代码的时候发生的,而不是发生在 PHP 引擎开始执行编译好的程序代码的时候(PHP 3.0 引擎的工作方式是编译一行执行一行,但是到了 PHP 4.0 就有所改变了,PHP 4.0 是先把整个程序代码全部编译完成后,再将这些编译好的程序代码一次执行完毕,在编译的过程中不会执行任何程序代码)。require() 通常来导入静态的内容,而 include() 则适合用来导入动态的程序代码。

        4.如同 include_once()函数,require_once() 函数会先检查目标档案的内容是不是在之前就已经导入过了,如果是的话,便不会再次重复导入同样的内容。

        我个人习惯使用 require() 函数来导入版权宣告(copyrights),静态文字或其它本身不含有变量,

       æˆ–者本身需要倚赖其它执行过的程序才能正确执行的程序代码。例如:

        <HTML>

        <HEAD><TITLE>网页标题</TITLE></HEAD> <BODY> [一堆内容] <?

        // 导入版权宣告文字

        require('/home/me/mycopyright'); ?>

        </BODY></HTML>

        另一方面,我通常在程序的开头使用 include() 函数来导入一些函式库或者类似的程序代码: <?

        // 导入我的函式库

        include('/home/me/myfunctions');

        // 利用之前导入的函式库里面定义好的 PHP 函数执行一些功能?> <HTML>

        <HEAD><TITLE>网页标题</TITLE></HEAD> <BODY> [一堆内容] </BODY> </HTML>

        接下来你可能会问这第一个挺符合逻辑的问题:「这些被导入的档案要放在哪儿呢?」简短的答案是:「放在服务器档案系统里的任何地方都行。」然而,要留意的 是如果被导入的档案除了单纯的程序代码片段以外还包含了一些敏感资料,例如连结数据库系统要用到的帐号和密码,那么建议你不要把这些档案放在 Web 服务器的文件根目录之下,因为那样的话他人便可以很容易地窃取到这些资料了。

        你可以将这些被包含的档案放在系统的任何一个目录里面,唯一的条件是 PHP 本身用来执行的身分(www,nobody 或者其它身分)必须要有足够的权限能够读取这些档案就可以了。这些档案的扩展名也可以任意取,甚至没有附档名也无所谓。

        善用include()和 require()来将网站里面经常需要变动的共享内容做合理的分割,在更新网站内容的时候将会容易进行得多。

        利用PHP来维护档案系统

        PHP 提供了很多与档案系统相关的函数,让我们不仅可以开启档案,还能够显示目录的内容,搬移档案的位置以及其它更多功能。有的朋友甚至写了能够通过浏览器来管理档案内容的 PHP 程序。

        在开始介绍 PHP 的档案系统相关功能之前,我们要先理清一件事情:在 Windows操作系统里

       é¢ï¼Œæ¡£æ¡ˆè·¯å¾„可以使用斜线(/)或者反斜线(\)来表示,但是在其它操作系统里面我们只会使用到斜线。为了保持统一性,下面的例 子里面的档案路径都是使用斜线。

        下面的例子程序我将教大家基本的目录内容显示功能,每个步骤都有批注,请直接阅读。

        <? /* $dir_name 这个变量的值是你想要读取的目录的完整路径 */ $dir_name = "/home/me/";

        /* opendir()函数会开启某个目录,并且传回一个参考值(handle)让我们可以用来在程序中参照到该目录 */

        $dir = opendir($dir_name);

        /* 开始建立一个字符串,这个字符串包含了 HTML 的列表卷标,用来显示目录中的文件名称。 */

        $file_list = "<ul>";

        /* 使用一个 while 循环叙述将前面开启的目录中的档案全部读取一遍。如果读取到的档名不是「.」或者「..」,就把该档名写入前面提到的字符串里面去。 */ while ($file_name = readdir($dir)) {

        if (($file_name != ".") && ($file_name != "..")) { $file_list .= "<li>$file_name"; } }

        /* 替 HTML 列表卷标加上结尾 */ $file_list .= "</ul>";

        /* 关闭之前开启的目录并且结束这段 PHP 程序 */ closedir($dir); ?>

        <!-- HTML原始码从这里开始 --> <HTML> <HEAD>

        </HEAD> <BODY>

        <!-- 使用 PHP 程序来将我们所读取的目录名称显示在页面上 --> <P>Files in: <? echo "$dir_name"; ?></p>

        <!-- 使用 PHP 程序将该目录中读取到的文件名显示在页面上 --> <? echo "$file_list"; ?> </BODY> </HTML>

        经过上面几步,你已经成功把某个目录中的文件名称显示在网页上了。但你要记住一点:要读取某个目录或者档案(读取档案内容的做法稍后会介绍),PHP 本身执行所用的身分必须至少拥有该目录或者档案的读取权限才行,否则系统会显示权限不足的错误讯息。

        下一个例子我将教大家如何复制一个档案:

        <? /* 变量$orginal储存源文件的完整路径,变量$copied储存复制过去的新档案的完整路径 */ $original = "/home/me/mydatabasedump"; $copied = "/archive/mydatabasedumo_";

        /* 呼叫 copy() 函数把档案从原始位置复制一份到新的位置去。如果无法复制,那么便终止程序的执行并且显示错误讯息。 */

        @copy($original, $copied) or die("无法复制档案。"); ?>

        上面的例子程序可以用来扩充成为一个档案备份系统程序。当这个程序执行的时候,它会将数据库的数据文件复制到其它目录下面做为备份之用。只要修改系统的排 程档案内容(crontab),我们便可以让这个程序自动在每天的固定时间执行一次,达到系统自动备份,不需要人工手动执行。

        如果你的系统上面有安装 Lynx 软件(Lynx 是一种纯文字的 Web 浏览器)的话,你可以在系统排程档案里面加入下面这笔记录来让系统在固定时间自动激活 Lynx 并且呼叫我们之前写好的 PHP 备份程序。当 Lynx 呼叫(浏览)我们的 PHP 程序的时候,该程序就会被执行,并且产生备份文件。下面这个例子教你如何在每天早晨五点钟执行我们的备份程序,并且在执行完以后自动将 Lynx 程序关闭:

       æ¥è‡ªï¼šé—«å¿—飞 > 《php》

       ä¸Šä¸€ç¯‡ï¼šphp 导出excel (html)

       ä¸‹ä¸€ç¯‡ï¼šWindows版本Apache+php的Xhprof应用——1

       è½¬è—åˆ°æˆ‘的图书馆

       çŒ®èŠ±(0)

       åˆ†äº«åˆ°å¾®ä¿¡

       åˆ†äº«ï¼š

       ç±»ä¼¼æ–‡ç« 

       æ›´å¤š

       PHP之PHP文件引用详解

       æ¯”较require(),include(),require_once(...

       php header函数使用要点

       include 和 include_once 有什么分别?r...

       åå¤©å­¦ä¼šPHP/第六天:PHP日期、引用

       PHP中file_exists与is_file,is_dir的区别....

       php 删除目录下N分钟前创建的所有文件

       è¿‡æ»¤å±é™©html代码的php自定义函数

       çƒ­é—¨æŽ¨å¹¿

       çŒœä½ å–œæ¬¢

       æœ€ç¾Žé›ªæ™¯æ¬£èµâ€”—你那里下雪了吗?

       å¹¿å‘Šè¥é”€å¦‚千军万马过独木桥 成功质...

       æ€ä¹¡æœ€æ˜¯è¯—行,给漂泊的游子

       ä¸ºäº†ä¸å¾—癌症,今天就要做

       åˆæ‹çš„地方

       ç§åƒå¾—起的抗衰老食物

       ä¸–界十大神秘"鬼船"有什么神秘故事

       å…¬å…±åŸºç¡€çŸ¥è¯†é¢˜

       è€å¸ˆå¸¸ç”¨æ•™å­¦ç½‘站账号密码大集合

       æ²¡æœ‰æ‰«æä»ªï¼Œæ€Žä¹ˆåŠžï¼Ÿç”¨ä»€ä¹ˆä»£æ›¿ï¼Ÿ

       å‘表评论:

       æ‚¨å¥½ï¼Œè¯· 登录 或者 注册 后再进行评论

       å…¶å®ƒå¸å·ç™»å½•ï¼š

       æœ€æ–°æ–‡ç« 

       æ·±å…¥ç†è§£php底层:php生命周期

       é€šè¿‡virtualbox最小化安装centos 6.3...

       debian下控制台和VI彩色显示&ssh

       Ubuntu下使用SVN

       sources镜像:sources.list.wheezy.de...

       nginx.conf 配置lnmp

       æ›´å¤š

       çƒ­é—¨æ–‡ç« 

       æ²¡è§è¿‡ç§èŠ±å·çš„做法吧&别错过学习的...

       â€œä¸­å›½å¼xx”让全世界哭笑不得

       å°å­¦è‹±è¯­è¾…导全套视频教程【珍藏版】

       æˆ‘ 家 宝 贝 女 儿[5]

       ã€ä»Žâ€œå°ä¸€â€œè‡³â€œé«˜ä¸‰â€œå„年级对孩子...

       çŒæ±¤åŒ…的皮怎么做又薄又透,能当气球吹

       èœ‚蜜加肉桂 ---- 令人叹为观止的神奇

       å¾·å›½åˆ¶é€ å’Œä¸­å›½åˆ¶é€ ç©¶ç«Ÿä¸åŒåœ¨å“ª

       å¥³äººçš„苦处:写的非常好——

       å¤–媒一则漫画揭示中美博弈(很喜感)

       ç™½é…’鲜姜云南白药粉治秃顶脱发效果神奇

       äººè¦é•¿ç”Ÿï¼Œè‚ è¦å¸¸æ¸…

       æ›´å¤š>>

       å…³é—­

       å…³é—­