mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-19 22:51:41 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
2410734221
115
published/20170921 The Rise and Rise of JSON.md
Normal file
115
published/20170921 The Rise and Rise of JSON.md
Normal file
@ -0,0 +1,115 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (runningwater)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: subject: (The Rise and Rise of JSON)
|
||||
[#]: via: (https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html)
|
||||
[#]: author: (https://twobithistory.org)
|
||||
[#]: url: (https://linux.cn/article-10440-1.html)
|
||||
|
||||
JSON 的兴起与崛起
|
||||
======
|
||||
|
||||
JSON 已经占领了全世界。当今,任何两个应用程序彼此通过互联网通信时,可以打赌它们在使用 JSON。它已被所有大型企业所采用:十大最受欢迎的 web API 接口列表中(主要由 Google、Facebook 和 Twitter 提供),仅仅只有一个 API 接口是以 XML 的格式开放数据的。[^1] 这个列表中的 Twitter API 为此做了一个鲜活的注脚:其对 XML 格式的支持到 2013 年结束,其时发布的新版本的 API 取消 XML 格式,转而仅使用 JSON。JSON 也在程序编码级别和文件存储上被广泛采用:在 Stack Overflow(LCTT 译注:一个面向程序员的问答网站)上,现在更多的是关于 JSON 的问题,而不是其他的数据交换格式。[^2]
|
||||
|
||||
![][1]
|
||||
|
||||
XML 仍然在很多地方存在。网络上它被用于 SVG 和 RSS / Atom 信息流。Android 开发者想要获得用户权限许可时,需要在其 APP 的 `manifest` 文件中声明 —— 此文件是 XML 格式的。XML 的替代品也不仅仅只有 JSON,现在有很多人在使用 YAML 或 Google 的 Protocol Buffers 等技术,但这些技术的受欢迎程度远不如 JSON。目前来看,JSON 是应用程序在网络之间通信的首选协议格式。
|
||||
考虑到自 2005 年来 Web 编程世界就垂涎于 “异步 JavaScript 和 XML” 而非 “异步 JavaScript 和 JSON” 的技术潜力,你可以发现 JSON 的主导地位是如此的让人惊讶。当然了,这可能与这两种通信格式的受欢迎程度无关,而仅反映出缩写 “AJAX” 似乎比 “AJAJ” 更具吸引力。但是,即使在 2005 年有些人(实际上没有太多人)已经用 JSON 来取代 XML 了,我们不禁要问为什么 XML 的噩运来的如此之快,以至于短短十来年,“异步 JavaScript 和 XML” 这个名称就成为一个很讽刺的误称。那这十来年发生了什么?JSON 怎么会在那么多应用程序中取代了 XML?现在被全世界工程师和系统所使用、依赖的这种数据格式是谁提出的?
|
||||
|
||||
### JSON 之诞生
|
||||
|
||||
2001 年 4 月,首个 JSON 格式的消息被发送出来。此消息是从旧金山湾区某车库的一台计算机发出的,这是计算机历史上重要的的时刻。Douglas Crockford 和 Chip Morningstar 是一家名为 State Software 的技术咨询公司的联合创始人,他们当时聚集在 Morningstar 的车库里测试某个想法,发出了此消息。
|
||||
|
||||
在 “AJAX” 这个术语被创造之前,Crockford 和 Morningstar 就已经在尝试构建好用的 AJAX 应用程序了,可是浏览器对其兼容性不好。他们想要在初始页面加载后就将数据传递给应用程序,但其目标要针对所有的浏览器,这就实现不了。
|
||||
|
||||
这在今天看来不太可信,但是要记得 2001 年的时候 Internet Explorer(IE)代表了网页浏览器的最前沿技术产品。早在 1999 年的时候,Internet Explorer 5 就支持了原始形式的 `XMLHttpRequest`,开发者可以使用名为 ActiveX 的框架来访问此对象。Crockford 和 Morningstar 能够使用此技术(在 IE 中)来获取数据,但是在 Netscape 4 中(这是他们想要支持的另一种浏览器)就无法使用这种解决方案。为此 Crockford 和 Morningstar 只得使用一套不同的系统以兼容不同的浏览器。
|
||||
|
||||
第一条 JSON 消息如下所示:
|
||||
|
||||
```
|
||||
<html><head><script>
|
||||
document.domain = 'fudco';
|
||||
parent.session.receive(
|
||||
{ to: "session", do: "test",
|
||||
text: "Hello world" }
|
||||
)
|
||||
</script></head></html>
|
||||
```
|
||||
|
||||
消息中只有一小部分类似于今天我们所知的 JSON,本身其实是一个包含有一些 JavaScript 的 HTML 文档。类似于 JSON 的部分只是传递给名为 `receive()` 的函数的 JavaScript 对象字面量。
|
||||
|
||||
Crockford 和 Morningstar 决定滥用 HTML 的帧(`<frame>`)以发送数据。他们可以让一个帧指向一个返回的上述 HTML 文档的 URL。当接收到 HTML 时,JavaScript 代码段就会运行,就可以把数据对象字面量如实地传递回应用程序。只要小心的回避浏览器保护策略(即子窗口不允许访问父窗口),这种技术就可以正常运行无误。可以看到 Crockford 和 Mornginstar 通过明确地设置文档域这种方法来达到其目的。(这种基于帧的技术,有时称为隐藏帧技术,通常在 90 年代后期,即在广泛使用 XMLHttpRequest 技术之前使用。[^3] )
|
||||
|
||||
第一个 JSON 消息的惊人之处在于,它显然不是一种新的数据格式的首次使用。它就是 JavaScript!实际上,以此方式使用 JavaScript 的想法如此简单,Crockford 自己也说过他不是第一个这样做的人。他说 Netscape 公司的某人早在 1996 年就使用 JavaScript 数组字面量来交换信息。[^4] 因为消息就是 JavaScript,其不需要任何特殊解析工作,JavaScript 解释器就可搞定一切。
|
||||
|
||||
最初的 JSON 信息实际上与 JavaScript 解释器发生了冲突。JavaScript 保留了大量的关键字(ECMAScript 6 版本就有 64 个保留字),Crockford 和 Morningstar 无意中在其 JSON 中使用了一个保留字。他们使用了 `do` 作为了键名,但 `do` 是解释器中的保留字。因为 JavaScript 使用的保留字太多了,Crockford 做了决定:既然不可避免的要使用到这些保留字,那就要求所有的 JSON 键名都加上引号。被引起来的键名会被 JavaScript 解释器识别成字符串,其意味着那些保留字也可以放心安全的使用。这就为什么今天 JSON 键名都要用引号引起来的原因。
|
||||
|
||||
Crockford 和 Morningstar 意识到这技术可以应用于各类应用系统。想给其命名为 “JSML”,即 <ruby>JavaScript 标记语言<rt>JavaScript Markup Language</rt></ruby>的意思,但发现这个缩写已经被一个名为 Java Speech 标记语言的东西所使用了。因此他们决定采用 “JavaScript Object Notation”,缩写为 JSON。他们开始向客户推销,但很快发现客户不愿意冒险使用缺乏官方规范的未知技术。所以 Crockford 决定写一个规范。
|
||||
|
||||
2002 年,Crockford 买下了 [JSON.org][2] 域名,放上了 JSON 语法及一个解释器的实例例子。该网站仍然在运行,现在已经包含有 2013 年正式批准的 JSON ECMA 标准的显著链接。在该网站建立后,Crockford 并没有过多的推广,但很快发现很多人都在提交各种不同编程语言的 JSON 解析器实现。JSON 的血统显然与 JavaScript 相关联,但很明显 JSON 非常适合于不同语言之间的数据交换。
|
||||
|
||||
### AJAX 导致的误会
|
||||
|
||||
2005 年,JSON 有了一次大爆发。那一年,一位名叫 Jesse James Garrett 的网页设计师和开发者在博客文章中创造了 “AJAX” 一词。他很谨慎地强调:AJAX 并不是新技术,而是 “好几种蓬勃发展的技术以某种强大的新方式汇集在一起。[^5] ” AJAX 是 Garrett 给这种正受到青睐的 Web 应用程序的新开发方法的命名。他的博客文章接着描述了开发人员如何利用 JavaScript 和 XMLHttpRequest 构建新型应用程序,这些应用程序比传统的网页更具响应性和状态性。他还以 Gmail 和 Flickr 网站已经使用 AJAX 技术作为了例子。
|
||||
|
||||
当然了,“AJAX” 中的 “X” 代表 XML。但在随后的问答帖子中,Garrett 指出,JSON 可以完全替代 XML。他写道:“虽然 XML 是 AJAX 客户端进行数据输入、输出的最完善的技术,但要实现同样的效果,也可以使用像 JavaScript Object Notation(JSON)或任何类似的结构数据方法等技术。 ”[^6]
|
||||
|
||||
开发者确实发现在构建 AJAX 应用程序时可以很容易的使用 JSON,许多人更喜欢它而不是 XML。具有讽刺意味的是,对 AJAX 的兴趣逐渐的导致了 JSON 的普及。大约在这个时候,JSON 引起了博客圈的注意。
|
||||
|
||||
2006 年,Dave Winer,一位高产的博主,他也是许多基于 XML 的技术(如 RSS 和 XML-RPC)背后的开发工程师,他抱怨到 JSON 毫无疑问的正在重新发明 XML。尽管人们认为数据交换格式之间的竞争不会导致某一技术的消亡。其写到:
|
||||
|
||||
> 毫无疑问,我可以编写一个例程来解析 JSON,但来看看他们要重新发明一个东西有多大的意义,出于某种原因 XML 本身对他们来说还不够好(我很想听听原因)。谁想干这荒谬之事?查找一棵树然后把节点串起来。可以立马试试。[^7]
|
||||
|
||||
我很理解 Winer 的挫败感。事实上并没有太多人喜欢 XML。甚至 Winer 也说过他不喜欢 XML。[^8] 但 XML 已被设计成一个可供任何人使用,并且可以用于几乎能想象到的所有事情。归根到底,XML 实际上是一门元语言,允许你为特定应用程序自定义该领域特定的语言。如 Web 信息流技术 RSS 和 SOAP(简单对象访问协议)就是例子。Winer 认为由于通用交换格式所带来的好处,努力达成共识非常重要。XML 的灵活性应该能满足任何人的需求,然而 JSON 格式呢,其并没有比 XML 提供更多东西,除了它抛弃了使 XML 更灵活的那些繁琐的东西。
|
||||
|
||||
Crockford 阅读了 Winer 的这篇文章并留下了评论。为了回应 JSON 重新发明 XML 的指责,Crockford 写到:“重造轮子的好处是可以得到一个更好的轮子。”[^9]
|
||||
|
||||
### JSON 与 XML 对比
|
||||
|
||||
到 2014 年,JSON 已经由 ECMA 标准和 RFC 官方正式认可。它有了自己的 MIME 类型。JSON 已经进入了大联盟时代。
|
||||
|
||||
为什么 JSON 比 XML 更受欢迎?
|
||||
|
||||
在 [JSON.org][2] 网站上,Crockford 总结了一些 JSON 的优势。他写到,JSON 的语法极少,其结构可预测,因此 JSON 更容易被人类和机器理解。[^10] 其他博主一直关注 XML 的冗长啰嗦及“尖括号负担”。[^11] XML 中每个开始标记都必须与结束标记匹配,这意味着 XML 文档包含大量的冗余信息。在未压缩时,XML 文档的体积比同等信息量 JSON 文档的体积大很多,但是,更重要的,这也使 XML 文档更难以阅读。
|
||||
|
||||
Crockford 还声称 JSON 的另一个巨大优势是其被设计为数据交换格式。[^12] 从一开始,它的目的就是在应用程序间传递结构化信息的。而 XML 呢,虽然也可以使用来传递数据,但其最初被设计为文档标记语言。它演变自 SGML(通用标准标记语言),而它又是从被称为 Scribe 的标记语言演变而来,其旨在发展成类似于 LaTeX 一样的文字处理系统。XML 中,一个标签可以包含有所谓的“混合内容”,即带有围绕单词、短语的内嵌标签的文本。这会让人浮现出一副用红蓝笔记录的手稿画面,这是标记语言核心思想的形象比喻。另一方面,JSON 不支持对混合内容模型的清晰构建,但这也意味着它的结构足够简单。一份文档最好的建模就是一棵树,但 JSON 抛弃了这种文档的思想,Crockford 将 JSON 抽象限制为字典和数组,这是所有程序员构建程序时都会使用的最基本的、也最熟悉的元素。
|
||||
|
||||
最后,我认为人们不喜欢 XML 是因为它让人困惑。它让人迷惑的地方就是有很多不同的风格。乍一看,XML 本身及其子语言(如 RSS、ATOM、SOAP 或 SVG)之间的界限并不明显。典型的 XML 文档的第一行标识了该 XML 的版本,然后该 XML 文档应该符合特定的子语言。这就有变化需要考虑了,特别是跟 JSON 做比较,JSON 是如此简单,以至于永远不需要编写新版本的 JSON 规范。XML 的设计者试图将 XML 做为唯一的数据交换格式以支配所有格式,就会掉入那个经典的程序员陷阱:过度工程化。XML 非常笼统及概念化,所以很难于简单的使用。
|
||||
|
||||
在 2000 年的时候,发起了一场使 HTML 符合 XML 标准的活动,发布了一份符合 XML 标准的 HTML 开发规范,这就此后很出名的 XHTML。虽然一些浏览器厂商立即开始支持这个新标准,但也很明显,大部分基于 HTML 技术的开发者不愿意改变他们的习惯。新标准要求对 XHTML 文档进行严格的验证,而不是基于 HTML 的基准。但大多的网站都是依赖于 HTML 的宽容规则的。到 2009 年的时候,试图编写第二版本的 XHTML 标准的努力已经流产,因为未来已清晰可见,HTML 将会发展为 HTML5(一种不强制要求接受 XML 规则的标准)。
|
||||
|
||||
如果 XHTML 的努力取得了成功,那么 XML 可能会成为其设计者所希望的通用数据格式。想象一下,一个 HTML 文档和 API 响应具有完全相同结构的世界。在这样的世界中,JSON 可能不会像现在一样普遍存在。但我把 HTML 的失败看做是 XML 阵营的一种道义上的失败。如果 XML 不是 HTML 的最佳工具,那么对于其他应用程序,也许会有更好的工具出现。在这个世界,我们的世界,很容易看到像 JSON 格式这样的足够简单、量体裁衣的才能获得更大的成功。
|
||||
|
||||
如果你喜欢这博文,每两周会更新一次! 请在 Twitter 上关注 [@TwoBitHistory][3] 或订阅 [RSS feed][4],以确保得到更新的通知。
|
||||
|
||||
[^1]: http://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html#software
|
||||
[^2]: https://insights.stackoverflow.com/trends?tags=json%2Cxml%2Cprotocol-buffers%2Cyaml%2Ccsv
|
||||
[^3]: Zakas, Nicholas C., et al. “What Is Ajax?” Professional Ajax, 2nd ed., Wiley, 2007.
|
||||
[^4]: https://youtu.be/-C-JoyNuQJs?t=32s
|
||||
[^5]: http://adaptivepath.org/ideas/ajax-new-approach-web-applications/
|
||||
[^6]: 同上
|
||||
[^7]: http://scripting.com/2006/12/20.html
|
||||
[^8]: http://blogoscoped.com/archive/2009-03-05-n15.html
|
||||
[^9]: https://scripting.wordpress.com/2006/12/20/scripting-news-for-12202006/#comment-26383
|
||||
[^10]: http://www.json.org/xml.html
|
||||
[^11]: https://blog.codinghorror.com/xml-the-angle-bracket-tax
|
||||
[^12]: https://youtu.be/-C-JoyNuQJs?t=33m50sgg
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html
|
||||
|
||||
作者:[Two-Bit History][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[runningwater](https://github.com/runningwater)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twobithistory.org
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://twobithistory.org/images/json.svg
|
||||
[2]: http://JSON.org
|
||||
[3]: https://twitter.com/TwoBitHistory
|
||||
[4]: https://twobithistory.org/feed.xml
|
@ -1,232 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 1 OK01)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html)
|
||||
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
|
||||
|
||||
Computer Laboratory – Raspberry Pi: Lesson 1 OK01
|
||||
======
|
||||
|
||||
The OK01 lesson contains an explanation about how to get started and teaches how to enable the 'OK' or 'ACT' **LED** on the Raspberry Pi board near the RCA and USB ports. This light was originally labelled OK but has been renamed to ACT on the revision 2 Raspberry Pi boards.
|
||||
|
||||
### 1 Getting Started
|
||||
|
||||
I am assuming at this point that you have already visited the [Downloads][1] page, and got the necessary GNU Toolchain. Also on the downloads page is a file called OS Template. Please download this and extract its contents to a new directory.
|
||||
|
||||
### 2 The Beginning
|
||||
|
||||
```
|
||||
The '.s' file extension is commonly used for all forms of assembly code, it is up to us to remember this is ARMv6.
|
||||
```
|
||||
|
||||
Now that you have extracted the template, create a new file in the 'source' directory called 'main.s'. This file will contain the code for this operating system. To be explicit, the folder structure should look like:
|
||||
|
||||
```
|
||||
build/
|
||||
(empty)
|
||||
source/
|
||||
main.s
|
||||
kernel.ld
|
||||
LICENSE
|
||||
Makefile
|
||||
```
|
||||
|
||||
Open 'main.s' in a text editor so that we can begin typing assembly code. The Raspberry Pi uses a variety of assembly code called ARMv6, so that is what we'll need to write in.
|
||||
|
||||
Copy in these first commands.
|
||||
|
||||
```
|
||||
.section .init
|
||||
.globl _start
|
||||
_start:
|
||||
```
|
||||
|
||||
As it happens, none of these actually do anything on the Raspberry Pi, these are all instructions to the assembler. The assembler is the program that will translate between assembly code that we understand, and binary machine code that the Raspberry Pi understands. In Assembly Code, each line is a new command. The first line here tells the Assembler[1] where to put our code. The template I provided causes the code in the section called .init to be put at the start of the output. This is important, as we want to make sure we can control which code runs first. If we don't do this, the code in the alphabetically first file name will run first! The .section command simply tells the assembler which section to put the code in, from this point until the next .section or the end of the file.
|
||||
|
||||
```
|
||||
In assembly code, you may skip lines, and put spaces before and after commands to aid readability.
|
||||
```
|
||||
|
||||
The next two lines are there to stop a warning message and aren't all that important.[2]
|
||||
|
||||
### 3 The First Line
|
||||
|
||||
Now we're actually going to code something. In assembly code, the computer simply goes through the code, doing each instruction in order, unless told otherwise. Each instruction starts on a new line.
|
||||
|
||||
Copy the following instruction.
|
||||
|
||||
```
|
||||
ldr r0,=0x20200000
|
||||
```
|
||||
|
||||
```
|
||||
ldr reg,=val puts the number val into the register named reg.
|
||||
```
|
||||
|
||||
That is our first command. It tells the processor to store the number 0x20200000 into the register r0. I shall need to answer two questions here, what is a register, and how is 0x20200000 a number?
|
||||
|
||||
```
|
||||
A single register can store any integer between 0 and 4,294,967,295 inclusive on the Raspberry Pi, which might seem like a large amount of memory, but it is only 32 binary bits.
|
||||
```
|
||||
|
||||
A register is a tiny piece of memory in the processor, which is where the processor stores the numbers it is working on right now. There are quite a few of these, many of which have a special meaning, which we will come to later. Importantly there are 13 (named r0,r1,r2,...,r9,r10,r11,r12) which are called General Purpose, and you can use them for whatever calculations you need to do. Since it's the first, I've used r0 in this example, but I could very well have used any of the others. As long as you're consistent, it doesn't matter.
|
||||
|
||||
0x20200000 is indeed a number. However it is written in Hexadecimal notation. To learn more about hexadecimal expand the box below:
|
||||
```
|
||||
Hexadecimal is an alternate system for writing numbers. You may only be aware of the decimal system for writing numbers in which we have 10 digits: 0,1,2,3,4,5,6,7,8 and 9. Hexadecimal is a system with 16 digits: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e and f.
|
||||
|
||||
![567 is 5 hundreds, 6 tens and 7 units.][2]
|
||||
|
||||
You may recall being taught how decimal numbers work in terms of place value. We say that the rightmost digits is the 'units' digits, the next one left is the 'tens' digit, the next is the 'hundreds' digit, and so on. What this actually meant is, the number is 100 × the value in the 'hundreds' digit, plus 10 × the value in the 'tens' digit, plus 1 × the value in the units digit.
|
||||
|
||||
![567 is 5x10^2+6x10^1+7x10^0][3]
|
||||
|
||||
More mathematically, we can now spot the pattern and say that the rightmost digit is the 100=1s digit, the next left is the 101=10s digit, the next is 102=100s digit, and so on. We have all agreed on the system that 0 is the lowest digit, 1 is the next and so on. But what if we used a different number instead of 10 in these powers? Hexadecimal is just the system in which we use 16 instead.
|
||||
|
||||
![567 = 5x10^2+6x10^1+7x10^0 = 2x16^2+3x16^1+7x16^0][4]
|
||||
|
||||
The mathematics to the right shows that the number 567 in decimal is equivalent to the number 237 in hexadecimal. Often when we need to be clear about what system we're using to write numbers in we put 10 for decimal and 16 for hexadecimal. Since it's difficult to write small numbers in assembly code, we use 0x instead to represent a number in hexadecimal notation. So 0x237 means 23716.
|
||||
|
||||
So where do a,b,c,d,e and f come in? Well, in order to be able to write every number in hexadecimal, we need extra digits. For example 916 = 9×160 = 910, but 1016 = 1×161 + 1×160 = 1610. So if we just used 0,1,2,3,4,5,6,7,8 and 9 we would not be able to write 1010, 1110, 1210, 1310, 1410, 1510. So we introduce 6 new digits such that a16 = 1010, b16 = 1110, c16 = 1210, d16 = 1310, e16 = 1410, f16 = 1510
|
||||
|
||||
So, we now have another system for writing numbers. But why did we bother? Well, it turns out that since computers always work in binary, hexadecimal notation is very useful because every hexadecimal digit is exactly four binary digits long. This has the nice side effect that a lot of computer numbers are round numbers in hexadecimal, even though they're not in decimal. For example, in the assembly code just above I used the number 2020000016. If I had chose to write this in decimal it would have been 53896806410, which is much less memorable.
|
||||
|
||||
To convert numbers from decimal to hexadecimal I find the following method easiest:
|
||||
|
||||
![Conversion example][5]
|
||||
|
||||
1. Start with the decimal number, say 567.
|
||||
2. Divide by 16 and calculate the remainder. For example 567 ÷ 16 = 35 remainder 7.
|
||||
3. The remainder is the last digit of the answer in hexadecimal, in the example this is 7.
|
||||
4. Repeat steps 2 and 3 again with the result of the last division until the result is 0. For example 35 ÷ 16 = 2 remainder 3, so 3 is the next digit of the answer. 2 ÷ 16 = 0 remainder 2, so 2 is the next digit of the answer.
|
||||
5. Once the result of the division is 0, you can stop. The answer is just the remainders in the reverse order to which you got them, so 56710 = 23716.
|
||||
|
||||
|
||||
|
||||
To convert hexadecimal numbers back to decimal, it is easiest to expand out the number, so 23716 = 2×162 + 3×161 +7 ×160 = 2×256 + 3×16 + 7×1 = 512 + 48 + 7 = 567.
|
||||
```
|
||||
|
||||
So our first command is to put the number 2020000016 into r0. That doesn't sound like it would be much use, but it is. In computers, there are an awful lot of chunks of memory and devices. In order to access them all, we give each one an address. Much like a postal address or a web address this is just a means of identifying the location of the device or chunks of memory we want. Addresses in computers are just numbers, and so the number 2020000016 happens to be the address of the GPIO controller. This is just a design decision taken by the manufacturers, they could have used any other address (providing it didn't conflict with anything else). I know this address only because I looked it up in a manual[3], there is no particular system to the addresses (other than that they are all large round numbers in hexadecimal).
|
||||
|
||||
### 4 Enabling Output
|
||||
|
||||
![A diagram showing key parts of the GPIO controller.][6]
|
||||
|
||||
Having read the manual, I know we're going to need to send two messages to the GPIO controller. We need to talk its language, but if we do, it will obligingly do what we want and turn on the OK LED. Fortunately, it is such a simple chip, that it only needs a few numbers in order to understand what to do.
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#18
|
||||
str r1,[r0,#4]
|
||||
```
|
||||
|
||||
```
|
||||
mov reg,#val puts the number val into the register named reg.
|
||||
|
||||
lsl reg,#val shifts the binary representation of the number in reg by val places to the left.
|
||||
|
||||
str reg,[dest,#val] stores the number in reg at the address given by dest + val.
|
||||
```
|
||||
|
||||
These commands enable output to the 16th GPIO pin. First we get a necessary value in r1, then send it to the GPIO controller. Since the first two instructions are just trying to get a value into r1, we could use another ldr command as before, but it will be useful to us later to be able to set any given GPIO pin, so it is better to deduce the value from a formula than write it straight in. The OK LED is wired to the 16th GPIO pin, and so we need to send a command to enable the 16th pin.
|
||||
|
||||
The value in r1 is needed to enable the LED pin. The first line puts the number 110 into r1. The mov command is faster than the ldr command, because it does not involve a memory interaction, whereas ldr loads the value we want to put into the register from memory. However, mov can only be used to load certain values[4]. In ARM assembly code, almost every instruction begins with a three letter code. This is called the mnemonic, and is supposed to hint at what the operation does. mov is short for move and ldr is short for load register. mov moves the second argument #1 into the first r1. In general, # must be used to denote numbers, but we have already seen a counterexample to this.
|
||||
|
||||
The second instruction is lsl or logical shift left. This means shift the binary representation for the first argument left by the second argument. In this case this will shift the binary representation of 110 (which is 12) left by 18 places (making it 10000000000000000002=26214410).
|
||||
|
||||
If you are unfamiliar with binary, expand the box below:
|
||||
```
|
||||
Just like hexadecimal binary is another way of writing numbers. In binary we only have 2 digits, 0 and 1. This is useful for computers because we can implement this in a circuit by saying that electricity flowing through the circuit means 1, and not means 0. This is how computers actually work and do maths. Despite only having 2 digits binary can still be used to represent every number, it just takes a lot longer.
|
||||
|
||||
![567 in decimal = 1000110111 in binary][7]
|
||||
|
||||
The image shows the binary representation of the number 56710 which is 10001101112. We use 2 to denote numbers written in binary.
|
||||
|
||||
One of the quirks of binary that we make heavy use of in assembly code is the ease by which numbers can be multiplied or divided by powers of 2 (e.g. 1,2,4,8,16). Normally multiplications and divisions are tricky operations, however these special cases are very easy, and so are very important.
|
||||
|
||||
![13*4 = 52, 1101*100=110100][8]
|
||||
|
||||
Shifting a binary number left by **n** places is the same as multiplying the number by 2 **n**. So, if we want to multiply by 4, we just shift the number left 2 places. If we want to multiply by 256 we could shift it left by 8 places. If we wanted to multiply by a number like 12, we could instead multiply it by 8, then separately by 4 and add the results (N × 12 = N × (8 + 4) = N × 8 + N × 4).
|
||||
|
||||
![53/16 = 3, 110100/10000=11][9]
|
||||
|
||||
Shifting a binary number right by **n** places is the same as dividing the number by 2 **n**. The remainder of the division is the bits that were lost when shifted right. Unfortunately dividing by a binary number that is not an exact power of 2 is very difficult, and will be covered in [Lesson 9: Screen04][10].
|
||||
|
||||
![Binary Terminology][11]
|
||||
|
||||
This diagram shows common terminology used with binary. A bit is a single binary digit. A nibble is 4 binary bits. A byte is 2 nibbles, or 8 bits. A half is half the size of a word, 2 bytes in this case. A word refers to the size of the registers on a processor, and so on the Raspberry Pi this is 4 bytes. The convention is to number the most significant bit of a word 31, and the least significant bit as 0. The top, or high bits refer to the most significant bits, and the low or bottom bits refer to the least significant. A kilobyte (KB) is 1000 bytes, a megabyte is 1000 KB. There is some confusion as to whether this should be 1000 or 1024 (a round number in binary). As such, the new international standard is that a KB is 1000 bytes, and a Kibibyte (KiB) is 1024 bytes. A Kb is 1000 bits, and a Kib is 1024 bits.
|
||||
|
||||
The Raspberry Pi is little endian by default, meaning that loading a byte from an address you just wrote a word to will load the lowest byte of the word.
|
||||
```
|
||||
|
||||
Once again, I only know that we need this value from reading the manual[3]. The manual says that there is a set of 24 bytes in the GPIO controller, which determine the settings of the GPIO pin. The first 4 relate to the first 10 GPIO pins, the second 4 relate to the next 10 and so on. There are 54 GPIO pins, so we need 6 sets of 4 bytes, which is 24 bytes in total. Within each 4 byte section, every 3 bits relates to a particular GPIO pin. Since we want the 16th GPIO pin, we need the second set of 4 bytes because we're dealing with pins 10-19, and we need the 6th set of 3 bits, which is where the number 18 (6×3) comes from in the code above.
|
||||
|
||||
Finally the str 'store register' command stores the value in the first argument, r1 into the address computed from the expression afterwards. The expression can be a register, in this case r0, which we know to be the GPIO controller address, and another value to add to it, in this case #4. This means we add 4 to the GPIO controller address and write the value in r1 to that location. This happens to be the location of the second set of 4 bytes that I mentioned before, and so we send our first message to the GPIO controller, telling it to ready the 16th GPIO pin for output.
|
||||
|
||||
### 5 A Sign Of Life
|
||||
|
||||
Now that the LED is ready to turn on, we need to actually turn it on. This means sending a message to the GPIO controller to turn pin 16 off. Yes, turn it off. The chip manufacturers decided it made more sense[5] to have the LED turn on when the GPIO pin is off. Hardware engineers often seem to take these sorts of decisions, seemingly just to keep OS Developers on their toes. Consider yourself warned.
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#16
|
||||
str r1,[r0,#40]
|
||||
```
|
||||
|
||||
Hopefully you should recognise all of the above commands, if not their values. The first puts a 1 into r1 as before. The second shifts the binary representation of this 1 left by 16 places. Since we want to turn pin 16 off, we need to have a 1 in the 16th bit of this next message (other values would work for other pins). Finally we write it out to the address which is 4010 added to the GPIO controller address, which happens to be the address to write to turn a pin off (28 would turn the pin on).
|
||||
|
||||
### 6 Happily Ever After
|
||||
|
||||
It might be tempting to finish now, but unfortunately the processor doesn't know we're done. In actuality, the processor never will stop. As long as it has power, it continues working. Thus, we need to give it a task to do forever more, or the Raspberry Pi will crash (not much of a problem in this example, the light is already on).
|
||||
|
||||
```
|
||||
loop$:
|
||||
b loop$
|
||||
```
|
||||
|
||||
```
|
||||
name: labels the next line name.
|
||||
|
||||
b label causes the next line to be executed to be label.
|
||||
```
|
||||
|
||||
The first line here is not a command, but a label. It names the next line loop$. This means we can now refer to the line by name. This is called a label. Labels get discarded when the code is turned into binary, but they're useful for our benefit for referring to lines by name, not number (address). By convention we use a $ for labels which are only important to the code in this block of code, to let others know they're not important to the overall program. The b (branch) command causes the next line to be executed to be the one at the label specified, rather than the one after it. Therefore, the next line to be executed will be this b, which will cause it to be executed again, and so on forever. Thus the processor is stuck in a nice infinite loop until it is switched off safely.
|
||||
|
||||
The new line at the end of the block is intentional. The GNU toolchain expects all assembly code files to end in an empty line, so that it is sure you were really finished, and the file hasn't been cut off. If you don't put one, you get an annoying warning when the assembler runs.
|
||||
|
||||
### 7 Pi Time
|
||||
|
||||
So we've written the code, now to get it onto the pi. Open a terminal on your computer and change the current working directory to the parent directory of the source directory. Type make and then press enter. If any errors occur, please refer to the troubleshooting section. If not, you will have generated three files. kernel.img is the compiled image of your operating system. kernel.list is a listing of the assembly code you wrote, as it was actually generated. This is useful to check that things were generated correctly in future. The kernel.map file contains a map of where all the labels ended up, which can be useful for chasing around values.
|
||||
|
||||
To install your operating system, first of all get a Raspberry PI SD card which has an operating system installed already. If you browse the files in the SD card, you should see one called kernel.img. Rename this file to something else, such as kernel_linux.img. Then, copy the file kernel.img that make generated onto the SD Card. You've just replaced the existing operating system with your own. To switch back, simply delete your kernel.img file, and rename the other one back to kernel.img. I find it is always helpful to keep a backup of you original Raspberry Pi operating system, in case you need it again.
|
||||
|
||||
Put the SD card into a Raspberry Pi and turn it on. The OK LED should turn on. If not please see the troubleshooting page. If so, congratulations, you just wrote your first operating system. See [Lesson 2: OK02][12] for a guide to making the LED flash on and off.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html
|
||||
|
||||
作者:[Robert Mullins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cl.cam.ac.uk/~rdm34
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal1.png
|
||||
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal2.png
|
||||
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal3.png
|
||||
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal4.png
|
||||
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioController.png
|
||||
[7]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary1.png
|
||||
[8]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary2.png
|
||||
[9]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
|
||||
[10]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
|
||||
[11]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary4.png
|
||||
[12]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
|
@ -1,3 +1,5 @@
|
||||
translating----geekpi
|
||||
|
||||
Working with modules in Fedora 28
|
||||
======
|
||||
![](https://fedoramagazine.org/wp-content/uploads/2018/05/modules-workingwith-816x345.jpg)
|
||||
|
@ -1,87 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: subject: (Turn an old Linux desktop into a home media center)
|
||||
[#]: via: (https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center)
|
||||
[#]: author: ([Alan Formy-Duval](https://opensource.com/users/alanfdoss))
|
||||
[#]: url: ( )
|
||||
|
||||
Turn an old Linux desktop into a home media center
|
||||
======
|
||||
Repurpose an outdated computer to browse the internet and watch videos on your big screen TV.
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/migration_innovation_computer_software.png?itok=VCFLtd0q)
|
||||
|
||||
My first attempt to set up an "entertainment PC" was back in the late 1990s, using a plain old desktop computer with a Trident ProVidia 9685 PCI graphics card. I used what was known as a "TV-out" card, which had an extra output to connect to a standard television set. The onscreen result didn't look very nice and there was no audio output. And it was ugly: I had an S-Video cable running across my living room floor to my 19" Sony Trinitron CRT TV set.
|
||||
|
||||
I had the same sad result from Linux and Windows 98. After struggling with systems that never looked right, I gave up for a few years. Thankfully, today we have HDMI with its vastly better performance and standardized resolution, which makes an inexpensive home media center a reality.
|
||||
|
||||
My new media center entertainment computer is actually my old Ubuntu Linux desktop, which I recently replaced with something faster. The computer became too slow for work, but its AMD Phenom II X4 965 processor at 3.4GHz and 8GB of RAM are good enough for general browsing and video streaming.
|
||||
|
||||
Here are the steps I took to get the best possible performance out of this old system for its new role.
|
||||
|
||||
### Hardware
|
||||
|
||||
First, I removed unnecessary devices including a card reader, hard drives, DVD drive, and a rear-mounted USB card, and I added a PCI-Express WiFi card. I installed Ubuntu to a single solid-state drive (SSD), which can really improve the performance of any older system.
|
||||
|
||||
### BIOS
|
||||
|
||||
In the BIOS, I disabled all unused devices, such as floppy and IDE drive controllers. I disabled onboard video because I installed an NVidia GeForce GTX 650 PCI Express graphics card with an HDMI output. I also disabled onboard audio because the NVidia graphics card chipset provides audio.
|
||||
|
||||
### Audio
|
||||
|
||||
The Nvidia GeForce GTX audio device is listed in the GNOME Control Center's sound settings as a GK107 HDMI Audio Controller, so a single HDMI cable handles both audio and video. There's no need for an audio cable connected to the onboard audio output jack.
|
||||
|
||||
![Sound settings screenshot][2]
|
||||
|
||||
HDMI audio controller shown in GNOME sound settings.
|
||||
|
||||
### Keyboard and mouse
|
||||
|
||||
I have a wireless keyboard and mouse, both from Logitech. When I installed them, I plugged in both peripherals' USB receivers; they worked, but I often had signal-response problems. Then I discovered one was labeled a Unifying Receiver, which meant it can handle multiple Logitech input devices on its own. Logitech doesn't provide software to configure Unifying Receivers in Linux; fortunately, the open source utility [Solaar][3] does. Using a single receiver solved my input performance issues.
|
||||
|
||||
![Solaar][5]
|
||||
|
||||
Solaar Unifying Receiver interface.
|
||||
|
||||
### Video
|
||||
|
||||
It was initially hard to read fonts on my 47" flat-panel TV, so I enabled "Large Text" under Universal Access. I downloaded some wallpapers matching the TV's 1920x1080 resolution that look fantastic!
|
||||
|
||||
### Final touches
|
||||
|
||||
I needed to balance the computer's cooling needs with my desire for unimpeded entertainment. Since this is a standard ATX mini-tower computer, I made sure I had just enough fans with carefully configured temperature settings in the BIOS to reduce fan noise. I also placed the computer behind my entertainment console to further block fan noise but positioned so I can reach the power button.
|
||||
|
||||
The result is a simple machine that is not overly loud and uses only two cables—AC power and HDMI. It should be able to run any mainstream or specialized media center Linux distribution. I don't expect to do too much high-end gaming because that may require more processing horsepower.
|
||||
|
||||
![Showing Ubuntu Linux About page onscreen][7]
|
||||
|
||||
Ubuntu Linux About page.
|
||||
|
||||
![YouTube on the big screen][9]
|
||||
|
||||
Testing a YouTube video on the big screen.
|
||||
|
||||
I haven't yet installed a dedicated media center distribution of Linux like [Kodi][10]. For now, it is running Ubuntu Linux 18.04.1 LTS and is very stable.
|
||||
|
||||
This was a fun challenge to make the best of what I already had rather than buying new hardware. This is just one benefit of open source software. Eventually, I will probably replace it with a smaller, quieter system with a media-center case or another small box, but for now, it meets my needs quite well.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center
|
||||
|
||||
作者:[Alan Formy-Duval][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alanfdoss
|
||||
[b]: https://github.com/lujun9972
|
||||
[2]: https://opensource.com/sites/default/files/uploads/soundsettings.png (Sound settings screenshot)
|
||||
[3]: https://pwr.github.io/Solaar/
|
||||
[5]: https://opensource.com/sites/default/files/uploads/solaar_interface.png (Solaar)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/finalresult1.png (Showing Ubuntu Linux About page onscreen)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/finalresult2.png (YouTube on the big screen)
|
||||
[10]: https://kodi.tv/
|
@ -1,102 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (runningwater)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: subject: (The Rise and Rise of JSON)
|
||||
[#]: via: ( https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html)
|
||||
[#]: author: (https://twobithistory.org)
|
||||
[#]: url: ( )
|
||||
|
||||
JSON 的兴起与崛起
|
||||
======
|
||||
JSON 已经占领了全世界。当今,任何两个应用程序彼此通过网络通信时,它们很有可能在使用 JSON。它已被所有大型企业所采用:十大最受欢迎的 web API 接口(主要由 Google、Facebook 和 Twitter 提供的)列表中,仅仅只有一个 API 接口是以 XML 的格式开放数据的。Twitter 给这个 API 添加了一个说明性示例:XML 格式的支持到 2013 年结束,到时候会发布一个新版本的 API,取消 XML 格式,转而使用 JSON。JSON 也在程序编码级别和文件存储上被广泛采用:在 Stack Overflow(一个面向程序员的问答网站)上,现在更多的是关于 JSON 的问题,而不是其他的数据交换格式。
|
||||
|
||||
![][1]
|
||||
|
||||
XML 仍然在很多地方存在。在网页上有 SVG 和 RSS 订阅服务、Atom 提供商。Android 开发者想要获得用户权限许可时,需要在其 APP 的 `manifest` 文件中声明。此文件是 XML 格式的。XML 的替代品也不仅仅只有 JSON,现在有很多人在使用 YAML 或 Google 的 Protocol Buffers 等技术,但这些技术的受欢迎程度远不如 JSON。目前来看,JSON 是应用程序在网络之间通信的首选协议格式。
|
||||
考虑到自 2005 年来网站编程世界对 “异步 JavaScript 和 XML” 而非 “异步 JavaScript 和 JSON” 技术潜力的垂涎欲滴状态,你可以发现 JSON 在其中的主导地位是如此让人惊讶。当然了,这可能与这两种通信格式的受欢迎程度无关,仅反映出 “AJAX” 似乎比 “AJAJ” 更具吸引力。但是,即使在 2015 年时有好些人已经用 JSON 来取代 XML 了(实际上还没有很多人),我们不禁要问 XML 的噩运来的如此之快,以至于短短十年左右,“异步 JavaScript 和 XML” 这个名称就成为一个很讽刺的误称。那个十年发生了什么?JSON 怎么会在那么多应用程序中取代了 XML?现在被全世界工程师和系统所使用、依赖的这种数据格式是谁提出的?
|
||||
|
||||
### JSON 之诞生
|
||||
|
||||
2001 年 4 月,首个 JSON 格式的消息被发送。此消息是从旧金山湾区某车库的一台计算机发出的,这是计算机历史上重要的的时刻。Douglas Crockford 和 Chip Morningstar 是一家名为 State Software 的技术咨询公司的联合创始人,他们当时聚集在 Morningstar 的车库里测试某个想法,发出了此消息。
|
||||
|
||||
在 “AJAX” 这个术语被创造之前, Crockford 和 Morningstar 就已经在尝试构建好用的 AJAX 应用程序了。可是浏览器对其兼容性不好。他们想要在初始页面加载后就将数据传递给应用程序,但其目标要针对所有的浏览器,这就实现不了。
|
||||
|
||||
这在今天看来不太可信,但是要记得 2001 年的时候 Internet Explorer(IE)代表了网页浏览器的最前沿技术产品。早在 1999 年的时候,Internet Explorer 5 就支持 `XMLHttpRequest 对象原型`,开发者可以使用名为 ActiveX 的框架来访问此对象。 Crockford 和 Morningstar 可能是使用此技术来获取数据,但是在 Netscape 4 中(这是他们想要支持的另一种浏览器)就无法使用这种解决方案。为此 Crockford 和 Morningstar 只得开发不同的系统程序以兼容不同的浏览器。
|
||||
|
||||
第一条 JSON 消息如下所示:
|
||||
|
||||
```
|
||||
<html><head><script>
|
||||
document.domain = 'fudco';
|
||||
parent.session.receive(
|
||||
{ to: "session", do: "test",
|
||||
text: "Hello world" }
|
||||
)
|
||||
</script></head></html>
|
||||
```
|
||||
|
||||
消息中只有一小部分类似于今天我们所知的 JSON,本身其实是一个包含有 JavaScript 的 HTML 文档。类似于 JSON 的部分只是传递给名为`receive()` 的函数的 JavaScript 对象。
|
||||
|
||||
Crockford 和 Morningstar 决定滥用 HTML 的 frame,以发送数据。敲入 URL 返回的 HTML 文档(如上所示)可以指向一个 frame 标签。当接收到 HTML 时,JavaScript 代码段一运行,就可以把数据对象如实地传递回应用程序。只要小心的回避浏览器保护策略,即子窗口不允许访问父窗口,这种技术就可以正常运行无误。可以看到 Crockford 和 Mornginstar 通过明确地设置文档域这种方法来达到其目的。(这种基于 frame 的技术,有时称为隐藏 frame 技术,通常在90年代后期,即广泛使用 XMLHttpRequest 技术之前使用。)
|
||||
|
||||
关于第一个 JSON 消息的惊人之处在于它显然不是第一次就使用新的数据格式。它仅仅是 JavaScript!实际上,以此使用 JavaScript 的想法如此简单,Crockford 自己也说过他不是第一个这样做的人。他声称 Netscape 公司的某人早在 1996 年就使用 JavaScript 数组文字来交换信息。因为消息就是 JavaScript 本身,其不需要任何特殊解析工作,JavaScript 解释器就可搞定一切。
|
||||
|
||||
最初的 JSON 信息实际上与 JavaScript 解释器发生了冲突。JavaScript 使用了大量的单词来做为保留字(ECMAScript 6 版本的就有 64 个保留字),Crockford 和 Morningstar 无意中在其 JSON 中引入了一个保留字。他们使用了 `do` 这个关键字,但 `do` 是解释器中的保留字。因为 JavaScript 使用的保留字太多了,Crockford 做了决定:既然不可避免的要使用到这些保留字,那就要求所有的 JSON 关键字都加上引号。被引起来的关键字会被 JavaScript 解释器识别成字符串,其意味着那些保留字也可以放心安全的使用。这就为什么今天 JSON 关键字都要用引号引起来的原因。
|
||||
|
||||
Crockford 和 Morningstar 意识到这技术可以应用于各类应用系统。想给其命名为 “JSML”,即 JavaScript 标记语言,但发现这个缩写已经被叫做 Java 标记语言的所使用了。因此他们决定采用 “JavaScript Object Notation” 或 JSON 命名。他们开始向客户推销,但很快发现客户不愿意冒险使用缺乏官方规范的未知技术。所以 Crockford 决定写一个规范。
|
||||
|
||||
2002 年,Crockford 买下了 [JSON.org][2] 域名,放上了 JSON 语法及一个解释器的实例例子。网站仍然在运行,现在已经包含有 2013 年正式批准的 JSON ECMA 标准的显著链接。在网站建立后,Crockford 并没有过多的推广,但很快发现很多人都在提交各种不同编程语言的 JSON 解析器实现。JSON 的血统明显与 JavaScript 相关联,但很明显 JSON 非常适合于不同语言之间的数据交换。
|
||||
|
||||
|
||||
### AJAX 导致的误会
|
||||
|
||||
2005 年,JSON 有了一次大扩展。那一年,一位名叫 Jesse James Garrett 的网页设计师和开发人员在博客文章中创造了 “AJAX” 一词。他很谨慎地强调:AJAX 并不是新技术,而是 “好几种技术以某种强大的新方式汇集,其中的各技术各自发展。” AJAX 是 Garrett 给 Web 应用程序开发的新方法(其正获得青睐)的命名。他的博客文章接着描述了开发人员如何利用 JavaScript 和 XMLHttpRequest 对象构建新的应用程序,这些应用程序比传统的网页更具响应性和状态性。 他还举了 Gmail 和 Flickr的网站已经使用 AJAX 技术的例子。
|
||||
|
||||
当然了,“AJAX” 中的 “X” 代表 XML。但在随后的问答帖子中,Garrett 指出,JSON 可以完全替代 XML。他写道:虽然 XML 是 AJAX 客户端进行数据输入输出的最完善的技术,但要实现同样的效果,也可以使用像 JavaScript Object Notation (JSON)或任何类似的结构数据方法等技术。
|
||||
|
||||
开发者确实发现在构建 AJAX 应用程序时可以很容易的使用 JSON,并且很多人也开始喜欢上 XML。具有讽刺意味的是,对 AJAX 的兴趣逐渐的导致了 JSON 的普及。大约在这个时候,JSON 引起了博客圈的注意。
|
||||
|
||||
2006 年,Dave Winer,一位高产的博主,也是许多基于 XML 技术(如 RSS 和 XML-RPC)的后端开发工程师,他抱怨到 JSON 毫无疑问的正在重新发明 XML。虽然他认为数据交换格式之间的竞争不会导致某一技术的消亡,其写到:
|
||||
|
||||
> 让我们来比较下重构某结构数据的深度及难度,由于某些原因(我很想听听原因),XML 自身做的并不好,所以毫无疑问地,我会写一个例程来解析 JSON 格式的数据。谁想干这荒谬之事?查找一棵树然后把节点串起来。可以立马试试。
|
||||
|
||||
很容易理解 Winer 的挫败感,事实上并没有太多人喜欢 XML。甚至 Winer 也说过他不喜欢 XML。但 XML 已被设计成一个可供任何人使用,并且几乎能想象到的事情都可以做到的系统。最终,XML 实际上是一门元语言,允许你为特定应用程序自定义特定域的语言。如 RSS、web feed 技术和 SOAP(简单对象访问协议)就是自定义的例子。Winer 认为由于通用交换格式所带来的好处,努力达成共识就很重要了。XML 的灵活性应该能满足任何人的需求,然而这里是 JSON 格式,其并不比 XML 更具优势,但其抛弃了 XML 中不好的设计,可以使 XML 更加的灵活。
|
||||
|
||||
Crockford 阅读了 Winer 的这篇文章并留下了评论。为了回应 JSON 重新发明 XML 的指责,Crockford 写到:重造轮子的好处是可以得到一个更好的轮子。
|
||||
|
||||
### JSON 与 XML 对比
|
||||
|
||||
到 2014 年,JSON 已经由 ECMA 标准和 RFC 官方正式认可。它有自己的 MIME 类型。JSON 已经进入了大联盟时代。
|
||||
|
||||
为什么 JSON 比 XML 更受欢迎?
|
||||
|
||||
在 [JSON.org][2] 网站上,Crockford 总结了一些 JSON 的优势。他写到,JSON 的语法很小,其结构可预测,因此 JSON 更容易被人类和机器理解。其他博主不得不关注 XML 的冗长啰嗦及“尖括号负担”。XML 中每个开始标记都必须与结束标记匹配,这意味着 XML 文档包含大量的冗余信息。在未压缩时,XML 文档的体积比同信息量 JSON 文档的体积大很多,但是,更重要的,这也使 XML 文档更难以阅读。
|
||||
|
||||
Crockford 还声称 JSON 的另一个巨大优势是其被设计为数据交换格式。从一开始,它的目的就是在应用程序间传递结构化信息的。而 XML 呢,虽然也可以使用来传递数据,但其最初被设计为文档标记语言。它从 SGML(通用标准标记语言)演变而来,后来又从称为 Scribe 的标记语言是发展,旨在发展成类似于 LaTeX 一样的文字处理系统。XML 中,一个标签可以包含有所谓的“混合内容”或包含有围绕单词、短语的内嵌标签的文本。这会让人浮现出一副用红蓝笔记录的手稿画面,这是标记语言核心思想的形象比喻。另一方面,JSON 不支持对混合内容模型清晰构建,但也意味着它的结构足够简单。一份文档最好的建模就是一棵树,但 JSON 抛弃了文档的思想,Crockford 将 JSON 抽象限制为字典和数组,这是所有程序员构建程序时都会使用的最基本也最熟悉的元素。
|
||||
|
||||
最后,我认为人们不喜欢 XML 是因为它让人困惑。它让人迷惑的地方就是有很多不同的风格。乍一看,XML 本身及其子语言(如 RSS、ATOM、SOAP 或 SVG)之间的界限并不明显。通用 XML 文档创建的版本做为第一个基线,然后特定的子语言 XML 版本应该在这基础上变动。这就有需要变化需要考虑的了,特别是跟 JSON 做比较。JSON 的是如此简单,以至于 JSON 新版本规范甚至都不用重写。XML 的设计者试图将 XML 做为唯一的数据交换格式以支配所有格式,会掉入那个经典程序员的陷阱:过度工程化。XML 非常笼统及概念化,所以很难于简单的使用。
|
||||
|
||||
在 2000 年的时候,推出了一场活动,以使 HTML 符合 XML 标准。发布了一份符合 XML 标准的 HTML 开发规范,这就此后很出名的 XHTML。虽然一些浏览器供应商立即开始支持这个新标准,但也很明显,大部分基于 HTML 技术的开发者不愿意改变他们的习惯。新标准要求对 XHTML 文档进行严格的验证,而不是基于 HTML 的基准。但大多的网站都是依赖于 HTML 的宽容规则的。到 2009 年的时候,试图编写第二版本的 XHTML 标准已经流产,因为未来已清晰可见, HTML 将会发展为 HTML5(一种不强制要求接受 XML 规则的标准)。
|
||||
|
||||
如果 XHTML 的努力取得了成功,那么 XML 可能会成为其设计者希望的通用数据格式。想象一下,HTML 文档和 API 响应具有完全相同结构的世界。在这样的世界中,JSON 可能不会像现在一样普遍存在。但我读懂了, XHTML 的失败是 XML 阵营的一种道德失败。如果 XML 不是 HTML 的最佳工具,那么为了其他应用程序,也许会有更好的工具出现。在这个世界,我们的世界,很容易看到像 JSON 格式这样的足够简单、量体裁衣才能获得更大的成功。
|
||||
|
||||
如果你喜欢这博文,每两周会更新一次! 请在 Twitter 上关注 [@TwoBitHistory] [3] 或订阅 [RSS feed] [4], 以确保得到更新的通知。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html
|
||||
|
||||
作者:[Two-Bit History][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[runningwater](https://github.com/runningwater)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://twobithistory.org
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://twobithistory.org/images/json.svg
|
||||
[2]: http://JSON.org
|
||||
[3]: https://twitter.com/TwoBitHistory
|
||||
[4]: https://twobithistory.org/feed.xml
|
@ -0,0 +1,230 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ()
|
||||
[#]: publisher: ()
|
||||
[#]: url: ()
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 1 OK01)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html)
|
||||
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
|
||||
|
||||
计算机实验室 - 树莓派:课程 1:OK01
|
||||
======
|
||||
|
||||
OK01 课程讲解了树莓派如何开始,以及在树莓派上如何启用靠近 RCA 和 USB 端口的 `OK` 或 `ACT` 的 **LED** 指示灯。这个指示灯最初是为了指示 `OK` 的,但它在第二版的树莓派上被重命名为 `ACT`。
|
||||
|
||||
### 1、入门
|
||||
|
||||
我们假设你已经访问了[下载][1]页面,并且已经获得了必需的 GNU 工具链。也下载了一个称为操作系统模板的文件。请下载这个文件并在一个新目录中解开它。
|
||||
|
||||
### 2、开始
|
||||
|
||||
```
|
||||
扩展名为 '.s' 的文件一般是汇编代码,需要记住的是,在这里它是 ARMv6 的汇编代码。
|
||||
```
|
||||
|
||||
现在,你已经展开了这个模板,在 `source` 目录中创建一个名为 `main.s` 的文件。这个文件包含了这个操作系统的代码。具体来看,这个文件夹的结构应该像下面这样:
|
||||
|
||||
```
|
||||
build/
|
||||
(empty)
|
||||
source/
|
||||
main.s
|
||||
kernel.ld
|
||||
LICENSE
|
||||
Makefile
|
||||
```
|
||||
|
||||
用文本编辑器打开 `main.s` 文件,这样我们就可以输入汇编代码了。树莓派使用了称为 ARMv6 的汇编代码变体,这就是我们即将要写的汇编代码类型。
|
||||
|
||||
首先,我们复制下面的这些命令。
|
||||
|
||||
```
|
||||
.section .init
|
||||
.globl _start
|
||||
_start:
|
||||
```
|
||||
|
||||
实际上,上面这些指令并没有在树莓派上做任何事情,它们是提供给汇编器的指令。汇编器是一个转换程序,它将树莓派能够理解的机器代码转换成我们能够理解的汇编代码,在汇编代码中,每个行都是一个新的命令。上面的第一行告诉汇编器在哪里放我们的代码。我们提供的模板中将它放到一个名为 `.init` 的节中的原因是,它是输出的起始点。这很重要,因为我们希望确保我们能够控制哪个代码首先运行。如果不这样做,首先运行的代码将是按字母顺序排在前面的代码!`.section` 命令简单地告诉汇编器,哪个节中放置代码,从这个点开始,直到下一个 `.section` 或文件结束为止。
|
||||
|
||||
```
|
||||
在汇编代码中,你可以跳行、在命令前或后放置空格去提升可读性。
|
||||
```
|
||||
|
||||
接下来两行是停止一个警告消息,它们并不重要。
|
||||
|
||||
### 3、第一行代码
|
||||
|
||||
现在,我们正式开始写代码。计算机执行汇编代码时,是简单地一行一行按顺序执行每个指令,除非明确告诉它不这样做。每个指令都是开始于一个新行。
|
||||
|
||||
复制下列指令。
|
||||
|
||||
```
|
||||
ldr r0,=0x20200000
|
||||
```
|
||||
|
||||
```
|
||||
ldr reg,=val 将数字 val 加载到名为 reg 的寄存器中。
|
||||
```
|
||||
|
||||
那是我们的第一个命令。它告诉处理器将数字 0x20200000 保存到寄存器 r0 中。在这里我需要去回答两个问题,寄存器是什么?0x20200000 是一个什么样的数字?
|
||||
|
||||
```
|
||||
树莓派上的一个单独的寄存器能够保存任何介于 0 到 4,294,967,295(含) 之间的任意整数,它可能看起来像一个很大的内存,实际上它仅有 32 个二进制比特。
|
||||
```
|
||||
|
||||
一个寄存器在处理器中就是一个极小的内存块,它是处理器保存正在处理的数字的地方。处理器中有很多寄存器,很多都有专门的用途,我们在后面会一一接触到它们。重要的是,它们有十三个(命名为 r0、r1、r2、…、r9、r10、r11、r12),它们被称为通用寄存器,你可以使用它们做任何计算。由于是写我们的第一行代码,我们在示例中使用了 r0,当然你可以使用它们中的任何一个。只要后面始终如一就没有问题。
|
||||
|
||||
0x20200000 是一个准确的数字。只不过它是以十六进制表示的。下面的内容详细解释了十六进制的相关信息:
|
||||
|
||||
十六进制是另一种表示数字的方式。你或许只知道十进制的数字表示方法,十进制共有十个数字:0、1、2、3、4、5、6、7、8 和 9。十六进制共有十六个数字:0、1、2、3、4、5、6、7、8、9、a、b、c、d、e 和 f。
|
||||
|
||||
![567 is 5 hundreds, 6 tens and 7 units.][2]
|
||||
|
||||
你可能还记得十进制是如何用位制来表示的。即最右侧的数字是个位,紧接着的左边一位是十位,再接着的左边一位是百位,依此类推。也就是说,它的值是 100 × 百位的数字,再加上 10 × 十位的数字,再加上 1 × 个位的数字。
|
||||
|
||||
![567 is 5x10^2+6x10^1+7x10^0][3]
|
||||
|
||||
从数学的角度来看,我们可以发现规律,最右侧的数字是 10<sup>0</sup>=1s,紧接着的左边一位是 10<sup>1</sup>=10s,再接着是 10<sup>2</sup>=100s,依此类推。我们设定在系统中,0 是最低位,紧接着是 1,依此类推。但如果我们使用一个不同于 10 的数字为幂底会是什么样呢?我们在系统中使用的十六进制就是这样的一个数字。
|
||||
|
||||
![567 = 5x10^2+6x10^1+7x10^0 = 2x16^2+3x16^1+7x16^0][4]
|
||||
|
||||
上面的数学等式表明,十进制的数字 567 等于十六进制的数字 237。通常我们需要在系统中明确它们,我们使用下标 <sub>10</sub> 表示它是十进制数字,用下标 <sub>16</sub> 表示它是十六进制数字。由于在汇编代码中写上下标的小数字很困难,因此我们使用 0x 来表示它是一个十六进制的数字,因此 0x237 的意思就是 237<sub>16</sub> 。
|
||||
|
||||
那么,后面的 a、b、c、d、e 和 f 又是什么呢?好问题!在十六进制中为了能够写每个数字,我们就需要额外的东西。例如 9<sub>16</sub> = 9×16<sup>0</sup> = 9<sub>10</sub> ,但是 10<sub>16</sub> = 1×16<sup>1</sup> + 1×16<sup>0</sup> = 16<sub>10</sub> 。因此,如果我们只使用 0、1、2、3、4、5、6、7、8 和 9,我们就无法写出 10<sub>10</sub> 、11<sub>10</sub> 、12<sub>10</sub> 、13<sub>10</sub> 、14<sub>10</sub> 、15<sub>10</sub> 。因此我们引入了 6 个新的数字,这样 a<sub>16</sub> = 10<sub>10</sub> 、b<sub>16</sub> = 11<sub>10</sub> 、c<sub>16</sub> = 12<sub>10</sub> 、d<sub>16</sub> = 13<sub>10</sub> 、e<sub>16</sub> = 14<sub>10</sub> 、f<sub>16</sub> = 15<sub>10</sub> 。
|
||||
|
||||
所以,我们就有了另一种写数字的方式。但是我们为什么要这么麻烦呢?好问题!由于计算机总是工作在二进制中,事实证明,十六进制是非常有用的,因为每个十六进制数字正好是四个二进制数字的长度。这种方法还有另外一个好处,那就是许多计算机的数字都是十六进制的整数倍,而不是十进制的整数倍。比如,我在上面的汇编代码中使用的一个数字 20200000<sub>16</sub> 。如果我们用十进制来写,它就是一个不太好记住的数字 538968064<sub>10</sub> 。
|
||||
|
||||
我们可以用下面的简单方法将十进制转换成十六进制:
|
||||
|
||||
![Conversion example][5]
|
||||
|
||||
1. 我们以十进制数字 567 为例来说明。
|
||||
2. 将十进制数字 567 除以 16 并计算其余数。例如 567 ÷ 16 = 35 余数为 7。
|
||||
3. 在十六进制中余数就是答案中的最后一位数字,在我们的例子中它是 7。
|
||||
4. 重复第 2 步和第 3 步,直到除法结果的整数部分为 0。例如 35 ÷ 16 = 2 余数为 3,因此 3 就是答案中的下一位。2 ÷ 16 = 0 余数为 2,因此 2 就是答案的接下来一位。
|
||||
5. 一旦除法结果的整数部分为 0 就结束了。答案就是反序的余数,因此 567<sub>10</sub> = 237<sub>16</sub>。
|
||||
|
||||
|
||||
|
||||
转换十六进制数字为十进制,也很容易,将数字展开即可,因此 237<sub>16</sub> = 2×16<sup>2</sup> + 3×16<sup>1</sup> +7 ×16<sup>0</sup> = 2×256 + 3×16 + 7×1 = 512 + 48 + 7 = 567。
|
||||
|
||||
因此,我们所写的第一个汇编命令是将数字 20200000<sub>16</sub> 加载到寄存器 r0 中。那个命令看起来似乎没有什么用,但事实并非如此。在计算机中,有大量的内存块和设备。为了能够访问它们,我们给每个内存块和设备指定了一个地址。就像邮政地址或网站地址一样,它用于标识我们想去访问的内存块或设备的位置。计算机中的地址就是一串数字,因此上面的数字 20200000<sub>16</sub> 就是 GPIO 控制器的地址。这个地址是由制造商的设计所决定的,他们也可以使用其它地址(只要不与其它的冲突即可)。我之所以知道这个地址是 GPIO 控制器的地址是因为我看了它的[手册][https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads/SoC-Peripherals.pdf],地址的使用没有专门的规范(除了它们都是以十六进制表示的大数以外)。
|
||||
|
||||
### 4、启用输出
|
||||
|
||||
![A diagram showing key parts of the GPIO controller.][6]
|
||||
|
||||
阅读了手册可以得知,我们需要给 GPIO 控制器发送两个消息。我们必须用它的语言告诉它,如果我们这样做了,它将非常乐意实现我们的意图,去打开 `OK` 的 LED 指示灯。幸运的是,它是一个非常简单的芯片,为了让它能够理解我们要做什么,只需要给它设定几个数字即可。
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#18
|
||||
str r1,[r0,#4]
|
||||
```
|
||||
|
||||
```
|
||||
mov reg,#val 将数字 val 放到名为 reg 的寄存器中。
|
||||
|
||||
lsl reg,#val 将寄存器 reg 中的二进制操作数左移 val 位。
|
||||
|
||||
str reg,[dest,#val] 将寄存器 reg 中的数字保存到地址 dest + val 上。
|
||||
```
|
||||
|
||||
这些命令的作用是在 GPIO 的第 16 号插针上启用输出。首先我们在寄存器 r1 中获取一个必需的值,接着将这个值发送到 GPIO 控制器。因此,前两个命令是尝试取值到寄存器 r1 中,我们可以像前面一样使用另一个命令 `ldr` 来实现,但 `lsl` 命令对我们后面能够设置任何给定的 GPIO 针比较有用,因此从一个公式中推导出值要比直接写入来好一些。表示 `OK` 的 LED 灯是直接连线到 GPIO 的第 16 号针脚上的,因此我们需要发送一个命令去启用第 16 号针脚。
|
||||
|
||||
寄存器 r1 中的值是启用 LED 针所需要的。第一行命令将数字 1<sub>10</sub> 放到 r1 中。在这个操作中 `mov` 命令要比 `ldr` 命令快很多,因为它不需要与内存交互,而 `ldr` 命令是将需要的值从内存中加载到寄存器中。尽管如此,`mov` 命令仅能用于加载某些值。在 ARM 汇编代码中,基本上每个指令都使用一个三字母代码表示。它们被称为助记词,用于表示操作的用途。`mov` 是 “move" 的简写,而 `ldr` 是 “load register” 的简写。`mov` 是将第二个参数 #1 移动到前面的 r1 寄存器中。一般情况下,`#` 肯定是表示一个数字,但我们已经看到了不符合这种情况的一个反例。
|
||||
|
||||
第二个指令是 `lsl`(逻辑左移)。它的意思是将第一个参数的二进制操作数向左移第二个参数所表示的位数。在这个案例中,将 1<sub>10</sub> (即 1<sub>2</sub> )向左移 18 位(将它变成 1000000000000000000<sub>2</sub>=262144<sub>10</sub> )。
|
||||
|
||||
如果你不熟悉二进制表示法,可以看下面的内容:
|
||||
|
||||
与十六进制一样,二进制是写数字的另一种方法。在二进制中只有两个数字,即 0 和 1。它在计算机中非常有用,因为我们可以用电路来实现它,即电流能够通过电路表示为 1,而电流不能通过电路表示为 0。这就是计算机能够完成真实工作和做数学运算的原理。尽管二进制只有两个数字,但它却能够表示任何一个数字,只是写起来有点长而已。
|
||||
|
||||
![567 in decimal = 1000110111 in binary][7]
|
||||
|
||||
这个图片展示了 567<sub>10</sub> 的二进制表示是 1000110111<sub>2</sub> 。我们使用下标 2 来表示这个数字是用二进制写的。
|
||||
|
||||
我们在汇编代码中大量使用二进制的其中一个巧合之处是,数字可以很容易地被 2 的幂(即 1、2、4、8、16)乘或除。通常乘法和除法都是非常难的,而在某些特殊情况下却变得非常容易,所以二进制非常重要。
|
||||
|
||||
![13*4 = 52, 1101*100=110100][8]
|
||||
|
||||
将一个二进制数字左移 **n** 位就相当于将这个数字乘以 2<sup> **n**</sup>。因此,如果我们想将一个数乘以 4,我们只需要将这个数字左移 2 位。如果我们想将它乘以 256,我们只需要将它左移 8 位。如果我们想将一个数乘以 12 这样的数字,我们可以有一个替代做法,就是先将这个数乘以 8,然后再将那个数乘以 4,最后将两次相乘的结果相加即可得到最终结果(N × 12 = N × (8 + 4) = N × 8 + N × 4)。
|
||||
|
||||
![53/16 = 3, 110100/10000=11][9]
|
||||
|
||||
右移一个二进制数 **n** 位就相当于这个数除以 2 <sup>**n**</sup> 。在右移操作中,除法的余数位将被丢弃。不幸的是,如果对一个不能被 2 的幂次方除尽的二进制数字做除法是非常难的,这将在 [课程 9:Screen04][10] 中讲到。
|
||||
|
||||
![Binary Terminology][11]
|
||||
|
||||
这个图展示了二进制常用的术语。一个<ruby>比特<rt>bit</rt></ruby>就是一个单独的二进制位。一个“<ruby>半字节<rt>nibble</rt></ruby>“ 是 4 个二进制位。一个<ruby>字节<rt>byte</rt></ruby>是 2 个半字节,也就是 8 个比特。在一个<ruby>字<rt>word</rt></ruby>用两个字节来表示的情况下,一半是指一个字长度的一半。一个字是指处理器上寄存器的大小,因此,树莓派的字长是 4 字节。按惯例,将一个数字最高有效位标识为 31,而将最低有效位标识为 0。顶部或最高位表示最高有效位,而底部或最低位表示最低有效位。一个 kilobyte(KB)就是 1000 字节,一个 megabyte 就是 1000 KB。这样表示会导致一些困惑,到底应该是 1000 还是 1024(二进制中的整数)。鉴于这种情况,新的国际标准规定,一个 KB 等于 1000 字节,而一个 Kibibyte(KiB)是 1024 字节。一个 Kb 是 1000 比特,而一个 Kib 是 1024 比特。
|
||||
|
||||
树莓派默认采用小端法,也就是说,你刚才写的从地址上加载一个字节时,是从一个字的低位字节开始加载的。
|
||||
|
||||
再强调一次,我们只有去阅读手册才能知道我们所需要的值。手册上说,GPIO 控制器中有一个 24 字节的集合,由它来决定 GPIO 针脚的设置。第一个 4 字节与前 10 个 GPIO 针脚有关,第二个 4 字节与接下来的 10 个针脚有关,依此类推。总共有 54 个 GPIO 针脚,因此,我们需要 6 个 4 字节的一个集合,总共是 24 个字节。在每个 4 字节中,每 3 个比特与一个特定的 GPIO 针脚有关。我们想去启用的是第 16 号 GPIO 针脚,因此我们需要去设置第二组 4 字节,因为第二组的 4 字节用于处理 GPIO 针脚的第 10-19 号,而我们需要 3 比特集合的第 6 位,它在上面的代码中的编号是 18(6×3)。
|
||||
|
||||
最后的 `str`(store register)命令去保存第一个参数中的值,将寄存器 r1 中的值保存到后面的表达式计算出来的地址上。这个表达式可以是一个寄存器,在上面的例子中是 r0,我们知道 r0 中保存了GPIO 控制器的地址,而另一个值是加到它上面的,在这个例子中是 #4。它的意思是将 GPIO 控制器地址加上 4 得到一个新的地址,并将寄存器 r1 中的值写到那个地址上。那个地址就是我们前面提到的第二个 4 字节集合的位置,因此,我们发送我们的第一个消息到 GPIO 控制器上,告诉它准备启用 GPIO 第 16 号针脚的输出。
|
||||
|
||||
### 5、一个活跃信号
|
||||
|
||||
现在,LED 已经做好了打开准备,我们还需要实际去打开它。意味着需要给 GPIO 控制器发送一个消息去关闭 16 号针脚。是的,你没有看错,就是要发送一个关闭的消息。芯片制造商认为,在 GPIO 针脚关闭时打开 LED 更有意义。硬件工程师经常做这种反常理的决策,似乎是为了让操作系统开发者保持警觉。可以认为是给自己的一个警告。
|
||||
|
||||
```
|
||||
mov r1,#1
|
||||
lsl r1,#16
|
||||
str r1,[r0,#40]
|
||||
```
|
||||
|
||||
希望你能够认识上面全部的命令,先不要管它的值。第一个命令和前面一样,是将值 1 推入到寄存器 r1 中。第二个命令是将二进制的 1 左移 16 位。由于我们是希望关闭 GPIO 的 16 号针脚,我们需要在下一个消息中将第 16 比特设置为 1(想设置其它针脚只需要改变相应的比特位即可)。最后,我们写这个值到 GPIO 控制器地址加上 40<sub>10</sub> 的地址上,这将使那个针脚关闭(加上 28 将打开针脚)。
|
||||
|
||||
### 6、永远幸福快乐
|
||||
|
||||
现在结束,可能有点意犹未尽,但不幸的是,处理器并不知道我们做了什么。事实上,处理器只要通电,它就永不停止地运转。因此,我们需要给它一个任务,让它一直运转下去,否则,树莓派将进入休眠(本示例中不会,因为 LED 灯一直亮着)。
|
||||
|
||||
```
|
||||
loop$:
|
||||
b loop$
|
||||
```
|
||||
|
||||
```
|
||||
name: labels 下一行的名字。
|
||||
|
||||
b label 下一行将去运行标签。
|
||||
```
|
||||
|
||||
第一行不是一个命令,而是一个标签。它是下一行循环 `loop$` 的名字,这意味着我们能够通过名字来指向到行。这就称为一个标签。当代码被转换成二进制后,标签将被丢弃,但这对我们通过名字而不是数字(地址)找到行比较有用。按惯例,我们使用一个 $ 表示标签,这个标签只对这个代码块中的代码起作用,让其它人知道,它不对整个程序起作用。`b`(branch)命令将去运行指定的标签中的命令,而不是去运行它后面的下一个命令。因此,下一行将再次去运行这个 `b` 命令,这将导致永远循环下去。因此处理器将进入一个无限循环中,直到它安全关闭为止。
|
||||
|
||||
代码块结尾的新行是有意这样写的。GNU 工具链要求所有的汇编代码文件都是以空行结束的,因此,这就需要你确保确实是要结束了,并且文件不能被截断。如果你不这样处理,在汇编器运行时,你将收到烦人的警告。
|
||||
|
||||
### 7、树莓派上场
|
||||
|
||||
由于我们已经写完了代码,现在,我们可以将它上传到树莓派中了。在你的计算机上打开一个终端,改变当前工作目录为 `source` 文件夹的父级目录。输入 `make` 然后回车。如果报错,请参考排错章节。如果没有报错,你将生成三个文件。 `kernel.img` 是你的编译后的操作系统镜像。`kernel.list` 是你写的汇编代码的一个清单,它实际上是生成的。这在将来检查程序是否正确时非常有用。`kernel.map` 文件包含所有标签结束位置的一个映射,这对于跟踪值非常有用。
|
||||
|
||||
为安装你的操作系统,需要先有一个已经安装了树莓派操作系统的 SD 卡。如果你浏览 SD 卡中的文件,你应该能看到一个名为 `kernel.img` 的文件。将这个文件重命名为其它名字,比如 `kernel_linux.img`。然后,复制你编译的 `kernel.img` 文件到 SD 卡中原来的位置,这将用你的操作系统镜像文件替换现在的树莓派操作系统镜像。想切换回来时,只需要简单地删除你自己的 `kernel.img` 文件,然后将前面重命名的文件改回 `kernel.img` 即可。我发现,保留一个原始的树莓派操作系统的备份是非常有用的,万一你要用到它呢。
|
||||
|
||||
将这个 SD 卡插入到树莓派,并打开它的电源。这个 `OK` 的 LED 灯将亮起来。如果不是这样,请查看故障排除页面。如果一切如愿,恭喜你,你已经写出了你的第一个操作系统。[课程 2:OK02][12] 将指导你让 LED 灯闪烁和关闭闪烁。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html
|
||||
|
||||
作者:[Robert Mullins][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: http://www.cl.cam.ac.uk/~rdm34
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal1.png
|
||||
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal2.png
|
||||
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal3.png
|
||||
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/hexadecimal4.png
|
||||
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioController.png
|
||||
[7]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary1.png
|
||||
[8]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary2.png
|
||||
[9]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
|
||||
[10]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen04.html
|
||||
[11]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary4.png
|
||||
[12]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok02.html
|
@ -0,0 +1,87 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: subject: (Turn an old Linux desktop into a home media center)
|
||||
[#]: via: (https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center)
|
||||
[#]: author: ([Alan Formy-Duval](https://opensource.com/users/alanfdoss))
|
||||
[#]: url: ( )
|
||||
|
||||
将旧的 Linux 桌面变成家庭媒体中心
|
||||
======
|
||||
重新利用过时的计算机来浏览互联网并在大屏电视上观看视频。
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/migration_innovation_computer_software.png?itok=VCFLtd0q)
|
||||
|
||||
我第一次尝试搭建一台“娱乐电脑”是在 20 世纪 90 年代后期,使用一台带 Trident ProVidia 9685 PCI 显卡的普通旧台式电脑。我使用了所谓的“电视输出”卡,它有一个额外的输出连接到标准电视端子上。屏幕显示看起来不太好,而且没有音频输出。并且外观很丑:有一条 S-Video 线穿过了客厅地板连接到我的 19 英寸 Sony Trinitron CRT 电视机上。
|
||||
|
||||
我在 Linux 和 Windows 98 上也得到了同样令人遗憾的结果。在和那些看起来不对劲的系统挣扎之后,我放弃了几年。值得庆幸的是,如今的 HDMI 拥有更好的性能和标准化的分辨率,这使得廉价的家庭媒体中心成为现实。
|
||||
|
||||
我的新媒体中心娱乐电脑实际上是我的旧 Ubuntu Linux 桌面,最近我用更快的电脑替换了它。这台电脑在工作中太慢,但是它的 3.4GHz 的 AMD Phenom II X4 965 处理器和 8GB 的 RAM 足以满足一般浏览和视频流的要求。
|
||||
|
||||
以下是我让旧系统在新角色中发挥最佳性能所采取的步骤。
|
||||
|
||||
### 硬件
|
||||
|
||||
首先,我移除了不必要的设备,包括读卡器、硬盘驱动器、DVD 驱动器和后置 USB 卡,我添加了一块 PCI-Express 无线网卡。我将 Ubuntu 安装到单个固态硬盘 (SSD) 上,这可以切实提高任何旧系统的性能。
|
||||
|
||||
### BIOS
|
||||
|
||||
在 BIOS 中,我禁用了所有未使用的设备,例如软盘和 IDE 驱动器控制器。我禁用了板载显卡,因为我安装了带 HDMI 输出的 NVidia GeForce GTX 650 PCI Express 显卡。我还禁用了板载声卡,因为 NVidia 显卡芯片组提供音频。
|
||||
|
||||
### 音频
|
||||
|
||||
Nvidia GeForce GTX 音频设备在 GNOME 控制中心的声音设置中被列为 GK107 HDMI Audio Controller,因此单条 HDMI 线缆可同时处理音频和视频。无需将音频线连接到板载声卡的输出插孔。
|
||||
|
||||
![Sound settings screenshot][2]
|
||||
|
||||
GNOME 音频设置中的 HDMI 音频控制器。
|
||||
|
||||
### 键盘和鼠标
|
||||
|
||||
我有罗技的无线键盘和鼠标。当我安装它们时,我插入了两个外置 USB 接收器,它们可以使用,但我经常遇到信号反应问题。接着我发现其中一个被标记为联合接收器,这意味着它可以自己处理多个罗技输入设备。罗技不提供在 Linux 中配置统一接收器的软件。但幸运的是,有个开源程序 [Solaar][3] 能够做到。使用单个接收器解决了我的输入性能问题。
|
||||
|
||||
![Solaar][5]
|
||||
|
||||
Solaar 联合接收器界面。
|
||||
|
||||
### 视频
|
||||
|
||||
最初很难在我的 47 英寸平板电视上阅读,所以我在 Universal Access 下启用了“大文字”。我下载了一些与电视 1920x1080 分辨率相匹配的壁纸,这看起来很棒!
|
||||
|
||||
### 最后处理
|
||||
|
||||
我需要在电脑的冷却需求和我对不受阻碍的娱乐的渴望之间取得平衡。由于这是一台标准的 ATX 微型塔式计算机,我确保我有足够的风扇,以及在 BIOS 中精心配置过的温度以减少噪音。我还把电脑放在我的娱乐控制台后面,以进一步减少风扇噪音,但同时我可以按到电源按钮。
|
||||
|
||||
最后得到一台简单的没有巨大噪音的机器,而且只使用了两根线缆—交流电源线和 HDMI。它应该能够运行任何主流或专门的媒体中心 Linux 发行版。我不期望去玩高端的游戏,因为这可能需要更多的处理能力。
|
||||
|
||||
![Showing Ubuntu Linux About page onscreen][7]
|
||||
|
||||
Ubuntu Linux 的关于页面。
|
||||
|
||||
![YouTube on the big screen][9]
|
||||
|
||||
在大屏幕上测试 YouTube 视频。
|
||||
|
||||
我还没安装像 [Kodi][10] 这样专门的媒体中心发行版。截至目前,它运行的是 Ubuntu Linux 18.04.1 LTS,而且很稳定。
|
||||
|
||||
这是一个有趣的挑战,可以充分利用我已经拥有的东西,而不是购买新的硬件。这只是开源软件的一个好处。最终,我可能会用一个更小,更安静的带有媒体中心的系统或其他小机顶盒替换它,但是现在,它很好地满足了我的需求。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/11/old-linux-desktop-new-home-media-center
|
||||
|
||||
作者:[Alan Formy-Duval][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alanfdoss
|
||||
[b]: https://github.com/lujun9972
|
||||
[2]: https://opensource.com/sites/default/files/uploads/soundsettings.png (Sound settings screenshot)
|
||||
[3]: https://pwr.github.io/Solaar/
|
||||
[5]: https://opensource.com/sites/default/files/uploads/solaar_interface.png (Solaar)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/finalresult1.png (Showing Ubuntu Linux About page onscreen)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/finalresult2.png (YouTube on the big screen)
|
||||
[10]: https://kodi.tv/
|
Loading…
Reference in New Issue
Block a user