本文为InfoQ中文站特供稿件。首发地址为: http://www.infoq.com/cn/articles/rust-core-components 。如需转载。请与InfoQ中文站联系。html
原文发表于2015年12月22日,现依据以前约定将其全文转发到我(Liigo)我的博客里。git
Rust是一门强调安全、并发、高效的系统编程语言。无GC实现内存安全机制、无数据竞争的并发机制、无执行时开销的抽象机制。是Rust独特的优越特性。它声称攻克了传统C语言和C++语言几十年来饱受责难的内存安全问题,同一时候还保持了很是高的执行效率、很是深的底层控制、很是广的应用范围,在系统编程领域具备强劲的竞争力和广阔的应用前景。github
从狭义的角度说。Rust编程语言。就是其语言自己,一份以人类语言描写叙述的计算机编程语言的规范文档。编程
然而单单语言自己,仅具备理论价值;要发挥其有用价值,每每还要有编译器、标准库、执行环境等一系列配套设施。共同组成一套完整的生态体系。后端
从广义的角度说,Rust编程语言包括了:语言规范(reference)、编译器(rustc)、执行时(runtime)、标准库(std)、核心库(core)、库(crates)、包管理器(cargo)、社区(communities)等等。安全
本文将比較具体的介绍广义上的Rust编程语言各个组成部分。markdown
Rust语言规范规定了Rust编程语言的语法和语义。跟其它语言规范同样。充满枯燥的文字。真正愿意通读下来的人很是少。大多数人经过0基础教程学习语言的基本的语法和语义。仅在必要时翻阅或查阅语言规范的局部内容。(严格来讲。Rust眼下提供的这份文档并不算是语言规范文档(specification),而仅仅仅仅是參考文档。)网络
官方的rustc是眼下惟一的Rust编译器(以前的rustboot编译器早就被废弃了)。它负责把Rust源码编译为可执行文件、Rust库(crates)或其它库文件(.a/.lib/.so/.dll)。多线程
rustc是跨平台的应用程序,其可执行文件名称是 rustc (for Unix/Linux/…) 或 rustc.exe (for Windows),最基本的命令行调用方法是 rustc hello.rs
。并发
rustc具备交叉编译功能,可以在当前平台下编译出可执行于其它平台的应用程序和库(但需要事先编译或安装目标平台的工具链)。
rustc採用LLVM做为编译器后端,具备很是好的代码生成和优化技术。支持不少目标平台。
rustc眼下使用gcc做为连接器(同一时候也执行时依赖glibc执行库,从此可换用MUSL静态库,相关开发工做在进行中);从此在Windows平台将支持使用MSVC做为连接器(相关开发工做在进行中)。
rustc编译出来的程序,支持用GDB和LLDB调试执行。用户不需要更换本身已经熟悉的调试工具,Rust没有也不需要本身专属的调试器。
rustc是用Rust语言开发的,而且是开源的,最新源码在这里:https://github.com/rust-lang/rust/tree/master/src/librustc
在没有明白上下文的状况下,执行时(runtime)一般可被理解为“执行时库(runtime library)”或“执行时损耗(runtime overhead)”。
如下就这两种状况分别阐述。最后得出的结论是:Rust可以没有执行时库,且仅有很是小的执行时损耗。
编程语言的执行时库,一般理解为。其编译出的可执行程序在执行时必须依赖的非操做系统自己的动态库。好比C程序必须依赖msvcrt或glibc,Java程序必须依赖JRE。VB程序必须依赖msvbvm,易语言程序必须依赖krnln.fne/fnr,等等。因为C执行时库每每跟操做系统紧密集成(尤为是类Unix系统),可以以为C执行时库是操做系统的一部分。进而以为C没有执行时库(固然这里见仁见智)。
假设认同这一点。那么。通过静态编译生成的Rust程序。执行时仅依赖C执行时库。也就可以以为没有执行时库了。
即便不认同这一点。等之后Rust支持了静态连接MUSL库(同一时候抛弃掉glibc)。依旧可以作到没有执行时库。固然,动态编译的Rust程序中执行时仍是必须依赖标准库libstd-*.so等动态库的,这是给予程序猿的额外可选项。
说Rust“可以”没有执行时库。就是说执行时库不必的,程序猿拥有选择权(而不是被迫必须接受执行时库)。
那为何说没有执行时库是一个优点呢?因为执行时库自己也有平台依赖性和/或执行时依赖性,有执行时库就意味着,你的程序仅仅能在执行时库所支持的平台下执行,也就是说它限制了程序的部署平台。
而执行时库支持哪些平台并不是程序猿个体所能决定的。
就算执行时库官方开发商决定向新的平台移植。也每每受诸多因素干扰,好比十多年前试图将JRE移植到手机平台时就破费周折,甚至不得不大幅删减功能、人为制造了残缺不全的手机版JRE。再试想,在一个没有网络系统、没有文件系统,甚至没有操做系统的嵌入式平台上,你有可能在上面跑JRE环境吗?作梦。
没有了执行时库。程序的所有代码都是程序猿可控的(至于标准库的影响,下文将会谈到)。
(更宽泛地说,执行时库居无定形。未必必定以独立动态库的形式存在,它也可能隐身于标准库甚至是可执行文件内部。
仅仅要它给程序自己带来了额外的且没法消除的明显的依赖和不可忽略的执行时损耗,咱们就统统以为它是执行时(库)。反过来讲。假设执行时(库)的执行时损耗小到必定程度,且没有带来额外的执行时依赖,咱们甚至可以以为它不是执行时(库)。此中斟酌。见仁见智。)
程序的执行时损耗。是指程序在执行过程当中所必须付出的额外的代价。好比Java的虚拟机、C#的垃圾回收器、脚本语言的解释器等等。这些子系统自己在执行时都会消耗数量可观的内存和CPU。影响程序和系统的执行性能。而Rust没有虚拟机、垃圾回收器和解释器。因此没有这类执行时损耗。
此外,内存管理、栈管理、调用操做系统API和C库等各类状况下,都有可能产生额外的执行时损耗。
Rust执行时需要每一个函数执行morestack检查栈溢出(morestack已被取消),为了内存安全这是“必需的”检查。而以C语言的思路去看可能就是“额外的”损耗。无论怎样这项执行时损耗很是小。Unwinding仅发生在panic以后,不视为执行时损耗。
Rust採用jemalloc管理内存(也可禁用)。不只没有执行时损耗。反而带来执行效率的明显提高。
Rust的Rc类型以引用计数管理对象内存,Arc类型以Atomic引用计数管理对象内存,这是较小的执行时损耗。
但假设程序猿不主动使用Rc/Arc类型,则无需为此付出额外的代价。
(Go语言的协程调度器。固然也有执行时损耗,但这在某种程度上是程序实现自身功能的必要,算不上“额外的”代价。假设不需要此功能则损耗很是小,故本文做者不视其为执行时损耗。
而其经过channel共享内存、管理逐步连续增加的栈、调用C库和系统API,则被视为执行时损耗,因为这些都是“非必要的”损耗,而且损耗还不小。)
(Java的JIT编译器在执行时把字节码编译为机器码,算不算执行时损耗呢?损耗确定是有的,但仅在特定条件下触发,且其带来的收益可能远大于损耗。是提高执行性能的必要步骤。故本文做者不以为它引入了“额外的”代价,不视其为执行时损耗。而Java的虚拟机和垃圾收集器,显然是突出的执行时损耗。)
Rust的标准库,为绝大多数的、常规的Rust程序开发提供基础支持、跨平台支持。是应用范围最广、地位最重要的库(没有之中的一个)。其规模居中,既不像传统C和C++标准库那么简陋,也不像Java和.Net标准库那样一应俱全。
Rust标准库的内容大体概括例如如下:
基础的接口性数据类型
如 Copy, Send, Sized, Sync, Drop, Deref, Clone, Iterator, IntoIterator, Debug, Display, Option, Result, Error, Eq, Ord, Fn, Cell, Hash 等等。当中多数都被包括在 std::prelude 内。
这些简明扼要的类型,构成了Rust生态系统的基石。假设标准库不提供这些类型。让第三方库各行其是的话。整个生态系统将很是难造成协力。
基础类型操做接口
如 bool, char, i8/u8, i16/u16, i32/u32, i64/u64, isize/usize, f32/f64, str/array/slice/tuple/pointer 等基础类型数据的操做接口及事实上现。
常用的功能性数据类型
如 String, Vec, HashMap, Rc, Arc, Box, CString, OsString, SipHasher 等等。
知足常见的、常用的,或特定的功能需求。
常用的宏定义
如 println!, format!, assert!, try!, panic!, vec!, thread_local!, file!, line!, include! 等等。
基础的或核心的宏。当中某些宏是借助编译器实现的。
跨平台的I/O相关的系统功能
如 std::io, std::fs, std::path, std::env, std::process 等等。
跨平台的网络/多线程/同步相关系统功能
如 std::net, std::thread, std::sync 等等。
其它的不跨平台的操做系统相关功能
如 std::os。为各主流操做系统分别提供了专门的操做接口,便于实现系统特有的功能调用。
底层操做接口
如 std::mem, std::ptr, std::intrinsics 等。操做内存、指针、调用编译器固有函数。
其它等等
Rust核心库,可以理解为是通过大幅精简的标准库。它被应用在标准库不能覆盖到的某些少数特定领域,如嵌入式开发。
前面提到过,标准库应用范围很是广,为绝大多数应用程序提供支持。但是在嵌入式开发、操做系统开发、裸金属(bare metal)环境下,标准库就无能为力了。主要有如下两个缘由致使标准库的应用范围受到必定的限制:
标准库的“跨平台”是指“跨主流操做系统平台”,也就是跨 Windows、Unix/Linux、Mac/OSX 等少数几个操做系统。
标准库内有至关数量的API(如文件、网络、多线程等)必须依赖操做系统提供的接口,到了非主流系统尤为是嵌入式系统环境下,标准库失去了底层系统的支撑根本就不可能工做。
标准库内有至关数量的API(如String/Vec、Box、panic等)依赖内存申请和释放功能,但是在操做系统开发、裸金属(bare metal)环境下,要么不存在这些功能。要么需要本身开发。
这些限制对Rust标准库来讲事实上并不是问题。跟世界上大多数编程语言的标准库同样,为主流系统的主流应用开发提供丰富的功能支持,才是最重要的。
假设单纯为了提高应用范围砍掉操做系统相关的功能,那标准库也大概成了空壳子,功能性和有用性大打折扣,完全失去了标准库的价值——谁能接受一个连文件、网络、多线程功能都没有的标准库呢?
Rust的选择是,在标准库以外。再单独提供一个核心库,重点应对嵌入式应用开发。核心库不依赖不论什么操做系统,也不提供文件/网络/多线程/内存申请释放相关的不论什么功能,于是可移植性更好、应用范围更广。当用Rust开发一个操做系统或硬件驱动或嵌入式应用时,你总不能期望去调用别的主流操做系统接口吧?那显然是不切实际的。因此对核心库来讲。它缺乏的那些OS相关功能本来就是多余的。
在代码开头写上 #![no_std]
就表明放弃标准库。而使用核心库。核心库里面有:基础的接口性数据类型(參见上文。下同)、基础类型操做接口、常用的功能性数据类型、常用的宏定义、底层操做接口等,而且跟标准库API差点儿是全然一致的;再配合alloc库(或本身定制的alloc库)又有了内存申请释放功能;再加上collections库。String/Vec/HashMap等也有了。
事实上从内部实现来讲。标准库里的某些功能正是来源于核心库(以及alloc/collections等)。
把多个Rust源码文件(后缀名.rs)放一块儿编译出来,就获得一个库。库一般以静态库.rlib或动态库.so/.dll的形式存在。咱们称Rust库为crate,就像别的语言把库称为library或package差点儿相同一个意思。仅仅是习惯上的命名不一样。
库是Rust程序猿共享代码和功能的基本单元。
编写应用程序和软件,无非就是综合利用各类库,官方的库、本身的库、第三方的库,调用它们提供的接口(API)。再融合本身的业务逻辑。终于达成目的。
在已经编译或安装了某个库xxx的前提下,要想调用这个库。需首先在源码首部增长这么一行代码:
extern crate xxx;
咱们不需要像Java操心CLASSPATH同样操心Rust库的载入路径,因为咱们有Cargo(如下会讲到)。因为咱们有静态编译。
眼下Rust已经有了大概3000多个公开的第三方库,所有集中在 crates.io 站点上(如下也会讲到)。这些库绝大多数都是Github上面的开源项目。
我好像极少听到有谁公布二进制的库(而不是公布源码)。
Cargo是Rust官方提供的包管理器(package manager),类似于Java界的Gradle。Cargo负责下载库源码,分析库的依赖项,下载依赖项的源码,再分析依赖项的依赖项,如此这般,终于把他们逐个编译出来。一句话,就是处理下载(源码)、依赖(第三方库)、和编译(生成库或可执行文件)。
有了Cargo,无论多复杂的项目,无论有多复杂的依赖项,也仅仅需在项目根文件夹下执行这么一条命令:
cargo build
Cargo包管理器跟crates.io站点造成了完整的生态系统。
crates.io就是一个中心仓库,全世界差点儿所有的Rust项目都被整合在此仓库中。每一个项目都包括了一个Cargo.toml的配置文件,指定了自身的依赖项。
Cargo就是环绕Cargo.toml开展工做的。
在C和C++的世界里。假设一个开源项目没有不论什么依赖,每每会被看成一项长处。因为你们都知道。编译带有依赖项的源码项目是很是麻烦的。尤为是当依赖项又有依赖项的时候,尤为是当依赖项的版本号号又不明白的时候。几十年了,都没出现一个被普遍接受的基于版本号的依赖管理和编译工具,颇为遗憾。
Rust不同,它一開始就有了Cargo。
Cargo是一个使人骄傲的优秀的工具。
它不只是一个工具。更是一个生态系统。
Rust有至关庞大的社区。仅參与开发Rust系统自己的开发人员就多达1300人,并持续增加。这类开发人员中,以Mozilla公司员工组成的约10人团队为核心,以来自世界各地的贡献者为辅助。
採用Rust开发应用的开发人员人数不少其它,但难以统计数量。固然,做为新兴语言,Rust社区规模相对Java、Python社区而言还稚嫩的很是,发展潜力无限。
Rust开发人员活动轨迹主要集中在Github站点、IRC在线聊天室、Reddit论坛和Rust官方论坛中。此外,环绕某些颇具雄心的项目还各自造成了独立子社区。如Servo、Piston、MaidSafe、Redox等。
源码仓库、设计开发讨论区:
- https://github.com/rust-lang/rust
- https://github.com/rust-lang/rfcs
- https://github.com/rust-lang/cargo
- https://internals.rust-lang.org
- https://client00.chat.mibbit.com/?server=irc.mozilla.org&channel=%23rustc
用户应用讨论提问区:
- https://www.reddit.com/r/rust
- https://users.rust-lang.org
- https://stackoverflow.com/questions/tagged/rust
- https://client00.chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
官方站点:
- https://www.rust-lang.org
- https://www.rust-lang.org/community.html
- http://blog.rust-lang.org
- https://crates.io
- http://this-week-in-rust.org
中文用户讨论区
- http://rust.cc
本文较具体的逐个介绍了Rust编程语言及其编译器、执行时、库、工具和社区等等核心部件,这些部件共同构成生机勃发的Rust生态系统。