📄 linuxemu-advanced.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="generator" content="HTML Tidy, see www.w3.org" /><title>高级主题</title><meta name="GENERATOR" content="Modular DocBook HTML Stylesheet Version 1.7" /><link rel="HOME" title="FreeBSD 使用手册" href="index.html" /><link rel="UP" title="Linux二进制兼容模式" href="linuxemu.html" /><link rel="PREVIOUS" title="安装SAP燫/3" href="sapr3.html" /><link rel="NEXT" title="系统管理" href="system-administration.html" /><link rel="STYLESHEET" type="text/css" href="docbook.css" /><meta http-equiv="Content-Type" content="text/html; charset=GB2312" /></head><body class="SECT1" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#840084"alink="#0000FF"><div class="NAVHEADER"><table summary="Header navigation table" width="100%" border="0" cellpadding="0"cellspacing="0"><tr><th colspan="3" align="center">FreeBSD 使用手册</th></tr><tr><td width="10%" align="left" valign="bottom"><a href="sapr3.html"accesskey="P">后退</a></td><td width="80%" align="center" valign="bottom">章 10. Linux二进制兼容模式</td><td width="10%" align="right" valign="bottom"><a href="system-administration.html"accesskey="N">前进</a></td></tr></table><hr align="LEFT" width="100%" /></div><div class="SECT1"><h1 class="SECT1"><a id="LINUXEMU-ADVANCED" name="LINUXEMU-ADVANCED">10.8.高级主题</a></h1><p>如果你对Linux兼容模式是如何工作的感到好奇,这节正是你所需要的。 下面的绝大部分内容是由Terry Lambert<code class="EMAIL"><<ahref="mailto:tlambert@primenet.com">tlambert@primenet.com</a>></code> (Message ID:<varclass="LITERAL"><199906020108.SAA07001@usr09.primenet.com></var>)发表在邮件列表<ahref="http://lists.FreeBSD.org/mailman/listinfo/freebsd-chat" target="_top">FreeBSD chat邮件列表</a>上的内容组成的。</p><div class="SECT2"><h2 class="SECT2"><a id="AEN15402" name="AEN15402">10.8.1. 它是如何工作的?</a></h2><p>FreeBSD有一个“可执行类加载器”。它主要是嵌入了<span class="CITEREFENTRY"><spanclass="REFENTRYTITLE">execve</span>(2)</span>系统调用。</p><p>碰巧的是FreeBSD有一个引导器(loader)的列表,而不是一个简单的返回一个 符号 <varclass="LITERAL">#!</var>的引导器!</p><p>从历史上来讲,只有<spanclass="TRADEMARK">UNIX</span>®平台的引导器会检查魔术(magic)数(通常是文件的前4个或8个字节)是否是二进制的, 如果是,就调用二进制引导程序。</p><p>如果它不是二进制类型的<span class="CITEREFENTRY"><spanclass="REFENTRYTITLE">execve</span>(2)</span>调用就会返回一个错误,shell就试图用shell命令执行它。</p><p>缺省是使用“当前设定的shell”。</p><p>随后,进行了一些hack, <span class="CITEREFENTRY"><spanclass="REFENTRYTITLE">sh</span>(1)</span>开始检查前两个字符,如果它们是<varclass="LITERAL">:\n</var>, 那它就调用<span class="CITEREFENTRY"><spanclass="REFENTRYTITLE">csh</span>(1)</span>(我们相信是SCO最先做这个hack的)。</p><p>FreeBSD现在所做的是用一个普通的<varclass="LITERAL">#!</var>引导器仔细检查引导器的列表,然后由解释程序一个接一个地解释,返回给<tt class="FILENAME">/bin/sh</tt>。</p><p>为了支持Linux ABI,FreeBSD就把魔术数看作为一个二进制ELF程序。(这样一来,它就使得在FreeBSD, <spanclass="TRADEMARK">Solaris</span>™,Linux和其他任何操作系统之间只要使用ELF格式就都可以顺利运行)。</p><p>ELF引导器会寻找一个专门的<span class="emphasis"><i class="EMPHASIS">标记</i></span>,它是在ELF映像中的一个注释部分,但在SVR4/<spanclass="TRADEMARK">Solaris</span>的ELF中没有。</p><p>为了执行Linux程序,它们必须被打上<var class="LITERAL">Linux</var>类型的<spanclass="emphasis"><i class="EMPHASIS">标记</i></span>; 使用<spanclass="CITEREFENTRY"><span class="REFENTRYTITLE">brandelf</span>(1)</span>:</p><pre class="SCREEN"><samp class="PROMPT">#</samp> <kbd class="USERINPUT">brandelf -t Linux file</kbd></pre><p>做完之后,ELF引导器就会看到文件上的<var class="LITERAL">Linux</var>的标记。</p><p>当ELF引导器看到<var class="LITERAL">Linux</var>的标记, 引导器就会在<varclass="LITERAL">proc</var>结构中替换一个指示器。所有的系统调用就会通过这个指示器来索引(在一个传统的 <spanclass="TRADEMARK">UNIX</span>系统中, 这就是<varclass="LITERAL">sysent[]</var>结构队列,包含系统调用)。此外,为了解决由于信号杂乱所造成的陷阱向量的问题,会造成线程的剧增,需要切断其他(或较小的)由Linux内核模块产生的修正。</p><p>Linux系统调用向量包含一个<var class="LITERAL">sysent[]</var>记录的列表,它的地址位于内核模块之中。</p><p>当一个系统调用被Linux程序调用时,有缺陷的代码会把系统调用功能的指示器从<varclass="LITERAL">proc</var>结构中解除, 然后获得Linux,而不是FreeBSD,系统调用入口点。</p><p>另外,Linux模式动态地<span class="emphasis"><iclass="EMPHASIS">reroots</i></span>查找;这和启动文件系统的<varclass="OPTION">union</var> 选项是等效的(即时不是<varclass="LITERAL">unionfs</var>文件系统)。 首先会试图在<ttclass="FILENAME">/compat/linux/<var class="REPLACEABLE">original-path</var></tt>目录查找文件,如果失败了,就会在<tt class="FILENAME">/<varclass="REPLACEABLE">original-path</var></tt>目录下查找。这使得需要其它程序的程序可以运行(例如,Linux工具链都可以在LinuxABI的支持下工作)。也就是说Linux程序可以加载和执行FreeBSD程序,如果当前没有相应的Linux程序, 那你可以在<ttclass="FILENAME">/compat/linux</tt>目录树中放置一个<span class="CITEREFENTRY"><spanclass="REFENTRYTITLE">uname</span>(1)</span>,来确保Linux程序不提示它们不能运行在Linux上。</p><p>在FreeBSD内核中有一个Linux内核;由内核提供的能够提供所有服务的各种潜在功能在FreeBSD系统调用表记录和Linux系统调用表记录之间是一样的:文件系统操作,虚拟内存操作,信号发送,System V IPC,...等等。唯一的不同是FreeBSD会得到FreeBSD的<span class="emphasis"><iclass="EMPHASIS">胶合</i></span>功能, 而Linux程序会得到Linux的<span class="emphasis"><iclass="EMPHASIS">胶合</i></span>功能 (大部分老的操作系统只有它们自己的<spanclass="emphasis"><i class="EMPHASIS">胶合</i></span>函数, 函数地址在静态全局变量<varclass="LITERAL">sysent[]</var>结构数据里面, 而不是动态的初始化到进程的<varclass="LITERAL">proc</var>结构)。</p><p>哪一个是FreeBSD自己的ABI呢?这无关紧要。基本上, 唯一的不同是FreeBSD的<spanclass="emphasis"><i class="EMPHASIS">胶合</i></span>功能是被静态连接到内核,而Linux的<span class="emphasis"><iclass="EMPHASIS">胶合</i></span>功能可能是被静态连接到内核,也可能它们通过一个内核模块来访问。</p><p>有一个真正的模拟器吗?没有,它只不过是一个ABI执行机制,不是一个模拟器。</p><p>为什么有时它被叫做“Linux模拟器”? 只是为了更容易地卖出FreeBSD罢了!实际上,历史上从来没有描述这样一种执行机制的名字,FreeBSD并不是真正地运行Linux程序,如果你不编译进代码,或加载一个模块。就需要有一个名字来描述这样一种加载功能--因此就想出了“Linux模拟器”这样一个名字。</p></div></div><div class="NAVFOOTER"><hr align="LEFT" width="100%" /><table summary="Footer navigation table" width="100%" border="0" cellpadding="0"cellspacing="0"><tr><td width="33%" align="left" valign="top"><a href="sapr3.html"accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html"accesskey="H">起点</a></td><td width="33%" align="right" valign="top"><a href="system-administration.html"accesskey="N">前进</a></td></tr><tr><td width="33%" align="left" valign="top">安装<spanclass="TRADEMARK">SAP</span>® <span class="TRADEMARK">R/3</span>®</td><td width="34%" align="center" valign="top"><a href="linuxemu.html"accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">系统管理</td></tr></table></div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -