国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【開發(fā)語言】PHP、Java、C語言的編譯執(zhí)行過程

13651657101 / 1495人閱讀

摘要:效率比較低,依賴解釋器,跨平臺性好語言編譯執(zhí)行過程下面都是鳥哥博客的內(nèi)容深入理解原理之引擎對這個文件進行詞法分析,語法分析,編譯成,然后執(zhí)行。

編譯型語言和解釋型語言

從PHP,Java和C語言的編譯執(zhí)行過程可以先解釋下編譯型語言和解釋型語言。

編譯型語言

程序在執(zhí)行之前需要一個專門的編譯過程,把程序編譯成為機器語言的文件,運行時不需要重新翻譯,直接使用編譯的結(jié)果就行了。程序執(zhí)行效率高,依賴編譯器,跨平臺性差些。如C、C++、Delphi等.

解釋型語言

程序不需要編譯,程序在運行時才翻譯成機器語言,每執(zhí)行一次都要翻譯一次。因此效率比較低。比如Basic語言,專門有一個解釋器能夠直接執(zhí)行Basic程序,每個語句都是執(zhí)行的時候才翻譯。(在運行程序的時候才翻譯,專門有一個解釋器去進行翻譯,每個語句都是執(zhí)行的時候才翻譯。效率比較低,依賴解釋器,跨平臺性好.)

PHP語言編譯執(zhí)行過程

下面都是鳥哥博客的內(nèi)容:深入理解PHP原理之opcode

hello.php
 

Zend引擎對這個hello.php文件進行詞法分析,語法分析,編譯成opcode,然后執(zhí)行opcode。這個Zend引擎是安裝PHP時安裝的??纯催@個文件是如何運行的,會經(jīng)過如下4個階段:

php hello.php

1.Scanning(Lexing) ,將PHP代碼轉(zhuǎn)換為語言片段(Tokens)
2.Parsing, 將Tokens轉(zhuǎn)換成簡單而有意義的表達式
3.Compilation, 將表達式編譯成Opocdes
4.Execution, 順次執(zhí)行Opcodes,每次一條,從而實現(xiàn)PHP腳本的功能。

在操作系統(tǒng)中執(zhí)行php命令也就是運行Zend引擎,然后Zend引擎拿到hello.php文件
那什么是Lexing? 學過編譯原理的同學都應(yīng)該對編譯原理中的詞法分析步驟有所了解,Lex就是一個詞法分析的依據(jù)表。 Zend/zend_language_scanner.c會根據(jù)Zend/zend_language_scanner.l(Lex文件),來輸入的 PHP代碼進行詞法分析,從而得到一個一個的“詞”,PHP4.2開始提供了一個函數(shù)叫token_get_all,這個函數(shù)就可以講一段PHP代碼 Scanning成Tokens;
如果用這個函數(shù)處理我們開頭提到的PHP代碼,將會得到如下結(jié)果:

Array
(
    [0] => Array
        (
           [0] => 367
           [1] =>  Array
        (
            [0] => 316
            [1] => echo
        )
    [2] => Array
        (
            [0] => 370
            [1] =>
        )
    [3] => Array
        (
            [0] => 315
            [1] => "Hello World"
        )
    [4] => ;
    [5] => Array
        (
            [0] => 370
            [1] =>
        )
    [6] => =
    [7] => Array
        (
            [0] => 370
            [1] =>
        )
    [8] => Array
        (
            [0] => 305
            [1] => 1
        )
    [9] => Array
        (
            [0] => 370
            [1] =>
        )
    [10] => +
    [11] => Array
        (
            [0] => 370
            [1] =>
        )
    [12] => Array
        (
            [0] => 305
            [1] => 1
        )
    [13] => ;
    [14] => Array
        (
            [0] => 370
            [1] =>
        )
    [15] => Array
        (
            [0] => 316
            [1] => echo
        )
    [16] => Array
        (
            [0] => 370
            [1] =>
        )
    [17] => ;
)

分析這個返回結(jié)果我們可以發(fā)現(xiàn),源碼中的字符串,字符,空格,都會原樣返回。每個源代碼中的字符,都會出現(xiàn)在相應(yīng)的順序處。而,其他的比如標簽,操作符,語句,都會被轉(zhuǎn)換成一個包含倆部分的Array: Token ID (也就是在Zend內(nèi)部的改Token的對應(yīng)碼,比如,T_ECHO,T_STRING),和源碼中的原來的內(nèi)容。
接下來,就是Parsing階段了,Parsing首先會丟棄Tokens Array中的多余的空格,然后將剩余的Tokens轉(zhuǎn)換成一個一個的簡單的表達式

> 1.echo a constant string
> 2.add two numbers together
> 3.store the result of the prior expression to a variable
> 4.echo a variable

1.Opcode數(shù)字的標識,指明了每個op_array的操作類型,比如add , echo
2.結(jié)果 存放Opcode結(jié)果
3.操作數(shù)1 給Opcode的操作數(shù)
4.操作數(shù)2
5.擴展值 1個整形用來區(qū)別被重載的操作符

然后就改Compilation階段了,它會把Tokens編譯成一個個op_array, 每個op_array包含如下5個部分
其中opcode數(shù)字標識符對應(yīng)zend_vm_opcode.h中的指令
參考laruence:opcode列表
比如,我們的PHP代碼會被Parsing成:

* ZEND_ECHO     "Hello World"
* ZEND_ADD       ~0 1 1
* ZEND_ASSIGN  !0 ~0
* ZEND_ECHO     !0
Java語言編譯執(zhí)行過程

JVM執(zhí)行程序的過程 :
I.加載.class文件
II.管理并分配內(nèi)存
III.執(zhí)行垃圾收集
JRE(java運行時環(huán)境)包含JVM的java程序的運行環(huán)境 [1]
JVM是Java程序運行的容器,但是他同時也是操作系統(tǒng)的一個進程,因此他也有他自己的運行的生命周期,也有自己的代碼和數(shù)據(jù)空間。
JVM在整個jdk中處于最底層,負責與操作系統(tǒng)的交互,用來屏蔽操作系統(tǒng)環(huán)境,提供一個完整的Java運行環(huán)境,因此也就虛擬計算機.操作系統(tǒng)裝入JVM是通過jdk中Java.exe來完成,通過下面4步來完成JVM環(huán)境。
1.創(chuàng)建JVM裝載環(huán)境和配置
2.裝載JVM.dll
3.初始化JVM.dll并掛接到JNIENV(JNI調(diào)用接口)實例
4.調(diào)用JNIEnv實例裝載并處理class類。

C語言編譯執(zhí)行過程

參考原文:C語言編譯過程詳解
平時開發(fā)中,大家可能一行代碼就編譯好了源代碼,如下:

$ gcc hello.c # 編譯
$ ./a.out # 執(zhí)行
hello world!

這個過程如此熟悉,以至于大家覺得編譯事件很簡單的事。事實真的如此嗎?我們來細看一下C語言的編譯過程到底是怎樣的。

上述gcc命令其實依次執(zhí)行了四步操作:
1.預(yù)處理(Preprocessing)
2.編譯(Compilation)
3.匯編(Assemble)
4.鏈接(Linking)

示例代碼:
// test.c
#include 
#include "mymath.h"http:// 自定義頭文件
int main(){
    int a = 2;
    int b = 3;
    int sum = add(a, b); 
    printf("a=%d, b=%d, a+b=%d
", a, b, sum);
}

頭文件定義:
// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int add(int a, int b);
int sum(int a, int b);
#endif

頭文件實現(xiàn):
// mymath.c
int add(int a, int b){
    return a+b;
}
int sub(int a, int b){
    return a-b;
}

預(yù)處理階段
預(yù)處理用于擴展源代碼,插入所有的#include命令指定的文件,并擴展所有用#define聲明指定的宏。預(yù)處理之后得到的仍然是文本文件,但文件體積會大很多。gcc的預(yù)處理是預(yù)處理器cpp來完成的,你可以通過如下命令對test.c進行預(yù)處理:

gcc -E -I./inc test.c -o test.i

或者直接調(diào)用cpp命令

cpp test.c -I./inc -o test.i

上述命令中-E是讓編譯器在預(yù)處理之后就退出,不進行后續(xù)編譯過程;-I指定頭文件目錄,這里指定的是我們自定義的頭文件目錄;-o指定輸出文件名。


編譯(Compilation)階段

gcc -S -I./inc test.c -o test.s

上述命令中-S讓編譯器在編譯之后停止,不進行后續(xù)過程。編譯過程完成后,將生成程序的匯編代碼test.s,這也是文本文件,內(nèi)容如下:

// test.c匯編之后的結(jié)果test.s
    .file   "test.c"
    .section    .rodata
.LC0:
    .string "a=%d, b=%d, a+b=%d
"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $2, 20(%esp)
    movl    $3, 24(%esp)
    movl    24(%esp), %eax
    movl    %eax, 4(%esp)
    movl    20(%esp), %eax
    movl    %eax, (%esp)
    call    add 
    movl    %eax, 28(%esp)
    movl    28(%esp), %eax
    movl    %eax, 12(%esp)
    movl    24(%esp), %eax
    movl    %eax, 8(%esp)
    movl    20(%esp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret 
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

匯編(Assemble)階段

匯編過程將上一步的匯編代碼轉(zhuǎn)換成機器碼(machine code),這一步產(chǎn)生的文件叫做目標文件,是二進制格式。gcc匯編過程通過as命令完成:

$ as test.s -o test.o

等價于:

gcc -c test.s -o test.o

這一步會為每一個源文件產(chǎn)生一個目標文件。因此mymath.c也需要產(chǎn)生一個mymath.o文件


鏈接(Linking)階段

鏈接過程將多個目標文以及所需的庫文件(.so等)鏈接成最終的可執(zhí)行文件(executable file)。
命令大致如下:

$ ld -o test.out test.o inc/mymath.o ...libraries...
幾種語言的編譯執(zhí)行本質(zhì)區(qū)別:

PHP:執(zhí)行時編譯為opcode,然后zend引擎執(zhí)行opcode
Java:先編譯成字節(jié)碼,然后由JVM虛擬機執(zhí)行字節(jié)碼
C:直接編譯成可執(zhí)行文件,然后由操作系統(tǒng)執(zhí)行可以行文件

參考資料:
http://tina.reeze.cn/book/
http://www.laruence.com/2008/...
http://rednaxelafx.iteye.com/...
http://www.vcgood.com/archive...
http://www.cnblogs.com/Carpen...
http://blog.csdn.net/cutesour...
http://www.nowamagic.net/libr...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/23230.html

相關(guān)文章

  • 開發(fā)語言PHPJava、C語言編譯執(zhí)行過程

    摘要:效率比較低,依賴解釋器,跨平臺性好語言編譯執(zhí)行過程下面都是鳥哥博客的內(nèi)容深入理解原理之引擎對這個文件進行詞法分析,語法分析,編譯成,然后執(zhí)行。 編譯型語言和解釋型語言 從PHP,Java和C語言的編譯執(zhí)行過程可以先解釋下編譯型語言和解釋型語言。 編譯型語言 程序在執(zhí)行之前需要一個專門的編譯過程,把程序編譯成為機器語言的文件,運行時不需要重新翻譯,直接使用編譯的結(jié)果就行了。程序執(zhí)行效率高...

    gnehc 評論0 收藏0
  • 第2章:軟件構(gòu)建過程和工具 2.2軟件構(gòu)建過程,系統(tǒng)和工具

    摘要:建模語言建模語言是可用于表達信息或知識或系統(tǒng)的任何人造語言,該結(jié)構(gòu)由一組一致的規(guī)則定義,目標是可視化,推理,驗證和傳達系統(tǒng)設(shè)計。將這些文件安排到不同的地方稱為源代碼樹。源代碼樹的結(jié)構(gòu)通常反映了軟件的體系結(jié)構(gòu)。 大綱 軟件構(gòu)建的一般過程: 編程/重構(gòu) 審查和靜態(tài)代碼分析 調(diào)試(傾倒和記錄)和測試 動態(tài)代碼分析/分析 軟件構(gòu)建的狹義過程(Build): 構(gòu)建系統(tǒng):組件和過程 構(gòu)建變體...

    godiscoder 評論0 收藏0
  • Hack on HHVM —— Facebook是如何優(yōu)化PHP

    摘要:周四正式發(fā)布了編程語言,將靜態(tài)類型以及一些現(xiàn)代的語言特性引入了。這是對優(yōu)化之路上的新里程碑。但是語言層面的優(yōu)化限制太多,對而言還是不夠用。其次是優(yōu)化運行的步驟。在這方面進行調(diào)整,可以提升運行的性能。值得注意的是,給的影響很大。 Facebook周四正式發(fā)布了Hack編程語言,將靜態(tài)類型以及一些現(xiàn)代的語言特性引入了PHP。這是Facebook對PHP優(yōu)化之路上的新里程碑。 showIm...

    lmxdawn 評論0 收藏0
  • 盤點 PHP 和 ASP.NET 10大對比!

    摘要:谷歌,,,雅虎和最近因世界杯獲得龐大觀眾數(shù)量的都在使用。因此,數(shù)據(jù)庫服務(wù)器的能力是毋庸置疑的。微軟的服務(wù)器,服務(wù)器以及未來的更新價格昂貴。更依賴于微軟數(shù)量有限的開發(fā)者做出的改進和更新。 【編者按】本文主要針對開源 PHP 和非開源的 ASP.NET 在性能、成本、可擴展性,技術(shù)支持和復雜性等方面進行比較。 在網(wǎng)上論壇,總是有成百上千的文章和帖子在討論 PHP 和 ASP.NET,究竟誰...

    hosition 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<