?? 核心源碼的物理布局.htm
字號:
color=#ffffff size=3>
<P><BR>其它操作<BR> <BR>這個目錄中的其余源文件為一些低級操作提供軟件接口。time.c從用戶程序讀寫核心時<BR>間值,resource.c為I/O端口實現請求和釋放機制,dma.c為DMA通道完成同樣的工作。so<BR>ftirq.c處理下半部(見第九章“中斷處理”中“下半部”一節),itimer.c定義系統調<BR>用來設置和取得間隔計時器值。<BR> <BR>想知道核心的消息處理是如何工作的,你可以看printk.c,它顯示了在第四章介紹的幾<BR>個概念的一些細節(也就是說,它包含了printk和sys_syslog的代碼)。<BR> <BR>exec_domain.c包含了獲得與其它風格的Unix兼容性所需要的代碼,info.c定義了sys_in<BR>fo。panic.c做的工作正如它的名字所示;它還支持在系統不穩定后自動重啟動。重新引<BR>導發生在由/proc/sys/kernel/panic設置的延遲之后。這個延遲通過對udelay(1000)的<BR>重復調用實現,因為在系統崩潰后,調度程序不再運行,udelay可以用于不長于1毫秒的<BR>延遲(見第六章“長延遲”一節)。<BR> <BR>sys.c實現幾個系統配置和權限處理函數,如uname,setsid及類似的調用。sysctl.c包<BR>含sysctl調用的實現和在sysctl表(系統控制入口點列表)注冊及取消注冊的入口點。<BR>這個文件也提供了按照注冊的表訪問/proc/sys文件的能力。<BR> <BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>mm目錄<BR> <BR>在mm目錄中的文件為Linux核心實現內存管理中體系結構無關的部分。這個目錄包含換頁<BR>及內存的分配和釋放的函數,還有允許用戶進程將內存區間映射到它們地址空間的各種<BR>技術。<BR> <BR> <BR> <BR>換頁和對換<BR> <BR>令人驚奇的是,swap.c并未實現對換算法。相反,它處理核心的命令行選項swap=和buff<BR>=。這些選項也可以通過sysctl系統調用或寫文件/proc/sys/vm來設置。<BR> <BR>sawp_state.c負責維護對換高速緩存,是這個目錄中最難的文件;我不想討論它的細節<BR>,因為很難理解它的設計,除非以前對相關的數據結構和策略已經有了很好的了解。<BR> <BR>swapfile.c實現對換文件和設備的管理。swapon和swapoff系統調用在這里定義,后者代<BR>碼非常困難。作為比較,有幾個Unix系統沒有實現swapoff,這樣如果不重啟動就無法停<BR>止向一個設備或文件的對換。swapfile.c還聲明了get_swap_page,它從對換池中取得一<BR>個空閑頁。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P>vmscan.c實現換頁策略。kswapd守護進程在這個文件定義,還有掃描內存,運行進程尋<BR>找可換出的頁的函數。<BR> <BR>最后,page_io.c實現了與對換空間之間進行低級數據傳送的功能。這個文件管理保證系<BR>統一致性的鎖機制,提供同步和異步的I/O。它還處理與不同設備使用不同塊大小相關的<BR>問題。(在Linux的早期版本,不可能對換到一個FAT分區上,因為不支持512字節的塊。<BR>)<BR> <BR> <BR> <BR>分配和釋放<BR> <BR>再第七章介紹的內存分配技巧都在mm目錄實現。讓我們再一次從最常用的函數開始:kma<BR>lloc。<BR> <BR>kmalloc.c實現內存區域的分配和釋放。kmalloc的內存池由一些“桶”組成,每個桶是<BR>同樣大小的內存區域的列表。kmalloc.c的主要功能是管理每個桶的鏈表。<BR> <BR>當需要新頁或有頁面被釋放時,這個文件利用在page_alloc.c中定義的函數。頁面用__g<BR>et_free_pages從空閑內存中取得,這是一個從空閑頁列表中取得頁面的短函數。如果空<BR>閑列表中沒有內存可用,就調用try_to_free_pages(vmscan.c)。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P>vmalloc.c實現了vmalloc,vremap,vfree函數。vmalloc返回核心虛擬空間中的連續內<BR>存,vremap給出特定物理地址的新的虛地址;它主要用來訪問高端內存的PCI緩沖。vfre<BR>e釋放內存,如它的名字所示。<BR> <BR> <BR> <BR>其它接口<BR> <BR>Linux內存管理最重要的函數是memory.c文件的一部分。這些函數一般不能通過系統調用<BR>訪問,因為它們處理硬件的換頁機制。<BR> <BR>另一方面,模塊的作者的確使用這些函數。verify_area和remap_page_range在memory.c<BR>中定義。其它有趣的函數是do_up_page和do_no_page,它們實現核心對次和主頁面錯的<BR>反應。文件中的其余函數處理頁表,都非常低級。<BR> <BR>內存映射是mm目錄中文件處理的另一個大任務。filemap.c的代碼很復雜。它實現常規文<BR>件的內存映射,提供支持共享映射的能力。被映射文件通過被映射頁的特殊結構vm_oper<BR>ations支持,如在十三章“Mmap和DMA”中“虛擬內存區域”一節中所描述的。這個源文<BR>件頁處理異步提前讀;注釋解釋了結構file中四個提前讀域的含義。這個文件中出現的<BR>唯一的系統調用是sys_msym。到內存映射的頂級接口(即do_mmap)出現在mmap.c。<BR> <BR>這個文件有定義brk系統調用開始,它被一個進程用來請求其最高允許的虛地址被增加或<BR></P></FONT><FONT
color=#ffffff size=3>
<P>減小。sys_brk的代碼提供了很多信息,即使你不是內存管理的大師。mmap.c的其余部分<BR>集中在do_mmap和do_munmap。如你所期望的,內存映射通過filp->f_op完成,盡管filp<BR>對do_mmap可能為NULL。這是brk 如何分配新的虛擬空間的。它還是依賴于內存映射零頁<BR>,而不需要特殊代碼。<BR> <BR>mremap.c包括sys_mremap。如果你已經搞清楚了mmap.c,這個文件就很容易了。<BR> <BR>與內存鎖定和解鎖相關的四個系統調用在mlock.c中定義,它是相當簡單發源文件。類似<BR>第,mprotect.c負責執行sys_mprotect。這些文件在定義上很相似,因為它們都修改了<BR>與進程頁相關的系統標志。<BR> <BR> <BR> <BR>fs目錄<BR> <BR>在我的觀點中,這個目錄是整個源碼樹中最有趣的一部分。文件處理是任何Unix系統的<BR>一個基本活動,所有與文件相關的操作都在這個目錄中實現。我不想在這兒描述fs子目<BR>錄,因為每種文件系統類型僅僅是把VFS層映射到特別的信息布局上。但講一下fs目錄中<BR>多數文件的作用還是很重要的,因為它們攜帶了大量的信息。<BR> <BR> <BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P>Exec和二進制格式<BR> <BR>Unix中最重要的系統調用是exec。用戶程序可以exec六種不同的形式,但在只有一個在<BR>核心中實現----其它都是隱射到全特征實現execve上的庫函數。<BR> <BR>exec函數用一個已注冊二進制格式的表以查找用來加載和執行一個磁盤文件的正確的加<BR>載程序。源文件的第一部分定義了register_binfmt接口。有興趣的是注意到腳本文件的<BR>#!魔幻鍵被作為二進制格式處理,如ELF和另外一些格式(盡管在1.2版本中它是exec.c<BR>的一種特殊情況)。kerneld也需要了解一個新的二進制格式是如何按照要求從讀取源文<BR>件被加載的。<BR> <BR>每個二進制格式由一個定義了三種操作(加載一個二進制文件,加載一個庫,傾倒內核<BR>(core dump))的數據結構描述。這個結構在<linux/binfmts.h>中定義。決大多數格<BR>式都只支持第一個操作(加載一個文件),不過這個接口已經足夠一般化,能夠支持任<BR>何可預見的新格式的需要。<BR> <BR> <BR> <BR>devices.ch和block_dev.c<BR> <BR>我們已經用了 devices.c中的代碼,因為它負責設備注冊和取消注冊。它同時也負責缺<BR>省的設備open方法,以及對塊設備的release方法。這些調用為被打開或關閉的設備取得<BR></P></FONT><FONT
color=#ffffff size=3>
<P>正確的文件操作并將執行分派到正確的方法。對模塊自動加載的支持在這個文件中實現<BR>。除了打開和關閉設備之外的所有東西都出現在drivers/*目錄,如filp->f_op所指示的<BR>。<BR> <BR>block_dev.c包含讀寫塊設備的缺省方法。如你可能記得的,一個塊驅動程序并不聲明它<BR>自己的I/O方法,只是它的請求例程。block_dev.c的缺省讀寫實現了解緩沖高速緩存,<BR>除了實際的數據傳送它提你做了所有的事情。<BR> <BR> <BR> <BR> <BR> <BR>VFS:超級塊<BR> <BR>程序和設備的執行只是fs目錄的一部分。fs的多數文件,以及子目錄中的所有文件,都<BR>與文件相關的系統調用有關。更特別地:它們實現了所謂的VFS機制:虛擬文件系統(或<BR>虛擬文件系統切換----這些解釋有點互相矛盾)。<BR> <BR>概念地說,VFS是Linux文件處理軟件的一層。通過利用各種文件系統格式提供的特征,<BR>這層提供了到文件的統一接口。在磁盤上布局信息的各種技巧可以通過VFS接口用一致的<BR>方法訪問。實際上,VFS減少到幾個定義“操作”的結構。每個文件系統聲明處理超級塊<BR>、inode、和文件的這些操作。我們在本書中已經使用的file_operations結構就是VFS接<BR></P></FONT><FONT
color=#ffffff size=3>
<P>口的一部分。<BR> <BR>核心通過安裝每個文件系統來訪問它。mount的一個任務是從磁盤上搜取所謂的“超級塊<BR>”。超級塊是一個文件系統中的主要數據結構。它的名字來自于一個事實,歷史上,它<BR>曾經是磁盤上的第一個物理塊。文件super.c包括與超級塊有關的有趣操作的源碼:讀取<BR>的同步它們、安裝和卸裝文件系統、在引導時安裝根文件系統。<BR> <BR>除了這些有趣的(還有點復雜)操作,super.c也返回與文件系統有關的信息,包括由/p<BR>roc/mounts和/proc/filesystems提供的信息。<BR> <BR>函數register_filesystem和unregister_filesystem被模塊化的文件系統類型使用;它<BR>們也在super.c中定義。文件filesystems.c是一個#ifdef語句的短表。依賴于那些選項<BR>被編譯進核心,對應不同文件系統的各種init函數被調用。每個文件系統類型的init函<BR>數調用register_filesystem,因此不需要別的條件編譯選項。<BR> <BR> <BR> <BR>Inode和高速緩存技術<BR> <BR>VFS接口的下一塊是inode。每個inode由一個由設備號和inode號組成的唯一的鍵值確定<BR>。用戶程序用文件名去訪問文件系統中的結點,核心負責將文件名映射到唯一的鍵值。<BR>為了獲得更好的性能,Linux維護了兩個與inode鍵值相關的高速緩存:inode高速緩存和<BR></P></FONT><FONT
color=#ffffff size=3>
<P>名字高速緩存(也叫目錄高速緩存)。另外,核心還負責已經熟悉的緩沖高速緩存。<BR> <BR>inode高速緩存是一個哈希表,用于從設備/ inode號鍵值查找inode結構。高速緩存的實<BR>現,以及讀寫inode的例程,都在inode.c中。這個文件也實現了inode結構的鎖機制以防<BR>止可能的死鎖。<BR> <BR>名字高速緩存是一個表,它將inode號和文件名關聯起來。當一個名字被連著用了幾次,<BR>高速緩存就可以避免重復的目錄查詢。源文件dcache.c包含管理高速緩存的軟件機制。<BR>使用名字高速緩存的多數系統調用和函數是namei.c(表示name-inode)的一部分,包括<BR>sys_mkdir,sys_symlink,sys_rename,及類似的調用。<BR> <BR>緩沖高速緩存是系統中最大的數據高速緩存,它的實現出現在巨大的文件buffer.c中。<BR> <BR>至于文件,file_table.c負責file結構的分配和釋放。這包括get_empty_filp,它被ope<BR>n,pipe,socket調用。<BR> <BR> <BR> <BR>open.c<BR> <BR>fs中其它源文件中多數負責文件操作----與在驅動程序中需要實現的一樣。第一個這樣<BR>的文件是open.c,它包括了很多系統調用的代碼。它也包括sys_open,及它的低級的對<BR></P></FONT><FONT
color=#ffffff size=3>
<P>應者do_open,還有sys_close。這些系統調用都很直接,被映射到filp->f_op。<BR> <BR>open.c包含修改inode的系統調用:chown和chmod,以及它們的對應者fchown和fchmod。<BR> 如果你對安全檢查和不可變標志的使用感興趣,你可以瀏覽源碼,它可以被幾乎所有的<BR>Unix編程者理解。改變inode中的次數也被支持----utime和utimes在這里定義。<BR> <BR>chroot,chdir,和fchdir也在open.c中找到,同時還有其它“改變”函數。<BR> <BR>源碼中定義的第一個函數是statfs和fstatfs,它們通過inode->I_sb->s_op->statfs被<BR>分派文件系統特定的代碼。<BR> <BR>truncate和access調用也出現在這個文件中。后者用進程的實際uid和gid檢查文件的權<BR>限,暫時不考慮fsuid和fsgid。<BR> <BR> <BR> <BR>read.c和readdir.c<BR> <BR>正如其名字所示,read_write.c包含讀和寫,但它也包含了lseek和llseek(有人猜測這<BR>個前導l的數目是每十年增加一個)。lseek是使用off_t(long)的標準調用,而llseek使<BR>用loff_t(long long)。llseek系統調用映射到lseek文件操作,它被作為lseek的超集實<BR>現。有趣的是注意到核心2.1版將這個方法改名為llseek,以與其實現保持一致。<BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>read和write是很簡單的函數,因為實際的數據傳送是通過filp->f_op來分派的;read_w<BR>rite.c也包含了readv和writev的代碼,它們稍為復雜,因為多塊數據的傳輸必須跨過核<BR>心和用戶邊界。<BR> <BR>Linux不允許你直接讀一個目錄文件,如果你嘗試,將會返回-EISDIR。目錄只能用readd<BR>ir系統調用來讀取,它是文件系統無關的;或使用getdents,即“取得目錄項”。用get<BR>dents讀一個目錄要快一點,因為一個調用可以返回很多目錄項,而readdir一次只能返<BR>回一項。不過,getdents只被libc-5.2或更新的庫所支持。<BR> <BR> <BR> <BR>select.c<BR> <BR>select的完整實現居于select.c,除了select_wait線入函數。盡管select.c的代碼很有<BR>趣,但卻很難閱讀,因為數據結構太復雜(這在第五章“增強的字符設備驅動程序操作<BR>”中“底層數據結構中討論過”)。不過select.c倒是閱讀核心代碼的一個好的起始點<BR>,因為它是自包含的;除了一些無關緊要的細節外它不依賴與其它源文件。<BR> <BR> <BR> <BR>Pipe和fifos<BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>pipe和fifo通信通道的實現與字符設備驅動程序非常類似。通過為兩個通道使用同樣的<BR>文件操作來避免了代碼重復;只有open方法不一樣。除了fifo_open和fifo_init外所有<BR>的函數都在pipe.c中定義。由于fifo與文件系統結點類似,除了file_operations結構,<BR>它們還需要一組inode_operations與之相關。正確的結構在fifo.c中定義。<BR> <BR>下一個有趣的事情是注意到在pipe和fifo的實現中,pipe.c定義了兩個file_operation<BR>結構:一個是為通道的可讀側的,一個是為可寫側的。這允許在read和write中跳過權限<BR>檢查。<BR> <BR> <BR> <BR>控制函數<BR> <BR>文件的“控制”系統調用在兩個根據這個調用命名的文件中:fcntl.c和ioctl.c。前者<BR>基本上是自包含的,因為為fcntl定義的所有的命令都是預定義的。由于其中一些只是du<BR>p的包裹者,因此dup的實現也在fcntl.c中。另外,由于fcntl調用負責異步觸發,kill_<BR>fasync也可以在此找到。<BR> <BR>ioctl.c包含ioctl系統調用的外部接口。它是一個短文件,當它收到不認識的命令時,<BR>還要依賴于文件操作。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR> <BR>文件鎖<BR> <BR>Linux中實現了兩類鎖接口,flock系統調用和fcntl命令。后者是POSIX兼容的。<BR> <BR>文件locks.c包含了處理兩個調用的代碼。它也包括對強制鎖的支持,它在2.0.0之前是<BR>一個編譯選項,在2.1.4被改為一個安裝(mount)時選項。<BR> <BR> <BR> <BR>次要文件<BR> <BR>fs的文件還支持磁盤定額(quota)。dquot.c實現了定額機制,而noquot.c包含空函數<BR>;如果定額沒有被包含在核心的配置中,它就代替dquot.c被編譯。<BR> <BR>最后,stat.c實現了stat、lstat、readlink系統調用。在2.0.x定義了stat和lstat的兩<BR>個實現,以保持與舊的x86庫的后向兼容。<BR> <BR> <BR> <BR>網絡<BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>Linux文件體系中的net目錄是套接字抽象和網絡協議的容庫;這些特征使用了大量的代<BR>碼,因為Linux支持集中不同的網絡協議。每個協議(IP,IPX等等)都居于它自己的子<BR>目錄中。Unix域的套接字被以一種網絡協議對待,它們的實現可以在unix子目錄找到。<BR>有趣的是注意到2.0版的核心只包含了IPv4,而版本2.1包含了相當完整的IPv6的支持,<BR>新來的標準解決了IPv4的編號問題。<BR> <BR>Linux中的網絡實現是基于用于設備文件的同樣的文件操作。這很自然,因為網絡連接(<BR>套接字)是用一般文件描述符描述的。在核心中一個套接字是由一個結構socket(<linux<BR>/net.h>)描述。文件socket.c是套接字文件操作的容庫。它通過結構proto_ops分派系統<BR>調用到其中的一個網絡協議。這個結構被每個網絡協議定義以將系統調用映射到低級的<BR>數據處理。<BR> <BR>net下的每個目錄(除bridge,core,ethernet)都專用來實現一個網絡協議。目錄brid<BR>ge包含符合IEEE規范的以太網橋的優化實現。core中文件實現了通用的網絡特征如:設<BR>備處理,火墻,選播和異名;這包括獨立于底層協議(core/sock.c)的套接字緩沖區(c<BR>ore/skbuff.c)和套接字操作的處理。最后,ethernet包含通用的以太網函數。<BR> <BR>幾乎每個net下的目錄都有一個處理系統控制的文件;這樣引出的信息可以通過/proc/sy<BR>s文件樹或通過sysctl系統調用來訪問。到sysctl的核心接口允許對系統控制入口點動態<BR>的增加和去除,在<linux/sysctl.h>中定義。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR> <BR>IPC和lib函數<BR> <BR>進程間通信和庫函數各有一個小的專用目錄。<BR> <BR>ipc目錄包含一個名為util.c的通用文件,以及每種通信方式的一個源文件:sem.c,shm<BR>..c,msg.c。msg.c負責消息隊列和kerneld引擎,kerneld_send。如果IPC沒有在編譯時<BR>打開,util.c引出一些空函數,它們通過返回-ENOSYS來實現IPC相關的系統調用。<BR> <BR>庫函數就象你在C程序中常見的一些工具和變量:sprintf,vsprintf,errno整數值,以<BR>及被各種<linux/ctype.h>宏使用的_ctype數組。文件string.c包含字符串函數的可移植<BR>實現,但只有在體系結構特定的代碼不包含優化的線入函數時才能編譯。如果線入函數<BR>在頭文件中定義,那么在string.c中的實現應該用#ifdef語句排除在外。<BR> <BR>lib中最“有趣”的文件是inflate.c,它是gzip的“gunzip”部分,是從gzip本身展開<BR>從而允許在引導時使用壓縮的RAMdisk。這個技巧在需要的數據除了壓縮,不能在一張軟<BR>盤上放下時使用。<BR> <BR> <BR> <BR>Drivers<BR></P></FONT><FONT
color=#ffffff size=3>
<P> 現在對Linux的drivers目錄已經沒什么可說的了。這個目錄中的源文件在整部書里已經<BR>被廣泛引用;這也使我為什么在討論源文件樹時把它們留在最后。<BR> <BR> <BR> <BR>字符設備、塊設備、和網絡驅動程序<BR> <BR>盡管這些目錄中大多數驅動程序是特定于某種特別的硬件的,還是有幾個文件在系統設<BR>置時起到比較通用的作用。<BR> <BR>關于目錄drivers/char,實現N_TTY行規則的代碼就在這兒。N_TTY是系統tty的缺省行規<BR>則,它在n_tty.c中定義。在drivers/char中的另一個設備無關的文件是misc.c,它提供<BR>對“雜類”設備的支持。一個 “雜類”設備是有一個次設備號的簡化的字符設備驅動程<BR>序。<BR> <BR>這個目錄還包含了對PC控制臺的支持,和其它一些體系結構相關的驅動程序;它實際上<BR>包含了一些在其它地方都不合適的雜項的集合。<BR> <BR>drivers/block則要清晰多了。它包含了多數快設備驅動程序的單個文件驅動程序,和全<BR>特征的IDE驅動程序,它被劈成了多個文件。這個目錄的資格文件提供了通用目的的支持<BR>;genhd.c處理分區表,ll_rw_block.c負責與物理設備之間數據傳送的低級機制。reque<BR>st結構是ll_rw_block.c的主要部分。<BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>drivers/net包含了PC網卡驅動程序的長列表,以及幾個其它體系結構的驅動程序(例如<BR>,sunlance.c是為了多數Sparc計算機的接口的)。有些驅動程序比它看起來要復雜一些<BR>,這在第十四章“網絡驅動程序”中介紹過。例如ppp.c聲明自己的行規則。<BR> <BR>在drivers/net下的通用目的源文件是Space.c和net_init.c。Space.c主要是包含了一個<BR>可用網絡設備的表。這個表包含了一個#ifdef項的長列表,它們在系統引導時被檢差以<BR>檢測和初始化網絡設備。net_init.c包含ether_setup,tr_setup,和類似的通用目的函<BR>數。<BR> <BR> <BR> <BR>SCSI驅動程序<BR> <BR>如在第一章“Linux核心介紹”中所提到的,Linux中的SCSI驅動程序沒有被包含在一般<BR>的字符和塊設備類中。這是因為SCSI接口總線有它自己的標準。因此,將SCSI設備和其<BR>它驅動程序分開,開發者可以分離和共享公用代碼。<BR> <BR>drivers/scsi中多數文件是為特定SCSI控制器的低級驅動程序。通用目的的SCSI實現在<BR>文件scsi_*.c中定義,還有sd.c是磁盤支持,sr.c是CD-ROM支持,st.c是SCSI磁帶支持<BR>,sg.c是通用SCSI支持。最后一個源文件對使用SCSI協議的設備定義<BR>--<BR><FONT
color=#00ff00>※ 來源:.華南網木棉站 bbs.gznet.edu.cn.[FROM: 202.38.196.234]</FONT><BR>--<BR><FONT
color=#00ffff>※ 轉寄:.華南網木棉站 bbs.gznet.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR><FONT
color=#0000ff>※ 轉寄:.華南網木棉站 bbs.gznet.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR><FONT
color=#ffff00>※ 轉載:.南京大學小百合站 bbs.nju.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR>
<P align=center><A href="http://joyfire.net/lsdp/index.htm"><FONT
color=#ffffff size=2>目錄頁</FONT></A> | <A
href="http://joyfire.net/lsdp/19.htm"><FONT color=#ffffff
size=2>上一頁</FONT></A> | <A href="http://joyfire.net/lsdp/21.htm"><FONT
color=#ffffff
size=2>下一頁</FONT></A></P></FONT></SPAN></TD></TR></TBODY></TABLE></TD></TR></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
<TBODY>
<TR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -