免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4464 | 回复: 0
打印 上一主题 下一主题

比较 Solaris、Linux 和 FreeBSD 内核 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-20 11:05 |只看该作者 |倒序浏览

[email=?subject=Sun Web Page: Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home&body=Check out this page on sun.com: %0A%0Ahttp%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2Fopensolaris_nas.html][/email]
[/url]
[url=http://del.icio.us/post?v=4;url=http%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2Fopensolaris_nas.html;title=Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home]

[/url]
[url=http://slashdot.org/bookmark.pl?title=Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home&url=http%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2Fopensolaris_nas.html]

[/url]


[url=http://developers.sun.com/jsp_utils/PrintPage.jsp]

Print-friendly Version

By
Developer Recipes
, 6/9/08


借助 OpenSolaris 操作系统中的新 CIFS 服务器,开发人员可以使用 ZFS 和 CIFS 创建家庭 NAS 网络存储器,以取代 Windows 共享机器。
目录

步骤 1:获取硬件

首先,需要配齐 NAS 网络存储器的硬件。本文将采用以下硬件:

  • 一台 Multipack 磁盘阵列柜(6 个 40GB 硬盘)
  • 一部闲置的 W2100Z 工作站。(这一出色的平台拥有双 64 位 AMD 处理器,一个内置 SCSI 磁盘驱动器,以及三个空闲驱动器仓位。)
  • DIMM 内存若干,用于 W2100Z
  • 外加一个 SCSI 卡

步骤 2:安装硬件

在开始升级硬件之前,请先佩戴防静电手腕带。
接下来,将 SCSI 卡安装到 Multipack 柜中。新增内存有助于提高 ZFS 的工作性能。硬件安装完毕后,就可以安装 OpenSolaris 操作系统了。
步骤 3:安装 OpenSolaris SXDE 1/08

安装 OpenSolaris 操作系统的准备工作十分简单快捷(耗时 5 分钟左右):
  • 下载并烧录 DVD。
  • 插入烧好的 DVD 片。
  • 启动工作站。
  • 回答提问。
  • 单击 Finish 按钮
    然后,安装真正开始。在本例中,安装需耗时 1.5 小时。现在,新服务器已经可以正常运行 OpenSolaris 操作系统。
    下面,需要做各方面配置。
    步骤 4:配置 OpenSolaris 操作系统

    请先阅读
    CIFS 入门指南
    。该指南很有价值,能给初学者提供各方面的帮助。
    创建用户
    首先,创建一些不同的用户。在安装期间,创建一个超级用户,然后再创建一个拥有“特权”的普通用户,和一个拥有文件访问权的用户。为此,使用用户 ID admin 和 media。要添加用户,在开始菜单的控制面板中设置用户帐户。

    图1:创建用户

    创建存储池
    为搭建服务器和服务数据,您需要配置存储器。为此,通过浏览器访问页面 https://:6789/zfs ,进入 ZFS 图形用户界面,登录用户有超级用户权限。此图形用户界面将显示系统安装的所有存储器及其使用情况。选中 Multipack 安装的全部驱动器,创建一个 RAIDZ1 池并将它命名为 mediapool。

    图2:创建存储池

    使用 ZFS 图形用户界面创建 ZFS 池之后,切换到终端窗口检查新建池的状态:
    # zfs list
    NAME USED AVAIL REFER MOUNTPOINT
    mediapool 144K 165G 29.9K /mediapool
    创建文件系统
    接下来,创建文件系统:
    # zfs create -o casesensitivity=mixed mediapool/music
    # zfs create -o casesensitivity=mixed mediapool/photos
    # zfs create -o casesensitivity=mixed mediapool/movies
    要使用大小写混合的文件名,请将 ZFS 属性设置为 casesensitivity=mixed。如果需要与 Windows 系统共享文件,则这一步十分重要。如果没有这一步,那么所有的文件名将设为大写,这对于阅览非常不便。
    配置 CIFS
    创建文件系统之后,启动 CIFS 服务:
    # svcadm enable -r smb/server
    # smbadm join -w WORKGROUP
    您可以使用工作组模式共享文件。在大多数情况下,一般将工作组设为 WORKGROUP。
    设置身份验证
    要配置 CIFS 服务器使用 PAM 身份验证,您需要升级 OpenSolaris 密码系统。为此,使用下面命令:
    # echo "other password required pam_smb_passwd.so.1 nowarn" >> /etc/pam.conf
    另外,输入上述命令后,对于准备使用 CIFS 验证的用户,必须全部重设密码:
    # passwd media
    现在,可以开始共享新建文件系统了。
    共享文件系统
    新服务器的搭建即将完工。CIFS 已经启用,文件系统业已创建,接下来只需共享文件系统:
    # zfs set sharesmb=name=Movies mediapool/movies
    # zfs set sharesmb=name=Music mediapool/music
    # zfs set sharesmb=name=photos mediapool/photos

    图 3:共享文件系统

    你可能用过单个 set 命令,附加选项 sharesmb=on ,但是此处讲解的命令对习惯于 Windows 平台命名的用户更加有用。为了避免歧义和长共享命名,需要明确设置。这既是一个小窍门,也是一条有用提示,请参阅
    CIFS 入门指南
    和讨论论坛。
    设置文件系统权限
    最后,所有文件的所有权应为主共享用户:
    # chown -R media /mediapool
    至此,在 NAS 网络存储器上配置 OpenSolaris 操作系统已经完成。
    步骤:配置 Windows

    现在,真正有趣的事情开始了。至此,本示例安装服务器硬件、安装操作系统和配置存储器仅耗费了两个小时;其中 90 分钟将用于 OpenSolaris 的安装。
    尽管在 Windows XP 系统上,收发电子邮件和浏览网页颇为简单;但是,它在共享文件方面有些复杂。基于 CIFS 的文件共享,不同于基于 NFS 的文件共享。
    在 OpenSolaris 系统上安装 CIFS 共享,必须经过该服务器的验证。这一点极其重要。而且,验证必须在服务器端,而不是在客户端。
    为了让 Windows 客户端上的文件共享正常工作,如下操作:
  • 以文件夹路径 \\\,映射 Windows 驱动器。
  • 选中链接 "Connect using a different user name",使用 OpenSolaris 服务器上的用户名和密码。

    图4:映射一个网络驱动器

    对于本文示例中的机器,文件夹路径是 \\PHRED\Movies,用户名是 media。
    此处提供的路径基于新建的 OpenSolaris NAS 网络存储器,所有 Windows 机器都可访问共享文件系统。
    [email=?subject=Sun Web Page: Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home&body=Check out this page on sun.com: %0A%0Ahttp%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2FA_Comparison_of_Solaris_Linux_and_FreeBSD_Kernels.html][/email]
    [/url]
    [url=http://del.icio.us/post?v=4;url=http%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2FA_Comparison_of_Solaris_Linux_and_FreeBSD_Kernels.html;title=Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home]

    [/url]
    [url=http://slashdot.org/bookmark.pl?title=Sun%E4%B8%AD%E5%9B%BD%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA-%20Sun%20Developer%20Network%20(SDN)%20Home&url=http%3A%2F%2Fdevelopers.sun.com.cn%2Fsolaris%2FA_Comparison_of_Solaris_Linux_and_FreeBSD_Kernels.html]

    [/url]


    [url=http://developers.sun.com/jsp_utils/PrintPage.jsp]

    Print-friendly Version

    By
    Max Bruning
    , 6/19/08


    我大部分时间都在教授 Solaris 内部实现、设备驱动程序以及内核崩溃转储分析和调试方面的课程。向学生解释如何在 Solaris 中实现各个子系统时,他们常常会问“在 Linux 中是怎样实现的呢?”或“在 FreeBSD 中是这样实现的,但在 Solaris中呢?”。本文对内核的三个基本子系统进行了探讨,并对它们在 Solaris 10、Linux 2.6 和 FreeBSD 5.3 中的实现进行了比较。
    本文探讨的三个子系统是调度、内存管理和文件系统体系结构。我之所以选择这些子系统,是因为它们是所有操作系统(不仅是 Unix 和类似于 Unix 的系统)所共有的,而且可能是操作系统中最容易理解的组件。
    本文不会对这些子系统进行深入的研究。要进行深入研究,请参考源代码、各种 Web 站点和有关这方面主题的书籍。以下是相关书籍:

    如果您在 Web 中搜索 Linux、FreeBSD 和 Solaris 的比较,大多数匹配的网页讨论的都是这些操作系统的旧版本(有时是 Solaris 2.5、Linux 2.2 等)。许多“事实”对于最新版本来说都是错误的,有些“事实”对于它们要介绍的版本来说也是不正确的。当然,大多数网页对于这些常常为大家所讨论的操作系统的优点还是做出了一些有价值的判断,但是对这些内核本身进行比较的信息却很少。以下站点中的信息相对而言可能是最新的:

    这三个操作系统颇有意思的一点是它们具有很多的相似点。除了命名约定不同,这些操作系统在实现各种概念时都采用了非常相似的方法。每个操作系统都支持线程的分时调度、支持通过“最近未使用页面替换算法”执行请求调页、支持可以实现不同文件系统体系结构的虚拟文件系统层。源于一个操作系统的概念经常被应用到其他操作系统中。例如,Linux 也采用了 Solaris 的
    Slab 内存分配器
    概念。FreeBSD 源代码中的许多术语也出现在 Solaris 中。随着 Sun 开放 Solaris 源代码活动的开展,我希望能够看到各种操作系统更多地相互取长补短。目前,LXR 计划针对 FreeBSD、Linux 和其他与 Unix 相关的操作系统提供了一个源代码相互参照浏览器,您可以从
    fxr.watson.org
    站点访问该浏览器。如果在该站点也能看到 OpenSolaris 源代码,那将是一件令人高兴的事情。
    调度和调度程序
    Solaris、FreeBSD 和 Linux 中的基本调度单元分别是 kthread_t、thread 和 task_struct。Solaris 将每个进程表示为一个 proc_t,而进程中的每个线程都有一个 kthread_t。Linux 用 task_struct 结构来表示进程(和线程)。Linux 中的单线程进程有一个 task_struct。Solaris 中的单线程进程有一个 proc_t、一个 kthread_t 和一个 klwp_t。klwp_t 为在用户和内核模式之间切换的线程提供一个存储区域。FreeBSD 中的单线程进程有一个 proc 结构、一个 thread 结构和一个 ksegrp 结构。ksegrp 是“内核调度实体组”。实际上,这三个操作系统都支持线程调度,其中线程在 Solaris 中为 kthread_t,在 FreeBSD 中为 thread 结构,在 Linux 中为 task_struct。
    调度决策基于优先级。在 Linux 和 FreeBSD 中,优先级值越小,代表的优先级越高。这是一种倒置;越接近 0 的值代表的优先级越高。在 Solaris 中,值越大,代表的优先级越高。
    表 1
    说明了不同操作系统的优先级值。
    表 1. Solaris、Linux 和 FreeBSD 中的调度优先级
    Solaris
    优先级
    调度类
    0-59
    分时、交互、固定、公平份额调度器
    60-99
    系统类
    100-159
    实时(请注意实时调度类的优先级高于系统线程)
    160-169
    低级别中断
    Linux
    优先级
    调度类
    0-99
    系统线程、实时(SCHED_FIFO、SCHED_RR)
    100-139
    用户优先级 (SCHED_NORMAL)
    FreeBSD
    优先级
    调度类
    0-63
    中断
    64-127
    上半部分内核
    128-159
    实时用户(系统线程具有更高的优先级)
    160-223
    分时用户
    224-255
    空闲用户
    这三个操作系统都优先考虑交互式线程/进程。交互式线程的优先级高于与计算机绑定的线程,但是交互式线程获得的时间片较短。Solaris、FreeBSD 和 Linux 都使用每 CPU“运行队列”。FreeBSD 和 Linux 使用“活动”队列和“过期”队列。系统从活动队列中按优先级调度线程。如果某个线程用完其时间片(也可能是为了避免资源匮乏),则它会从活动队列移到过期队列。如果活动队列为空,内核将交换活动队列和过期队列。FreeBSD 还有一个用来容纳“空闲”线程的队列。仅当其他两个队列为空时,才会调度该队列中的线程。Solaris 使用每 CPU“分发队列”。如果线程用完其时间片,内核会为其分配一个新优先级,然后将其放回分发队列。这三个操作系统的“运行队列”对于不同优先级的可运行线程都有单独的链接表。(虽然在 FreeBSD 中每四种优先级使用一个列表,但在 Solaris 和 Linux 中都是每种优先级使用一个单独的列表。)
    Linux 和 FreeBSD 基于运行时间和休眠时间的比(“交互性”度量方法)使用算术运算计算线程的优先级。Solaris 执行表查找。这三个操作系统都不支持“组调度”。实际上,每个操作系统都调度下一个线程而不是调度 n 个线程来运行。这三个操作系统都有利用高速缓存(热关联)和负载平衡的机制。对于超线程 CPU,FreeBSD 具有将多个线程保持在同一 CPU 节点(尽管可能是不同的超线程)上的机制。Solaris 也有类似的机制,不过是在用户和应用程序的控制下,而且并不限于超线程(在 Solaris 中称为“处理器集”,在 FreeBSD 中称为“处理器组”)。
    与其他两个操作系统最大的不同点在于,Solaris 可以同时在系统中支持多个“调度类”。这三个操作系统都支持 Posix SCHED_FIFO、SCHED_RR 和 SCHED_OTHER(或 SCHED_NORMAL)。SCHED_FIFO 和 SCHED_RR 通常导致“实时”线程。(请注意,Solaris 和 Linux 为了支持实时线程都支持内核抢占。)Solaris 支持“固定优先级”类、系统线程(如页出线程)的“系统类”、用于在 X 服务器控制下在窗口环境中运行的线程的“交互式”类,以及用于支持资源管理的公平份额调度器。有关如何使用这些类的信息以及各种类的功能概述,请参见 priocntl(1)。有关特定于公平份额调度器的概述,请参见 FSS(7)。FreeBSD 的调度程序是在编译时选择的,而 Linux 的调度程序取决于 Linux 的版本。
    支持将新调度类添加到系统中是要付出代价的。内核中每个可以制订调度决策(选择要运行的线程的实际操作除外)的地方都有一个用于调用特定于调度类代码的间接函数。例如,当线程将要休眠时,它将调用调度类相关代码,执行该类中线程休眠需要完成的工作。在 Linux 和 FreeBSD 中,调度代码即可执行所需操作,而不再需要一个间接调用。在 Solaris 中,额外的层意味着要花费更多一些的系统开销用于调度(不过提供了更多的功能)。
    内存管理和分页
    在 Solaris 中,每个进程都有一个由称为“段”的逻辑节分区组成的“地址空间”。可通过 pmap(1) 来查看进程地址空间的段。Solaris 将内存管理代码和数据结构分为平台无关和平台相关两个部分。内存管理的平台相关部分位于 HAT(即硬件地址转换)层。FreeBSD 用 vmspace 来描述其进程地址空间(划分为称为区域的逻辑节)。硬件相关部分位于 "pmap"(物理映射)模块中,而 "vmap" 例程处理硬件无关部分和数据结构。Linux 使用内存描述符将进程地址空间划分为称为“存储区”的逻辑节,使用逻辑节来描述进程地址空间。Linux 也使用 pmap 命令来检查进程地址空间。
    Linux 将计算机相关层与软件中较高级别的计算机无关层分开。例如,在 Solaris 和 FreeBSD 中,用来处理页故障的代码大都与计算机无关。在 Linux 中,用来处理页故障的代码(从故障处理开始)绝大多数都与计算机相关。这样 Linux 便可以更快地处理许多分页代码,因为代码中的数据抽象(分层)较少。但是,代价是更改底层硬件或模型时需要对代码进行更多的更改。Solaris 和 FreeBSD 则分别把这些更改隔离到 HAT 层和 pmap 层。
    段、区域和存储区由以下各项来限定:

    • 区域开头的虚拟地址。
    • 它们在由段/区域/存储区映射的对象/文件中的位置。
    • 权限。
    • 映射的大小。

    例如,程序文本位于段/区域/存储区。这三个操作系统中用于管理地址空间的机制十分相似,但是数据结构的名称却完全不同。此外,与其他两个操作系统相比,有更多 Linux 代码依赖于计算机。
    分页
    这三个操作系统都使用最近最少使用算法的变体进行页偷取/替换。它们都有一个用于执行页替换的守护进程/线程。在 FreeBSD 中,会定期或当可用内存不多时唤醒 vm_pageout 守护进程。当可用内存小于某些阈值时,vm_pageout 将运行一个例程 (vm_pageout_scan) 来扫描内存,以尝试释放一些页。vm_pageout_scan 例程在释放已修改的页之前,可能需要先将这些页异步写入磁盘。无论有多少个 CPU,这样的守护进程只有一个。Solaris 有一个 pageout 守护进程,它也会定期运行并且会在可用内存较少时做出响应。在 Solaris 中,分页阈值是在系统启动时自动校准的,这样守护进程便不会由于页出请求而过度使用 CPU 或对磁盘进行泛洪攻击。大多数情况下,FreeBSD 守护进程使用硬编码值或可调值来确定分页阈值。Linux 也使用运行时动态调整的 LRU(Least Recently Used,最近最少使用)算法。在 Linux 中,可以有多个 kswapd 守护进程(每个 CPU 最多一个)。这三个操作系统都使用全局工作集策略(与每进程工作集相对)。
    FreeBSD 有多个页列表用来跟踪最近使用的页。这些列表跟踪“活动”页、“非活动”页、“高速缓存”页和“空闲”页。根据使用情况,将在这些链接表间移动页。经常访问的页将在活动列表中。退出的进程的数据页会立即放入空闲列表。如果 vm_pageout_scan 无法跟上负载变化(例如,如果系统内存不足),FreeBSD 可能会将所有进程全部换出。如果内存严重不足,vm_pageout_scan 将中止系统中最大的进程。
    Linux 也使用不同的页链接表以简化 LRU 样式的算法。Linux 将物理内存分为三个“区域 (zone)”(可能为多组):一个用于 DMA 页,一个用于正常页,一个用于动态分配的内存。这些区域很可能是由 x86 体系结构约束产生的实现详细信息。页在“热”列表、“冷”列表和“空闲”列表间移动。页在这些列表间移动的机制与 FreeBSD 中的非常相似。经常访问的页将在“热”列表中。空闲页将在“冷”列表或“空闲”列表中。
    Solaris 使用空闲列表、散列表和 vnode 页列表来维护其 LRU 替换算法的变体。Solaris 使用“双指针时钟”算法(在《Solaris 内部实现》及其他地方进行了介绍)扫描所有页,而不是扫描 vnode 页列表或散列页列表(相当于 FreeBSD/Linux 实现中的“活动”/“热”列表)。这两个指针之间保持固定的距离。前面的指针通过清除页的引用位使页过期。如果前面的指针访问该页后没有进程引用该页,后面的指针将释放该页(如果该页已被修改,则先将该页异步写入磁盘)。
    这三个操作系统在分页过程中都会考虑 NUMA 本地性。在这三个操作系统中,I/O 高速缓存存储区和虚拟内存页高速缓存都合并到一个系统页高速缓存中。该系统页高速缓存用于读/写文件以及经过 mmap 处理的文件、文本和应用程序数据。
    文件系统
    这三个操作系统都使用数据抽象层来向应用程序隐藏文件系统实现的详细信息。在这三个操作系统中,无论文件数据的底层实现和组织如何,都可以使用 open、close、read、write、stat 等系统调用来访问文件。Solaris 和 FreeBSD 将该机制称为 VFS(virtual file system,虚拟文件系统),其基本数据结构为 vnode(即“虚拟节点”)。在 Solaris 或 FreeBSD 中,会为每个被访问的文件分配一个 vnode。除通用文件信息外,vnode 还包含指向文件系统特定信息的指针。Linux 也使用类似的机制,该机制也称为 VFS(即虚拟文件切换)。在 Linux 中,独立于文件系统的数据结构是 inode。该结构与 Solaris/FreeBSD 中的 vnode 类似。(请注意,在 Solaris/FreeBSD 中也有 inode 结构,但对于 UFS 文件系统,这是与文件系统相关的数据)。Linux 有两个不同的结构,一个用于文件操作,另一个用于 inode 操作。Solaris 和 FreeBSD 将这两种操作合并为“vnode 操作”。
    VFS 允许在系统中实现多种文件系统类型。这意味着这些操作系统可以相互访问对方的文件系统。当然,这要求将相关文件系统例程和数据结构导入相关操作系统的 VFS。这三个操作系统都允许堆叠文件系统。
    表 2
    列出了在各个操作系统中实现的文件系统类型,但未列出所有文件系统类型。
    表 2. 部分文件系统类型列表
    Solaris
    ufs
    缺省本地文件系统(基于 BSD 快速文件系统)
    nfs
    远程文件
    proc
    /proc 文件;请参见 proc(4)
    namefs
    名称文件系统;允许将门/流以文件形式打开
    ctfs
    用于服务管理工具的合同文件系统
    tmpfs
    对临时文件使用匿名空间(内存/交换)
    swapfs
    跟踪匿名空间(数据、堆、栈等)
    objfs
    跟踪内核模块,请参见 objfs(7FS)
    devfs
    跟踪 /devices 文件;请参见 devfs(7FS)
    FreeBSD
    ufs
    缺省本地文件系统(ufs2,基于 BSD 快速文件系统)
    defvs
    跟踪 /dev 文件
    ext2
    Linux ext2 文件系统(基于 GNU)
    nfs
    远程文件
    ntfs
    Windows NT 文件系统
    smbfs
    Samba 文件系统
    portalfs
    将进程挂载到目录中
    kernfs
    包含各种系统信息的文件
    Linux
    ext3
    日志记录,源自 ext2 的基于扩展的文件系统
    ext2
    基于扩展的文件系统
    afs
    AFS 客户机支持远程文件共享
    nfs
    远程文件
    coda
    另一个网络文件系统
    procfs
    进程、处理器、总线和平台的特定信息
    reiserfs
    日志记录文件系统
    结论
    Solaris、FreeBSD 和 Linux 显然彼此都取长补短。随着 Solaris 开放其源代码,这种相互促进有望更快。我个人感觉 Linux 的变化最快。其好处就是新技术能够快速地结合到该系统中。不过,文档(和健壮性)有时相对滞后。Linux 有(有时看上去有)很多开发者。FreeBSD 则大概(在某种意义上)是这三个系统中历史最长的一个。Solaris 来自 BSD Unix 和 AT&T Bell Labs Unix 的结合。Solaris 使用了更多数据抽象分层,因此通常能更容易地支持更多功能。但是,内核中大多数这样的分层都没有记录。随着源代码的开放这一点可能会有所改善。
    突出说明这三个操作系统间差异的简单示例就是页故障处理。在 Solaris 中,发生页故障时,将开始执行特定于平台的陷阱处理程序中的代码,然后调用通用 as_fault() 例程。该例程确定发生故障的段,然后调用“段驱动程序”处理故障。段驱动程序调用文件系统代码。文件系统代码再调用设备驱动程序以换入所需页。页入完成后,段驱动程序调用 HAT 层以更新页表项(或其等效内容)。在 Linux 中,发生页故障时,内核会调用代码来处理故障。系统将立即执行特定于平台的代码。这意味着在 Linux 中可更快地执行故障处理代码,但是 Linux 代码可能不易扩展或导入。
    内核可见性和调试工具对于正确理解系统行为非常重要。您可以阅读源代码,但是相信您很容易误解代码。使用工具验证您对代码工作原理的猜测非常重要。在这一点上,我认为 Solaris 毫无疑问是个赢家,它拥有 kmdb、mdb 和 Dtrace。我对 Solaris 进行了多年的“反向工程”。我发现,解决问题时使用工具常常比阅读源代码要快。至于 Linux,在这方面就不能提供如此多的选择。FreeBSD 允许使用 gdb 来调试内核崩溃转储。gdb 可以设置断点、单步,检查和修改数据以及代码。至于 Linux,下载并安装相应工具后也可以执行这些操作。
    Max Bruning 目前教授 Solaris 内部实现、设备驱动程序、内核(和应用程序)崩溃分析和调试、网络内部实现以及各种专题,并提供咨询。请通过 max@bruningsystems.com 或 http://mbruning.blogspot.com/ 与他联系。
    我大部分时间都在教授 Solaris 内部实现、设备驱动程序以及内核崩溃转储分析和调试方面的课程。向学生解释如何在 Solaris 中实现各个子系统时,他们常常会问“在 Linux 中是怎样实现的呢?”或“在 FreeBSD 中是这样实现的,但在 Solaris中呢?”。本文对内核的三个基本子系统进行了探讨,并对它们在 Solaris 10、Linux 2.6 和 FreeBSD 5.3 中的实现进行了比较。
    本文探讨的三个子系统是调度、内存管理和文件系统体系结构。我之所以选择这些子系统,是因为它们是所有操作系统(不仅是 Unix 和类似于 Unix 的系统)所共有的,而且可能是操作系统中最容易理解的组件。
    本文不会对这些子系统进行深入的研究。要进行深入研究,请参考源代码、各种 Web 站点和有关这方面主题的书籍。以下是相关书籍:

    如果您在 Web 中搜索 Linux、FreeBSD 和 Solaris 的比较,大多数匹配的网页讨论的都是这些操作系统的旧版本(有时是 Solaris 2.5、Linux 2.2 等)。许多“事实”对于最新版本来说都是错误的,有些“事实”对于它们要介绍的版本来说也是不正确的。当然,大多数网页对于这些常常为大家所讨论的操作系统的优点还是做出了一些有价值的判断,但是对这些内核本身进行比较的信息却很少。以下站点中的信息相对而言可能是最新的:

    这三个操作系统颇有意思的一点是它们具有很多的相似点。除了命名约定不同,这些操作系统在实现各种概念时都采用了非常相似的方法。每个操作系统都支持线程的分时调度、支持通过“最近未使用页面替换算法”执行请求调页、支持可以实现不同文件系统体系结构的虚拟文件系统层。源于一个操作系统的概念经常被应用到其他操作系统中。例如,Linux 也采用了 Solaris 的
    Slab 内存分配器
    概念。FreeBSD 源代码中的许多术语也出现在 Solaris 中。随着 Sun 开放 Solaris 源代码活动的开展,我希望能够看到各种操作系统更多地相互取长补短。目前,LXR 计划针对 FreeBSD、Linux 和其他与 Unix 相关的操作系统提供了一个源代码相互参照浏览器,您可以从
    fxr.watson.org
    站点访问该浏览器。如果在该站点也能看到 OpenSolaris 源代码,那将是一件令人高兴的事情。
    调度和调度程序
    Solaris、FreeBSD 和 Linux 中的基本调度单元分别是 kthread_t、thread 和 task_struct。Solaris 将每个进程表示为一个 proc_t,而进程中的每个线程都有一个 kthread_t。Linux 用 task_struct 结构来表示进程(和线程)。Linux 中的单线程进程有一个 task_struct。Solaris 中的单线程进程有一个 proc_t、一个 kthread_t 和一个 klwp_t。klwp_t 为在用户和内核模式之间切换的线程提供一个存储区域。FreeBSD 中的单线程进程有一个 proc 结构、一个 thread 结构和一个 ksegrp 结构。ksegrp 是“内核调度实体组”。实际上,这三个操作系统都支持线程调度,其中线程在 Solaris 中为 kthread_t,在 FreeBSD 中为 thread 结构,在 Linux 中为 task_struct。
    调度决策基于优先级。在 Linux 和 FreeBSD 中,优先级值越小,代表的优先级越高。这是一种倒置;越接近 0 的值代表的优先级越高。在 Solaris 中,值越大,代表的优先级越高。
    表 1
    说明了不同操作系统的优先级值。
    表 1. Solaris、Linux 和 FreeBSD 中的调度优先级
    Solaris
    优先级
    调度类
    0-59
    分时、交互、固定、公平份额调度器
    60-99
    系统类
    100-159
    实时(请注意实时调度类的优先级高于系统线程)
    160-169
    低级别中断
    Linux
    优先级
    调度类
    0-99
    系统线程、实时(SCHED_FIFO、SCHED_RR)
    100-139
    用户优先级 (SCHED_NORMAL)
    FreeBSD
    优先级
    调度类
    0-63
    中断
    64-127
    上半部分内核
    128-159
    实时用户(系统线程具有更高的优先级)
    160-223
    分时用户
    224-255
    空闲用户
    这三个操作系统都优先考虑交互式线程/进程。交互式线程的优先级高于与计算机绑定的线程,但是交互式线程获得的时间片较短。Solaris、FreeBSD 和 Linux 都使用每 CPU“运行队列”。FreeBSD 和 Linux 使用“活动”队列和“过期”队列。系统从活动队列中按优先级调度线程。如果某个线程用完其时间片(也可能是为了避免资源匮乏),则它会从活动队列移到过期队列。如果活动队列为空,内核将交换活动队列和过期队列。FreeBSD 还有一个用来容纳“空闲”线程的队列。仅当其他两个队列为空时,才会调度该队列中的线程。Solaris 使用每 CPU“分发队列”。如果线程用完其时间片,内核会为其分配一个新优先级,然后将其放回分发队列。这三个操作系统的“运行队列”对于不同优先级的可运行线程都有单独的链接表。(虽然在 FreeBSD 中每四种优先级使用一个列表,但在 Solaris 和 Linux 中都是每种优先级使用一个单独的列表。)
    Linux 和 FreeBSD 基于运行时间和休眠时间的比(“交互性”度量方法)使用算术运算计算线程的优先级。Solaris 执行表查找。这三个操作系统都不支持“组调度”。实际上,每个操作系统都调度下一个线程而不是调度 n 个线程来运行。这三个操作系统都有利用高速缓存(热关联)和负载平衡的机制。对于超线程 CPU,FreeBSD 具有将多个线程保持在同一 CPU 节点(尽管可能是不同的超线程)上的机制。Solaris 也有类似的机制,不过是在用户和应用程序的控制下,而且并不限于超线程(在 Solaris 中称为“处理器集”,在 FreeBSD 中称为“处理器组”)。
    与其他两个操作系统最大的不同点在于,Solaris 可以同时在系统中支持多个“调度类”。这三个操作系统都支持 Posix SCHED_FIFO、SCHED_RR 和 SCHED_OTHER(或 SCHED_NORMAL)。SCHED_FIFO 和 SCHED_RR 通常导致“实时”线程。(请注意,Solaris 和 Linux 为了支持实时线程都支持内核抢占。)Solaris 支持“固定优先级”类、系统线程(如页出线程)的“系统类”、用于在 X 服务器控制下在窗口环境中运行的线程的“交互式”类,以及用于支持资源管理的公平份额调度器。有关如何使用这些类的信息以及各种类的功能概述,请参见 priocntl(1)。有关特定于公平份额调度器的概述,请参见 FSS(7)。FreeBSD 的调度程序是在编译时选择的,而 Linux 的调度程序取决于 Linux 的版本。
    支持将新调度类添加到系统中是要付出代价的。内核中每个可以制订调度决策(选择要运行的线程的实际操作除外)的地方都有一个用于调用特定于调度类代码的间接函数。例如,当线程将要休眠时,它将调用调度类相关代码,执行该类中线程休眠需要完成的工作。在 Linux 和 FreeBSD 中,调度代码即可执行所需操作,而不再需要一个间接调用。在 Solaris 中,额外的层意味着要花费更多一些的系统开销用于调度(不过提供了更多的功能)。
    内存管理和分页
    在 Solaris 中,每个进程都有一个由称为“段”的逻辑节分区组成的“地址空间”。可通过 pmap(1) 来查看进程地址空间的段。Solaris 将内存管理代码和数据结构分为平台无关和平台相关两个部分。内存管理的平台相关部分位于 HAT(即硬件地址转换)层。FreeBSD 用 vmspace 来描述其进程地址空间(划分为称为区域的逻辑节)。硬件相关部分位于 "pmap"(物理映射)模块中,而 "vmap" 例程处理硬件无关部分和数据结构。Linux 使用内存描述符将进程地址空间划分为称为“存储区”的逻辑节,使用逻辑节来描述进程地址空间。Linux 也使用 pmap 命令来检查进程地址空间。
    Linux 将计算机相关层与软件中较高级别的计算机无关层分开。例如,在 Solaris 和 FreeBSD 中,用来处理页故障的代码大都与计算机无关。在 Linux 中,用来处理页故障的代码(从故障处理开始)绝大多数都与计算机相关。这样 Linux 便可以更快地处理许多分页代码,因为代码中的数据抽象(分层)较少。但是,代价是更改底层硬件或模型时需要对代码进行更多的更改。Solaris 和 FreeBSD 则分别把这些更改隔离到 HAT 层和 pmap 层。
    段、区域和存储区由以下各项来限定:

    • 区域开头的虚拟地址。
    • 它们在由段/区域/存储区映射的对象/文件中的位置。
    • 权限。
    • 映射的大小。

    例如,程序文本位于段/区域/存储区。这三个操作系统中用于管理地址空间的机制十分相似,但是数据结构的名称却完全不同。此外,与其他两个操作系统相比,有更多 Linux 代码依赖于计算机。
    分页
    这三个操作系统都使用最近最少使用算法的变体进行页偷取/替换。它们都有一个用于执行页替换的守护进程/线程。在 FreeBSD 中,会定期或当可用内存不多时唤醒 vm_pageout 守护进程。当可用内存小于某些阈值时,vm_pageout 将运行一个例程 (vm_pageout_scan) 来扫描内存,以尝试释放一些页。vm_pageout_scan 例程在释放已修改的页之前,可能需要先将这些页异步写入磁盘。无论有多少个 CPU,这样的守护进程只有一个。Solaris 有一个 pageout 守护进程,它也会定期运行并且会在可用内存较少时做出响应。在 Solaris 中,分页阈值是在系统启动时自动校准的,这样守护进程便不会由于页出请求而过度使用 CPU 或对磁盘进行泛洪攻击。大多数情况下,FreeBSD 守护进程使用硬编码值或可调值来确定分页阈值。Linux 也使用运行时动态调整的 LRU(Least Recently Used,最近最少使用)算法。在 Linux 中,可以有多个 kswapd 守护进程(每个 CPU 最多一个)。这三个操作系统都使用全局工作集策略(与每进程工作集相对)。
    FreeBSD 有多个页列表用来跟踪最近使用的页。这些列表跟踪“活动”页、“非活动”页、“高速缓存”页和“空闲”页。根据使用情况,将在这些链接表间移动页。经常访问的页将在活动列表中。退出的进程的数据页会立即放入空闲列表。如果 vm_pageout_scan 无法跟上负载变化(例如,如果系统内存不足),FreeBSD 可能会将所有进程全部换出。如果内存严重不足,vm_pageout_scan 将中止系统中最大的进程。
    Linux 也使用不同的页链接表以简化 LRU 样式的算法。Linux 将物理内存分为三个“区域 (zone)”(可能为多组):一个用于 DMA 页,一个用于正常页,一个用于动态分配的内存。这些区域很可能是由 x86 体系结构约束产生的实现详细信息。页在“热”列表、“冷”列表和“空闲”列表间移动。页在这些列表间移动的机制与 FreeBSD 中的非常相似。经常访问的页将在“热”列表中。空闲页将在“冷”列表或“空闲”列表中。
    Solaris 使用空闲列表、散列表和 vnode 页列表来维护其 LRU 替换算法的变体。Solaris 使用“双指针时钟”算法(在《Solaris 内部实现》及其他地方进行了介绍)扫描所有页,而不是扫描 vnode 页列表或散列页列表(相当于 FreeBSD/Linux 实现中的“活动”/“热”列表)。这两个指针之间保持固定的距离。前面的指针通过清除页的引用位使页过期。如果前面的指针访问该页后没有进程引用该页,后面的指针将释放该页(如果该页已被修改,则先将该页异步写入磁盘)。
    这三个操作系统在分页过程中都会考虑 NUMA 本地性。在这三个操作系统中,I/O 高速缓存存储区和虚拟内存页高速缓存都合并到一个系统页高速缓存中。该系统页高速缓存用于读/写文件以及经过 mmap 处理的文件、文本和应用程序数据。
    文件系统
    这三个操作系统都使用数据抽象层来向应用程序隐藏文件系统实现的详细信息。在这三个操作系统中,无论文件数据的底层实现和组织如何,都可以使用 open、close、read、write、stat 等系统调用来访问文件。Solaris 和 FreeBSD 将该机制称为 VFS(virtual file system,虚拟文件系统),其基本数据结构为 vnode(即“虚拟节点”)。在 Solaris 或 FreeBSD 中,会为每个被访问的文件分配一个 vnode。除通用文件信息外,vnode 还包含指向文件系统特定信息的指针。Linux 也使用类似的机制,该机制也称为 VFS(即虚拟文件切换)。在 Linux 中,独立于文件系统的数据结构是 inode。该结构与 Solaris/FreeBSD 中的 vnode 类似。(请注意,在 Solaris/FreeBSD 中也有 inode 结构,但对于 UFS 文件系统,这是与文件系统相关的数据)。Linux 有两个不同的结构,一个用于文件操作,另一个用于 inode 操作。Solaris 和 FreeBSD 将这两种操作合并为“vnode 操作”。
    VFS 允许在系统中实现多种文件系统类型。这意味着这些操作系统可以相互访问对方的文件系统。当然,这要求将相关文件系统例程和数据结构导入相关操作系统的 VFS。这三个操作系统都允许堆叠文件系统。
    表 2
    列出了在各个操作系统中实现的文件系统类型,但未列出所有文件系统类型。
    表 2. 部分文件系统类型列表
    Solaris
    ufs
    缺省本地文件系统(基于 BSD 快速文件系统)
    nfs
    远程文件
    proc
    /proc 文件;请参见 proc(4)
    namefs
    名称文件系统;允许将门/流以文件形式打开
    ctfs
    用于服务管理工具的合同文件系统
    tmpfs
    对临时文件使用匿名空间(内存/交换)
    swapfs
    跟踪匿名空间(数据、堆、栈等)
    objfs
    跟踪内核模块,请参见 objfs(7FS)
    devfs
    跟踪 /devices 文件;请参见 devfs(7FS)
    FreeBSD
    ufs
    缺省本地文件系统(ufs2,基于 BSD 快速文件系统)
    defvs
    跟踪 /dev 文件
    ext2
    Linux ext2 文件系统(基于 GNU)
    nfs
    远程文件
    ntfs
    Windows NT 文件系统
    smbfs
    Samba 文件系统
    portalfs
    将进程挂载到目录中
    kernfs
    包含各种系统信息的文件
    Linux
    ext3
    日志记录,源自 ext2 的基于扩展的文件系统
    ext2
    基于扩展的文件系统
    afs
    AFS 客户机支持远程文件共享
    nfs
    远程文件
    coda
    另一个网络文件系统
    procfs
    进程、处理器、总线和平台的特定信息
    reiserfs
    日志记录文件系统
    结论
    Solaris、FreeBSD 和 Linux 显然彼此都取长补短。随着 Solaris 开放其源代码,这种相互促进有望更快。我个人感觉 Linux 的变化最快。其好处就是新技术能够快速地结合到该系统中。不过,文档(和健壮性)有时相对滞后。Linux 有(有时看上去有)很多开发者。FreeBSD 则大概(在某种意义上)是这三个系统中历史最长的一个。Solaris 来自 BSD Unix 和 AT&T Bell Labs Unix 的结合。Solaris 使用了更多数据抽象分层,因此通常能更容易地支持更多功能。但是,内核中大多数这样的分层都没有记录。随着源代码的开放这一点可能会有所改善。
    突出说明这三个操作系统间差异的简单示例就是页故障处理。在 Solaris 中,发生页故障时,将开始执行特定于平台的陷阱处理程序中的代码,然后调用通用 as_fault() 例程。该例程确定发生故障的段,然后调用“段驱动程序”处理故障。段驱动程序调用文件系统代码。文件系统代码再调用设备驱动程序以换入所需页。页入完成后,段驱动程序调用 HAT 层以更新页表项(或其等效内容)。在 Linux 中,发生页故障时,内核会调用代码来处理故障。系统将立即执行特定于平台的代码。这意味着在 Linux 中可更快地执行故障处理代码,但是 Linux 代码可能不易扩展或导入。
    内核可见性和调试工具对于正确理解系统行为非常重要。您可以阅读源代码,但是相信您很容易误解代码。使用工具验证您对代码工作原理的猜测非常重要。在这一点上,我认为 Solaris 毫无疑问是个赢家,它拥有 kmdb、mdb 和 Dtrace。我对 Solaris 进行了多年的“反向工程”。我发现,解决问题时使用工具常常比阅读源代码要快。至于 Linux,在这方面就不能提供如此多的选择。FreeBSD 允许使用 gdb 来调试内核崩溃转储。gdb 可以设置断点、单步,检查和修改数据以及代码。至于 Linux,下载并安装相应工具后也可以执行这些操作。


    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/23363/showart_2154450.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP