Merge pull request #9 from LCTT/master

update
This commit is contained in:
acyanbird 2019-02-04 21:23:13 +08:00 committed by GitHub
commit b73868e299
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1439 additions and 1434 deletions

View File

@ -0,0 +1,339 @@
如何搜索一个包是否在你的 Linux 发行版中
======
如果你知道包名称,那么你可以直接安装所需的包。
在某些情况下,如果你不知道确切的包名称或者你想搜索某些包,那么你可以在发行版的包管理器的帮助下轻松搜索该包。搜索会自动包括已安装和可用的包。结果的格式取决于选项。如果你的查询没有输出任何信息,那么意味着没有匹配条件的包。这可以通过发行版的包管理器的各种选项来完成。我已经在本文中添加了所有可能的选项,你可以选择最好的和最合适你的选项。
或者,我们可以通过 `whohas` 命令实现这一点。它会从所有的主流发行版(例如 Debian、Ubuntu、 Fedora 等)中搜索,而不仅仅是你自己的系统发行版。
建议阅读:
- [适用于 Linux 的命令行包管理器列表以及用法][1]
- [Linux 包管理器的图形前端工具][2]
### 如何在 Debian/Ubuntu 中搜索一个包
我们可以使用 `apt`、`apt-cache` 和 `aptitude` 包管理器在基于 Debian 的发行版上查找给定的包。我为这个包管理器中包括了大量的选项。
我们可以在基于 Debian 的系统中使用三种方式完成此操作。
* `apt` 命令
* `apt-cache` 命令
* `aptitude` 命令
#### 如何使用 apt 命令搜索一个包
APT 代表<ruby>高级包管理工具<rt>Advanced Packaging Tool</rt></ruby>APT它取代了 `apt-get`。它有功能丰富的命令行工具,包括所有功能包含在一个命令(`apt`)里,包括 `apt-cache`、`apt-search`、`dpkg`、`apt-cdrom`、`apt-config`、`apt-key` 等,还有其他几个独特的功能。
APT 是一个强大的命令行工具,它可以访问 libapt-pkg 底层库的所有特性,它可以用于安装、下载、删除、搜索和管理以及查询包的信息,另外它还包含一些较少使用的与包管理相关的命令行实用程序。
```
$ apt -q list nano vlc
Listing...
nano/artful,now 2.8.6-3 amd64 [installed]
vlc/artful 2.2.6-6 amd64
```
或者,我们可以使用以下格式搜索指定的包。
```
$ apt search ^vlc
Sorting... Done
Full Text Search... Done
vlc/artful 2.2.6-6 amd64
multimedia player and streamer
vlc-bin/artful 2.2.6-6 amd64
binaries from VLC
vlc-data/artful,artful 2.2.6-6 all
Common data for VLC
vlc-l10n/artful,artful 2.2.6-6 all
Translations for VLC
vlc-plugin-access-extra/artful 2.2.6-6 amd64
multimedia player and streamer (extra access plugins)
vlc-plugin-base/artful 2.2.6-6 amd64
multimedia player and streamer (base plugins)
```
#### 如何使用 apt-cache 命令搜索一个包
`apt-cache` 会在 APT 的包缓存上执行各种操作。它会显示有关指定包的信息。`apt-cache` 不会改变系统的状态,但提供了从包的元数据中搜索和生成有趣输出的操作。
```
$ apt-cache search nano | grep ^nano
nano - small, friendly text editor inspired by Pico
nano-tiny - small, friendly text editor inspired by Pico - tiny build
nanoblogger - Small weblog engine for the command line
nanoblogger-extra - Nanoblogger plugins
nanoc - static site generator written in Ruby
nanoc-doc - static site generator written in Ruby - documentation
nanomsg-utils - nanomsg utilities
nanopolish - consensus caller for nanopore sequencing data
```
或者,我们可以使用以下格式搜索指定的包。
```
$ apt-cache policy vlc
vlc:
Installed: (none)
Candidate: 2.2.6-6
Version table:
2.2.6-6 500
500 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 Packages
```
或者,我们可以使用以下格式搜索给定的包。
```
$ apt-cache pkgnames vlc
vlc-bin
vlc-plugin-video-output
vlc-plugin-sdl
vlc-plugin-svg
vlc-plugin-samba
vlc-plugin-fluidsynth
vlc-plugin-qt
vlc-plugin-skins2
vlc-plugin-visualization
vlc-l10n
vlc-plugin-notify
vlc-plugin-zvbi
vlc-plugin-vlsub
vlc-plugin-jack
vlc-plugin-access-extra
vlc
vlc-data
vlc-plugin-video-splitter
vlc-plugin-base
```
#### 如何使用 aptitude 命令搜索一个包
`aptitude` 是一个基于文本的 Debian GNU/Linux 软件包系统的命令行界面。它允许用户查看包列表,并执行包管理任务,例如安装、升级和删除包,它可以从可视化界面或命令行执行操作。
```
$ aptitude search ^vlc
p vlc - multimedia player and streamer
p vlc:i386 - multimedia player and streamer
p vlc-bin - binaries from VLC
p vlc-bin:i386 - binaries from VLC
p vlc-data - Common data for VLC
v vlc-data:i386 -
p vlc-l10n - Translations for VLC
v vlc-l10n:i386 -
p vlc-plugin-access-extra - multimedia player and streamer (extra access plugins)
p vlc-plugin-access-extra:i386 - multimedia player and streamer (extra access plugins)
p vlc-plugin-base - multimedia player and streamer (base plugins)
p vlc-plugin-base:i386 - multimedia player and streamer (base plugins)
p vlc-plugin-fluidsynth - FluidSynth plugin for VLC
p vlc-plugin-fluidsynth:i386 - FluidSynth plugin for VLC
p vlc-plugin-jack - Jack audio plugins for VLC
p vlc-plugin-jack:i386 - Jack audio plugins for VLC
p vlc-plugin-notify - LibNotify plugin for VLC
p vlc-plugin-notify:i386 - LibNotify plugin for VLC
p vlc-plugin-qt - multimedia player and streamer (Qt plugin)
p vlc-plugin-qt:i386 - multimedia player and streamer (Qt plugin)
p vlc-plugin-samba - Samba plugin for VLC
p vlc-plugin-samba:i386 - Samba plugin for VLC
p vlc-plugin-sdl - SDL video and audio output plugin for VLC
p vlc-plugin-sdl:i386 - SDL video and audio output plugin for VLC
p vlc-plugin-skins2 - multimedia player and streamer (Skins2 plugin)
p vlc-plugin-skins2:i386 - multimedia player and streamer (Skins2 plugin)
p vlc-plugin-svg - SVG plugin for VLC
p vlc-plugin-svg:i386 - SVG plugin for VLC
p vlc-plugin-video-output - multimedia player and streamer (video output plugins)
p vlc-plugin-video-output:i386 - multimedia player and streamer (video output plugins)
p vlc-plugin-video-splitter - multimedia player and streamer (video splitter plugins)
p vlc-plugin-video-splitter:i386 - multimedia player and streamer (video splitter plugins)
p vlc-plugin-visualization - multimedia player and streamer (visualization plugins)
p vlc-plugin-visualization:i386 - multimedia player and streamer (visualization plugins)
p vlc-plugin-vlsub - VLC extension to download subtitles from opensubtitles.org
p vlc-plugin-zvbi - VBI teletext plugin for VLC
p vlc-plugin-zvbi:i386
```
### 如何在 RHEL/CentOS 中搜索一个包
YumYellowdog Updater Modified是 Linux 操作系统中的包管理器实用程序之一。Yum 命令用于在一些基于 RedHat 的 Linux 发行版上,它用来安装、更新、搜索和删除软件包。
```
# yum search ftpd
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
* base: centos.hyve.com
* epel: mirrors.coreix.net
* extras: centos.hyve.com
* rpmforge: www.mirrorservice.org
* updates: mirror.sov.uk.goscomb.net
============================================================== N/S Matched: ftpd ===============================================================
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
vsftpd.x86_64 : Very Secure Ftp Daemon
Name and summary matches only, use "search all" for everything.
```
或者,我们可以使用以下命令搜索相同内容。
```
# yum list ftpd
```
### 如何在 Fedora 中搜索一个包
DNF 代表 Dandified yum。我们可以说 DNF 是下一代 yum 包管理器Yum 的衍生品),它使用 hawkey/libsolv 库作为底层。Aleš Kozumplík 从 Fedora 18 开始开发 DNF最终在 Fedora 22 中发布。
```
# dnf search ftpd
Last metadata expiration check performed 0:42:28 ago on Tue Jun 9 22:52:44 2018.
============================== N/S Matched: ftpd ===============================
proftpd-utils.x86_64 : ProFTPD - Additional utilities
pure-ftpd-selinux.x86_64 : SELinux support for Pure-FTPD
proftpd-devel.i686 : ProFTPD - Tools and header files for developers
proftpd-devel.x86_64 : ProFTPD - Tools and header files for developers
proftpd-ldap.x86_64 : Module to add LDAP support to the ProFTPD FTP server
proftpd-mysql.x86_64 : Module to add MySQL support to the ProFTPD FTP server
proftpd-postgresql.x86_64 : Module to add PostgreSQL support to the ProFTPD FTP
: server
vsftpd.x86_64 : Very Secure Ftp Daemon
proftpd.x86_64 : Flexible, stable and highly-configurable FTP server
owfs-ftpd.x86_64 : FTP daemon providing access to 1-Wire networks
perl-ftpd.noarch : Secure, extensible and configurable Perl FTP server
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
pyftpdlib.noarch : Python FTP server library
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
```
或者,我们可以使用以下命令搜索相同的内容。
```
# dnf list proftpd
Failed to synchronize cache for repo 'heikoada-terminix', disabling.
Last metadata expiration check: 0:08:02 ago on Tue 26 Jun 2018 04:30:05 PM IST.
Available Packages
proftpd.x86_64
```
### 如何在 Arch Linux 中搜索一个包
pacman 代表包管理实用程序pacman。它是一个用于安装、构建、删除和管理 Arch Linux 软件包的命令行实用程序。pacman 使用 libalpmArch Linux Package ManagementALPM作为底层来执行所有操作。
在本例中,我将要搜索 chromium 包。
```
# pacman -Ss chromium
extra/chromium 48.0.2564.116-1
The open-source project behind Google Chrome, an attempt at creating a safer, faster, and more stable browser
extra/qt5-webengine 5.5.1-9 (qt qt5)
Provides support for web applications using the Chromium browser project
community/chromium-bsu 0.9.15.1-2
A fast paced top scrolling shooter
community/chromium-chromevox latest-1
Causes the Chromium web browser to automatically install and update the ChromeVox screen reader extention. Note: This
package does not contain the extension code.
community/fcitx-mozc 2.17.2313.102-1
Fcitx Module of A Japanese Input Method for Chromium OS, Windows, Mac and Linux (the Open Source Edition of Google Japanese
Input)
```
默认情况下,`-s` 选项内置 ERE扩展正则表达式会导致很多不需要的结果。使用以下格式会仅匹配包名称。
```
# pacman -Ss '^chromium-'
```
`pkgfile` 是一个用于在 Arch Linux 官方仓库的包中搜索文件的工具。
```
# pkgfile chromium
```
### 如何在 openSUSE 中搜索一个包
Zypper 是 SUSE 和 openSUSE 发行版的命令行包管理器。它用于安装、更新、搜索和删除包以及管理仓库执行各种查询等。Zypper 命令行对接到 ZYpp 系统管理库libzypp
```
# zypper search ftp
or
# zypper se ftp
Loading repository data...
Reading installed packages...
S | Name | Summary | Type
--+----------------+-----------------------------------------+--------
| proftpd | Highly configurable GPL-licensed FTP -> | package
| proftpd-devel | Development files for ProFTPD | package
| proftpd-doc | Documentation for ProFTPD | package
| proftpd-lang | Languages for package proftpd | package
| proftpd-ldap | LDAP Module for ProFTPD | package
| proftpd-mysql | MySQL Module for ProFTPD | package
| proftpd-pgsql | PostgreSQL Module for ProFTPD | package
| proftpd-radius | Radius Module for ProFTPD | package
| proftpd-sqlite | SQLite Module for ProFTPD | package
| pure-ftpd | A Lightweight, Fast, and Secure FTP S-> | package
| vsftpd | Very Secure FTP Daemon - Written from-> | package
```
### 如何使用 whohas 命令搜索一个包
`whohas` 命令是一个智能工具,从所有主流发行版中搜索指定包,如 Debian、Ubuntu、Gentoo、Arch、AUR、Mandriva、Fedora、Fink、FreeBSD 和 NetBSD。
```
$ whohas nano
Mandriva nano-debug 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/0b33dc73bca710749ad14bbc3a67e15a
Mandriva nano-debug 2.2.4-1mdv2010.1.i http://sophie.zarb.org/rpms/d9dfb2567681e09287b27e7ac6cdbc05
Mandriva nano-debug 2.2.4-1mdv2010.1.x http://sophie.zarb.org/rpms/3299516dbc1538cd27a876895f45aee4
Mandriva nano 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/98421c894ee30a27d9bd578264625220
Mandriva nano 2.3.1-1mdv2010.2.i http://sophie.zarb.org/rpms/cea07b5ef9aa05bac262fc7844dbd223
Mandriva nano 2.2.4-1mdv2010.1.s http://sophie.zarb.org/rpms/d61f9341b8981e80424c39c3951067fa
Mandriva spring-mod-nanoblobs 0.65-2mdv2010.0.sr http://sophie.zarb.org/rpms/74bb369d4cbb4c8cfe6f6028e8562460
Mandriva nanoxml-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/287a4c37bc2a39c0f277b0020df47502
Mandriva nanoxml-manual-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/17dc4f638e5e9964038d4d26c53cc9c6
Mandriva nanoxml-manual 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/a1b5092cd01fc8bb78a0f3ca9b90370b
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 2.9.8 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 2.9.7
```
如果你希望只从当前发行版仓库中搜索指定包,使用以下格式:
```
$ whohas -d Ubuntu vlc
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty/vlc
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty-updates/vlc
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial/vlc
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial-updates/vlc
Ubuntu vlc 2.2.6-6 40K all http://packages.ubuntu.com/artful/vlc
Ubuntu vlc 3.0.1-3build1 32K all http://packages.ubuntu.com/bionic/vlc
Ubuntu vlc 3.0.2-0ubuntu0.1 32K all http://packages.ubuntu.com/bionic-updates/vlc
Ubuntu vlc 3.0.3-1 33K all http://packages.ubuntu.com/cosmic/vlc
Ubuntu browser-plugin-vlc 2.0.6-2 55K all http://packages.ubuntu.com/trusty/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/xenial/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/artful/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/bionic/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/cosmic/browser-plugin-vlc
Ubuntu libvlc-bin 2.2.6-6 27K all http://packages.ubuntu.com/artful/libvlc-bin
Ubuntu libvlc-bin 3.0.1-3build1 17K all http://packages.ubuntu.com/bionic/libvlc-bin
Ubuntu libvlc-bin 3.0.2-0ubuntu0.1 17K all
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/how-to-search-if-a-package-is-available-on-your-linux-distribution-or-not/
作者:[Prakash Subramanian][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.2daygeek.com/author/prakash/
[1]:https://www.2daygeek.com/list-of-command-line-package-manager-for-linux/
[2]:https://www.2daygeek.com/list-of-graphical-frontend-tool-for-linux-package-manager/

View File

@ -1,16 +1,16 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10507-1.html)
[#]: subject: (Get started with Roland, a random selection tool for the command line)
[#]: via: (https://opensource.com/article/19/1/productivity-tools-roland)
[#]: author: (Kevin Sonney https://opensource.com/users/ksonney (Kevin Sonney))
开始使用 Roland一款命令行随机选择工具
开始使用 Roland,一款命令行随机选择工具
======
Roland 是我们在开源工具系列中的第七个工具,将帮助你在 2019 年提高工作效率。
> Roland 可以帮你做出艰难的决定,它是我们在开源工具系列中的第七个工具,将帮助你在 2019 年提高工作效率。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/dice_tabletop_board_gaming_game.jpg?itok=y93eW7HN)
@ -22,13 +22,13 @@ Roland 是我们在开源工具系列中的第七个工具,它将帮助你在
当一周的工作结束后,我唯一想做的就是躺到沙发上打一个周末的游戏。但即使我的职业义务在工作日结束后停止了,但我仍然需要管理我的家庭。洗衣、宠物护理、确保我孩子有他所需要的东西,以及最重要的是:决定晚餐吃什么。
像许多人一样,我经常受到[决策疲劳][1]的困扰,根据速度、准备难易以及(坦白地说)任何让我压力最小的方式都会导致不太健康的晚餐选择。
像许多人一样,我经常受到[决策疲劳][1]的困扰,根据速度、准备难易程度以及(坦白地说)任何让我压力最小的方式都会导致不太健康的晚餐选择。
![](https://opensource.com/sites/default/files/uploads/roland-1.png)
[Roland][2]让我计划饭菜变得容易。Roland 是一款专为桌面角色扮演游戏设计的 Perl 应用。它从怪物和雇佣者等物品列表中随机挑选。从本质上讲Roland 在命令行做的事情与游戏大师在掷骰子时做的同样的事情,以便在游戏大师的《对玩家的坏事书》中的桌子上查找东西
[Roland][2] 让我计划饭菜变得容易。Roland 是一款专为桌面角色扮演游戏设计的 Perl 应用。它从怪物和雇佣者等项目列表中随机挑选。从本质上讲Roland 在命令行做的事情就像游戏管理员在桌子上掷骰子,以便在《要对玩家做的坏事全书》中找个东西一样
通过微小的修改Roland 可以做得更多。例如,只需添加一张桌子,我就可以让 Roland 帮我选择晚餐。
通过微小的修改Roland 可以做得更多。例如,只需添加一张,我就可以让 Roland 帮我选择晚餐。
第一步是安装 Roland 及其依赖项。
@ -41,36 +41,36 @@ cpan install Getopt::Long::Descriptive Moose \
cd oland
```
接下来,创建一个名为 **dinner** 的 YAML 文档,并输入我们所有的用餐选项。
接下来,创建一个名为 `dinner` 的 YAML 文档,并输入我们所有的用餐选项。
```
type: list
pick: 1
items:
- "frozen pizza"
 - "chipotle black beans"
 - "huevos rancheros"
 - "nachos"
 - "pork roast"
 - "15 bean soup"
 - "roast chicken"
 - "pot roast"
 - "grilled cheese sandwiches"
- "frozen pizza"
  - "chipotle black beans"
  - "huevos rancheros"
  - "nachos"
  - "pork roast"
  - "15 bean soup"
  - "roast chicken"
  - "pot roast"
  - "grilled cheese sandwiches"
```
运行命令 **bin/roland dinner** 将读取文件并选择其中一项。
运行命令 `bin/roland dinner` 将读取文件并选择其中一项。
![](https://opensource.com/sites/default/files/uploads/roland-2.png)
我想提前计划一周,这样我可以提前购买所有食材。 **pick** 命令确定列表中要选择的物品数量,现在,**pick** 设置为 1。如果我想计划一周的晚餐菜单我可以将 **pick: 1** 变成 **pick: 7**,它会提供一周的菜单。你还可以使用 **-m** 选项手动输入选择。
我想提前计划一周,这样我可以提前购买所有食材。 `pick` 命令确定列表中要选择的物品数量,现在,`pick` 设置为 1。如果我想计划一周的晚餐菜单我可以将 `pick: 1` 变成 `pick: 7`,它会提供一周的菜单。你还可以使用 `-m` 选项手动输入选择。
![](https://opensource.com/sites/default/files/uploads/roland-3.png)
你也可以用 Roland 做些有趣的事情,比如用经典短语添加一个名为 **8ball** 的文件。
你也可以用 Roland 做些有趣的事情,比如用经典短语添加一个名为 `8ball` 的文件。
![](https://opensource.com/sites/default/files/uploads/roland-4.png)
你可以创建各种文件来帮助做出长时间工作后看起来非常难做的常见决策。即使你不用来做这个,你仍然可以用它来决定为今晚的游戏设置哪个狡猾的陷阱。
你可以创建各种文件来帮助做出长时间工作后看起来非常难做的常见决策。即使你不用来做这个,你仍然可以用它来为今晚的游戏设置哪个狡猾的陷阱做个决定
--------------------------------------------------------------------------------
@ -80,7 +80,7 @@ via: https://opensource.com/article/19/1/productivity-tools-roland
作者:[Kevin Sonney][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,49 +1,49 @@
[#]: collector: (lujun9972)
[#]: translator: (zhs852)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-10508-1.html)
[#]: subject: (fdisk Easy Way To Manage Disk Partitions In Linux)
[#]: via: (https://www.2daygeek.com/linux-fdisk-command-to-manage-disk-partitions/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
fdisk Linux 下管理磁盘分区的利器
fdiskLinux 下管理磁盘分区的利器
======
一块硬盘可以被划分成一个或多个逻辑磁盘,我们将其称作分区。我们对硬盘进行的划分信息被储存于建立在扇区 0 的分区表MBR 或 GPT中。
Linux 需要至少一个分区来当作 root 文件系统,所以我们不能在没有分区的情况下安装 Linux 系统。当我们创建一个分区时,我们必须将它格式化为一个适合的文件系统,否则我们就没办法往里面储存文件了。
Linux 需要至少一个分区来当作文件系统,所以我们不能在没有分区的情况下安装 Linux 系统。当我们创建一个分区时,我们必须将它格式化为一个适合的文件系统,否则我们就没办法往里面储存文件了。
要在 Linux 中完成分区的相关工作我们需要一些工具。Linux 下有很多可用的相关工具,我们曾介绍过 **[Parted 命令][1]**。不过,今天我们的主角是 fdisk。
要在 Linux 中完成分区的相关工作我们需要一些工具。Linux 下有很多可用的相关工具,我们曾介绍过 [Parted 命令][1]。不过,今天我们的主角是 `fdisk`
人人都喜欢用 fdisk它是 Linux 下管理磁盘分区的最佳利器之一。它可以操作最大 `2TB` 的分区。大量 Linux 管理员都喜欢使用这个工具,因为当下 LVM 和 SAN 的原因,并没有多少人会用到 2TB 以上的分区。并且这个工具被世界上许多的基础设施所使用。如果你还是想创建比 2TB 更大的分区,请使用 **Parted 命令****cfdisk 命令**
人人都喜欢用 `fdisk`,它是 Linux 下管理磁盘分区的最佳利器之一。它可以操作最大 2TB 的分区。大量 Linux 管理员都喜欢使用这个工具,因为当下 LVM 和 SAN 的原因,并没有多少人会用到 2TB 以上的分区。并且这个工具被世界上许多的基础设施所使用。如果你还是想创建比 2TB 更大的分区,请使用 `parted` 命令 或 `cfdisk` 命令
对磁盘进行分区和创建文件系统是 Linux 管理员的日常。如果你在许多不同的环境中工作,你一定每天都会重复几次这项操作。
### Linux 内核是如何理解硬盘的?
作为人类,我们可以很轻松地理解一些事情;但是电脑就不是这样了,它们需要合适的命名交流才能理解事情
作为人类,我们可以很轻松地理解一些事情;但是电脑就不是这样了,它们需要合适的命名才能理解这些
在 Linux 中,外围设备都位于 `/dev` 挂载点,内核以下的方式理解硬盘:
在 Linux 中,外围设备都位于 `/dev` 挂载点,内核通过以下的方式理解硬盘:
* **`/dev/hdX[a-z]:`** IDE 硬盘被命名为 hdX
* **`/dev/sdX[a-z]:`** SCSI 硬盘被命名为 sdX
* **`/dev/xdX[a-z]:`** XT 硬盘被命名为 xdX
* **`/dev/vdX[a-z]:`** 虚拟硬盘被命名为 vdX
* **`/dev/fdN:`** 软盘被命名为 fdN
* **`/dev/scdN or /dev/srN:`** CD-ROM 被命名为 /dev/scdN 或 /dev/srN
* `/dev/hdX[a-z]:` IDE 硬盘被命名为 hdX
* `/dev/sdX[a-z]:` SCSI 硬盘被命名为 sdX
* `/dev/xdX[a-z]:` XT 硬盘被命名为 xdX
* `/dev/vdX[a-z]:` 虚拟硬盘被命名为 vdX
* `/dev/fdN:` 软盘被命名为 fdN
* `/dev/scdN or /dev/srN:` CD-ROM 被命名为 `/dev/scdN``/dev/srN`
### 什么是 fdisk 命令?
fdisk 的意思是 <ruby>固定磁盘<rt>Fixed Disk</rt></ruby><ruby>格式化磁盘<rt>Format Disk</rt></ruby>,它是命令行下允许用户对分区进行查看、创建、调整大小、删除、移动和复制的工具。它支持 MBR、Sun、SGI、BSD 分区表,但是它不支持 GUID 分区表GPT。它不是为操作大分区设计的。
`fdisk` 的意思是 <ruby>固定磁盘<rt>Fixed Disk</rt></ruby><ruby>格式化磁盘<rt>Format Disk</rt></ruby>,它是命令行下允许用户对分区进行查看、创建、调整大小、删除、移动和复制的工具。它支持 MBR、Sun、SGI、BSD 分区表,但是它不支持 GUID 分区表GPT。它不是为操作大分区设计的。
fdisk 允许我们在每块硬盘上创建最多四个主分区。它们中的其中一个可以作为扩展分区并下设多个逻辑分区。1-4 扇区作为主分区被保留,逻辑分区从扇区 5 开始。
`fdisk` 允许我们在每块硬盘上创建最多四个主分区。它们中的其中一个可以作为扩展分区并下设多个逻辑分区。1-4 扇区作为主分区被保留,逻辑分区从扇区 5 开始。
![磁盘分区结构图][3]
### 如何在 Linux 下安装 fdisk
fdisk 作为核心组件内置于 Linux 中,所以你不必手动安装它。
`fdisk` 作为核心组件内置于 Linux 中,所以你不必手动安装它。
### 如何用 fdisk 列出可用磁盘?
@ -52,36 +52,36 @@ fdisk 作为核心组件内置于 Linux 中,所以你不必手动安装它。
```shell
$ sudo fdisk -l
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xeab59449
Device Boot Start End Sectors Size Id Type
/dev/sda1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 20973568 62914559 41940992 20G 83 Linux
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 20973568 62914559 41940992 20G 83 Linux
Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdd: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sde: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
```
@ -93,19 +93,19 @@ I/O size (minimum/optimal): 512 bytes / 512 bytes
```shell
$ sudo fdisk -l /dev/sda
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xeab59449
Device Boot Start End Sectors Size Id Type
/dev/sda1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 20973568 62914559 41940992 20G 83 Linux
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 20973568 62914559 41940992 20G 83 Linux
```
### 如何列出 fdisk 所有的可用操作?
在 fdisk 中敲击 `m`,它便会列出所有可用操作:
`fdisk` 中敲击 `m`,它便会列出所有可用操作:
```shell
$ sudo fdisk /dev/sdc
@ -121,44 +121,44 @@ Command (m for help): m
Help:
DOS (MBR)
a toggle a bootable flag
b edit nested BSD disklabel
c toggle the dos compatibility flag
DOS (MBR)
a toggle a bootable flag
b edit nested BSD disklabel
c toggle the dos compatibility flag
Generic
d delete a partition
F list free unpartitioned space
l list known partition types
n add a new partition
p print the partition table
t change a partition type
v verify the partition table
i print information about a partition
Generic
d delete a partition
F list free unpartitioned space
l list known partition types
n add a new partition
p print the partition table
t change a partition type
v verify the partition table
i print information about a partition
Misc
m print this menu
u change display/entry units
x extra functionality (experts only)
Misc
m print this menu
u change display/entry units
x extra functionality (experts only)
Script
I load disk layout from sfdisk script file
O dump disk layout to sfdisk script file
Script
I load disk layout from sfdisk script file
O dump disk layout to sfdisk script file
Save & Exit
w write table to disk and exit
q quit without saving changes
Save & Exit
w write table to disk and exit
q quit without saving changes
Create a new label
g create a new empty GPT partition table
G create a new empty SGI (IRIX) partition table
o create a new empty DOS partition table
s create a new empty Sun partition table
Create a new label
g create a new empty GPT partition table
G create a new empty SGI (IRIX) partition table
o create a new empty DOS partition table
s create a new empty Sun partition table
```
### 如何使用 fdisk 列出分区类型?
在 fdisk 中敲击 `l`,它便会列出所有可用分区的类型:
`fdisk` 中敲击 `l`,它便会列出所有可用分区的类型:
```shell
$ sudo fdisk /dev/sdc
@ -172,37 +172,37 @@ Created a new DOS disklabel with disk identifier 0x9ffd00db.
Command (m for help): l
0 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
1 FAT12 27 Hidden NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
2 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
3 XENIX usr 3c PartitionMagic 84 OS/2 hidden or c6 DRDOS/sec (FAT-
4 FAT16 <32M 40 Venix 80286 85 Linux extended c7 Syrinx
5 Extended 41 PPC PReP Boot 86 NTFS volume set da Non-FS data
6 FAT16 42 SFS 87 NTFS volume set db CP/M / CTOS / .
7 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux plaintext de Dell Utility
8 AIX 4e QNX4.x 2nd part 8e Linux LVM df BootIt
9 AIX bootable 4f QNX4.x 3rd part 93 Amoeba e1 DOS access
a OS/2 Boot Manag 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad hi ea Rufus alignment
e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
f W95 Ext'd (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
11 Hidden FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC b
12 Compaq diagnost 5c Priam Edisk a9 NetBSD f1 SpeedStor
14 Hidden FAT16 <3 61 SpeedStor ab Darwin boot f4 SpeedStor
16 Hidden FAT16 63 GNU HURD or Sys af HFS / HFS+ f2 DOS secondary
17 Hidden HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
18 AST SmartSleep 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
1b Hidden W95 FAT3 70 DiskSecure Mult bb Boot Wizard hid fd Linux raid auto
1c Hidden W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
1e Hidden W95 FAT1 80 Old Minix be Solaris boot ff BBT
0 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
1 FAT12 27 Hidden NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
2 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
3 XENIX usr 3c PartitionMagic 84 OS/2 hidden or c6 DRDOS/sec (FAT-
4 FAT16 <32M 40 Venix 80286 85 Linux extended c7 Syrinx
5 Extended 41 PPC PReP Boot 86 NTFS volume set da Non-FS data
6 FAT16 42 SFS 87 NTFS volume set db CP/M / CTOS / .
7 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux plaintext de Dell Utility
8 AIX 4e QNX4.x 2nd part 8e Linux LVM df BootIt
9 AIX bootable 4f QNX4.x 3rd part 93 Amoeba e1 DOS access
a OS/2 Boot Manag 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad hi ea Rufus alignment
e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
f W95 Ext'd (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
11 Hidden FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC b
12 Compaq diagnost 5c Priam Edisk a9 NetBSD f1 SpeedStor
14 Hidden FAT16 <3 61 SpeedStor ab Darwin boot f4 SpeedStor
16 Hidden FAT16 63 GNU HURD or Sys af HFS / HFS+ f2 DOS secondary
17 Hidden HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
18 AST SmartSleep 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
1b Hidden W95 FAT3 70 DiskSecure Mult bb Boot Wizard hid fd Linux raid auto
1c Hidden W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
1e Hidden W95 FAT1 80 Old Minix be Solaris boot ff BBT
```
### 如何使用 fdisk 创建一个磁盘分区?
如果你希望新建磁盘分区,请参考下面的步骤。比如我希望在 `/dev/sdc` 中新建四个分区(三个主分区和一个扩展分区),只需要执行下文的命令。
首先,请在操作 “First sector” 的时候先按下 `Enter`,然后在 “Last sector” 中输入你希望创建分区的大小(可以在数字后面加 KB、MB、G 和 TB。例如你希望为这个分区扩容 1GB就应该在 “Last sector” 中输入 `+1G`。当你创建三个分区之后fdisk 默认会将分区类型设为扩展分区,如果你希望创建第四个主分区,请输入 `p` 来替代它的默认值 `e`
首先,请在操作 “First sector” 的时候先按下回车,然后在 “Last sector” 中输入你希望创建分区的大小(可以在数字后面加 KB、MB、G 和 TB。例如你希望为这个分区扩容 1GB就应该在 “Last sector” 中输入 `+1G`。当你创建三个分区之后,`fdisk` 默认会将分区类型设为扩展分区,如果你希望创建第四个主分区,请输入 `p` 来替代它的默认值 `e`
```shell
$ sudo fdisk /dev/sdc
@ -214,8 +214,8 @@ Be careful before using the write command.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): Enter
Using default response p.
@ -227,14 +227,14 @@ Created a new partition 1 of type 'Linux' and of size 1 GiB.
Command (m for help): p
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8cc8f9e5
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
Command (m for help): w
The partition table has been altered.
@ -256,8 +256,8 @@ Be careful before using the write command.
Command (m for help): n
Partition type
p primary (3 primary, 0 extended, 1 free)
e extended (container for logical partitions)
p primary (3 primary, 0 extended, 1 free)
e extended (container for logical partitions)
Select (default e): Enter
Using default response e.
@ -269,17 +269,17 @@ Created a new partition 4 of type 'Extended' and of size 7 GiB.
Command (m for help): p
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8cc8f9e5
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
Command (m for help): w
The partition table has been altered.
@ -303,11 +303,11 @@ Be careful before using the write command.
Command (m for help): F
Unpartitioned space /dev/sdc: 7 GiB, 7515144192 bytes, 14678016 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
Start End Sectors Size
6293504 20971519 14678016 7G
Start End Sectors Size
6293504 20971519 14678016 7G
Command (m for help): q
```
@ -333,18 +333,18 @@ Created a new partition 5 of type 'Linux' and of size 1 GiB.
Command (m for help): p
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8cc8f9e5
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc2 2099200 4196351 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
Command (m for help): w
The partition table has been altered.
@ -373,17 +373,17 @@ Partition 2 has been deleted.
Command (m for help): p
Disk /dev/sdc: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 512 = 512 bytes
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8cc8f9e5
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 2099199 2097152 1G 83 Linux
/dev/sdc3 4196352 6293503 2097152 1G 83 Linux
/dev/sdc4 6293504 20971519 14678016 7G 5 Extended
/dev/sdc5 6295552 8392703 2097152 1G 83 Linux
Command (m for help): w
The partition table has been altered.
@ -399,35 +399,33 @@ Syncing disks.
```shell
$ sudo mkfs.ext4 /dev/sdc1
or
$ sudo mkfs -t ext4 /dev/sdc1
or
$ sudo mke2fs /dev/sdc1
mke2fs 1.43.5 (04-Aug-2017)
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: c0a99b51-2b61-4f6a-b960-eb60915faab0
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
```
当你在分区上建立文件系统时,以下重要信息会同时被创建:
* **`Filesystem UUID:`** UUID 代表了通用且独一无二的识别符UUID 在 Linux 中通常用来识别设备。它 128 位长的数字代表了 32 个十六进制数。
* **`Superblock:`** Superblock 储存了文件系统的元数据。如果某个文件系统的 Superblock 被破坏,我们就无法挂载它了(也就是说无法访问其中的文件了)。
* **`Inode:`** Inode 是类 Unix 系统中文件系统的数据结构,它储存了所有除名称以外的文件信息和数据。
* **`Journal:`** 日志式文件系统包含了用来修复电脑意外关机产生下错误信息的日志Journal
* `Filesystem UUID:` UUID 代表了通用且独一无二的识别符UUID 在 Linux 中通常用来识别设备。它 128 位长的数字代表了 32 个十六进制数。
* `Superblock:` 超级块储存了文件系统的元数据。如果某个文件系统的超级块被破坏,我们就无法挂载它了(也就是说无法访问其中的文件了)。
* `Inode:` Inode 是类 Unix 系统中文件系统的数据结构,它储存了所有除名称以外的文件信息和数据。
* `Journal:` 日志式文件系统包含了用来修复电脑意外关机产生下错误信息的日志。
### 如何在 Linux 中挂载分区?
在你创建完分区和文件系统之后,我们需要挂载它们以便使用。我们需要创建一个挂载点来挂载分区,使用 mkdir 来创建一个挂载点。
在你创建完分区和文件系统之后,我们需要挂载它们以便使用。我们需要创建一个挂载点来挂载分区,使用 `mkdir` 来创建一个挂载点。
```shell
$ sudo mkdir -p /mnt/2g-new
@ -439,7 +437,7 @@ $ sudo mkdir -p /mnt/2g-new
$ sudo mount /dev/sdc1 /mnt/2g-new
```
如果你希望永久挂载某个分区,请将分区详情加入 fstab 文件。我们既可以输入设备名称,也可以输入 UUID。
如果你希望永久挂载某个分区,请将分区详情加入 `fstab` 文件。我们既可以输入设备名称,也可以输入 UUID。
使用设备名称来进行永久挂载:
@ -449,8 +447,7 @@ $ sudo mount /dev/sdc1 /mnt/2g-new
/dev/sdc1 /mnt/2g-new ext4 defaults 0 0
```
Permanent mount using UUID Value. To get a UUID of the partition use blkid command.
使用 UUID 来进行永久挂载(请使用 blkid 来获取 UUID
使用 UUID 来进行永久挂载(请使用 `blkid` 来获取 UUID
```
$ sudo blkid
@ -464,20 +461,20 @@ $ sudo blkid
UUID=d17e3c31-e2c9-4f11-809c-94a549bc43b7 /mnt/2g-new ext4 defaults 0 0
```
使用 df 命令亦可:
使用 `df` 命令亦可:
```
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 969M 0 969M 0% /dev
tmpfs 200M 7.0M 193M 4% /run
/dev/sda1 20G 16G 3.0G 85% /
tmpfs 997M 0 997M 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 997M 0 997M 0% /sys/fs/cgroup
tmpfs 200M 28K 200M 1% /run/user/121
tmpfs 200M 25M 176M 13% /run/user/1000
/dev/sdc1 1008M 1.3M 956M 1% /mnt/2g-new
Filesystem Size Used Avail Use% Mounted on
udev 969M 0 969M 0% /dev
tmpfs 200M 7.0M 193M 4% /run
/dev/sda1 20G 16G 3.0G 85% /
tmpfs 997M 0 997M 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 997M 0 997M 0% /sys/fs/cgroup
tmpfs 200M 28K 200M 1% /run/user/121
tmpfs 200M 25M 176M 13% /run/user/1000
/dev/sdc1 1008M 1.3M 956M 1% /mnt/2g-new
```
--------------------------------------------------------------------------------
@ -487,7 +484,7 @@ via: https://www.2daygeek.com/linux-fdisk-command-to-manage-disk-partitions/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[zhs852](https://github.com/zhs852)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,76 +0,0 @@
tomjlw is translating
Building Slack for the Linux community and adopting snaps
======
![][1]
Used by millions around the world, [Slack][2] is an enterprise software platform that allows teams and businesses of all sizes to communicate effectively. Slack works seamlessly with other software tools within a single integrated environment, providing an accessible archive of an organisations communications, information and projects. Although Slack has grown at a rapid rate in the 4 years since their inception, their desktop engineering team who work across Windows, MacOS and Linux consists of just 4 people currently. We spoke to Felix Rieseberg, Staff Software Engineer, who works on this team following the release of Slacks first [snap last month][3] to discover more about the companys attitude to the Linux community and why they decided to build a snap.
[Install Slack snap][4]
### Can you tell us about the Slack snap which has been published?
We launched our first snap last month as a new way to distribute to our Linux community. In the enterprise space, we find that people tend to adopt new technology at a slower pace than consumers, so we will continue to offer a .deb package.
### What level of interest do you see for Slack from the Linux community?
Im excited that interest for Slack is growing across all platforms, so it is hard for us to say whether the interest coming out of the Linux community is different from the one were generally seeing. However, it is important for us to meet users wherever they do their work. We have a dedicated QA engineer focusing entirely on Linux and we really do try hard to deliver the best possible experience.
We generally find it is a little harder to build for Linux, than say Windows, as there is a less predictable base to work from and this is an area where the Linux community truly shines. We have a fairly large number of users that are quite helpful when it comes to reporting bugs and hunting root causes down.
### How did you find out about snaps?
Martin Wimpress at Canonical reached out to me and explained the concept of snaps. Honestly, initially I was hesitant even though I use Ubuntu because it seemed like another standard to build and maintain. However, once understanding the benefits I was convinced it was a worthwhile investment.
### What was the appeal of snaps that made you decide to invest in them?
Without doubt, the biggest reason we decided to build the snap is the updating feature. We at Slack make heavy use of web technologies, which in turn allows us to offer a wide variety of features like the integration of YouTube videos or Spotify playlists. Much like a browser, that means that we frequently need to update the application.
On macOS and Windows, we already had a dedicated auto-updater that doesnt require the user to even think about updates. We have found that any sort of interruption, even for an update, is an annoyance that wed like to avoid. Therefore, the automatic updates via snaps seemed far more seamless and easy.
### How does building snaps compare to other forms of packaging you produce? How easy was it to integrate with your existing infrastructure and process?
As far as Linux is concerned, we have not tried other “new” packaging formats, but well never say never. Snaps were an easy choice given that the majority of our Linux customers do use Ubuntu. The fact that snaps also run on other distributions was a decent bonus. I think it is really neat how Canonical is making snaps cross-distro rather than focusing on just Ubuntu.
Building it was surprisingly easy: We have one unified build process that creates installers and packages and our snap creation simply takes the .deb package and churns out a snap. For other technologies, we sometimes had to build in-house tools to support our buildchain, but the `snapcraft` tool turned out to be just the right thing. The team at Canonical were incredibly helpful to push it through as we did experience a few problems along the way.
### How do you see the store changing the way users find and install your software?
What is really unique about Slack is that people dont just stumble upon it they know about it from elsewhere and actively try to find it. Therefore, our levels of awareness are already high but having the snap available in the store, I hope, will make installation a lot easier for our users.
We always try to do the best for our users. The more convinced we become that it is better than other installation options, the more we will recommend the snap to our users.
### What are your expectations or already seen savings by using snaps instead of having to package for other distros?
We expect the snap to offer more convenience for our users and ensure they enjoy using Slack more. From our side, the snap will save time on customer support as users wont be stuck on previous versions which will naturally resolve a lot of issues. Having the snap is an additional bonus for us and something to build on, rather than displacing anything we already have.
### What release channels (edge/beta/candidate/stable) in the store are you using or plan to use, if any?
We used the edge channel exclusively in the development to share with the team at Canonical. Slack for Linux as a whole is still in beta, but long-term, having the options for channels is interesting and being able to release versions to interested customers a little earlier will certainly be beneficial.
### How do you think packaging your software as a snap helps your users? Did you get any feedback from them?
Installation and updating generally being easier will be the big benefit to our users. Long-term, the question is “Will users that installed the snap experience less problems than other customers?” I have a decent amount of hope that the built-in dependencies in snaps make it likely.
### What advice or knowledge would you share with developers who are new to snaps?
I would recommend starting with the Debian package to build your snap that was shockingly easy. It also starts the scope smaller to avoid being overwhelmed. It is a fairly small time investment and probably worth it. Also if you can, try to find someone at Canonical to work with they have amazing engineers.
### Where do you see the biggest opportunity for development?
We are taking it step by step currently first get people on the snap, and build from there. People using it will already be more secure as they will benefit from the latest updates.
--------------------------------------------------------------------------------
via: https://insights.ubuntu.com/2018/02/06/building-slack-for-the-linux-community-and-adopting-snaps/
作者:[Sarah][a]
译者:[译者ID](https://github.com/tomjlw)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://insights.ubuntu.com/author/sarahfd/
[1]:https://insights.ubuntu.com/wp-content/uploads/a115/Slack_linux_screenshot@2x-2.png
[2]:https://slack.com/
[3]:https://insights.ubuntu.com/2018/01/18/canonical-brings-slack-to-the-snap-ecosystem/
[4]:https://snapcraft.io/slack/

View File

@ -1,84 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Hacking math education with Python)
[#]: via: (https://opensource.com/article/19/1/hacking-math)
[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
Hacking math education with Python
======
Teacher, programmer, and author Peter Farrell explains why teaching math with Python works better than the traditional approach.
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/getting_started_with_python.png?itok=MFEKm3gl)
Mathematics instruction has a bad reputation, especially with people (like me) who've had trouble with the traditional approach, which emphasizes rote memorization and theory that seems far removed from students' real world.
While teaching a student who was baffled by his math lessons, [Peter Farrell][1], a Python developer and mathematics teacher, decided to try using Python to teach the boy the math concepts he was having trouble learning.
Peter was inspired by the work of [Seymour Papert][2], the father of the Logo programming language, which lives on in Python's [Turtle module][3]. The Turtle metaphor hooked Peter on Python and using it to teach math, much like [I was drawn to Python][4].
Peter shares his approach in his new book, [Math Adventures with Python][5]: An Illustrated Guide to Exploring Math with Code. And, I recently interviewed him to learn more about it.
**Don Watkins:** What is your background?
**Peter Farrell:** I was a math teacher for eight years, and I tutored math for 10 years after that. When I was a teacher, I read Papert's [Mindstorms][6] and was inspired to introduce all my math classes to Logo and Turtles.
**DW:** Why did you start using Python?
**PF:** I was working with a homeschooled boy on a very dry, textbook-driven math curriculum, which at the time seemed like a curse to me. But I found ways to sneak in the Logo Turtles, and he was a programming fan, so he liked that. Once we got into functions and real programming, he asked if we could continue in Python. I didn't know any Python but it didn't seem that different from Logo, so I agreed. And I never looked back!
I was also looking for a 3D graphics package I could use to model a solar system and lead students through making planets move and get pulled by the force of attraction between the bodies, according to Newton's formula. Many graphics packages required programming in C or something hard, but I found an excellent package called Visual Python that was very easy to use. I used [VPython][7] for years after that.
So, I was introduced to Python in the context of working with a student on math. For some time after that, he was my programming tutor while I was his math tutor!
**DW:** What got you interested in math?
**PF:** I learned it the old-fashioned way: by hand, on paper and blackboards. I was good at manipulating symbols, so algebra was never a problem, and I liked drawing and graphing, so geometry and trig could be fun, too. I did some programming in BASIC and Fortran in college, but it never inspired me. Later on, programming inspired me greatly! I'm still tickled by the way programming makes easy work of the laborious stuff you have to do in math class, freeing you up to do the more fun of exploring, graphing, tweaking, and discovering.
**DW:** What inspired you to consider your Python approach to math?
**PF:** When I was teaching the homeschooled student, I was amazed at what we could do by writing a simple function and then calling it a bunch of times with different values using a loop. That would take a half an hour by hand, but the computer spit it out instantly! Then we could look for patterns (which is what a math student should be doing), express the pattern as a function, and extend it further.
**DW:** How does your approach to teaching help students—especially those who struggle with math? How does it make math more relevant?
**PF:** Students, especially high-schoolers, question the need to be doing all this calculating, graphing, and solving by hand in the 21st century, and I don't disagree with them. Learning to use Excel, for example, to crunch numbers should be seen as a basic necessity to work in an office. Learning to code, in any language, is becoming a very valuable skill to companies. So, there's a real-world appeal to me.
But the idea of making art with code can revolutionize math class. Just putting a shape on a screen requires math—the position (x-y coordinates), the dimensions, and even the color are all numbers. If you want something to move or change, you'll need to use variables, and not the "guess what x equals" kind of variable. You'll vary the position using a variable or, more efficiently, using a vector. [This makes] math topics like vectors and matrices seen as helpful tools you can use, rather than required information you'll never use.
Students who struggle with math might just be turned off to "school math," which is heavy on memorization and following rules and light on creativity and real applications. They might find they're actually good at math, just not the way it was taught in school. I've had parents see the cool graphics their kids have created with code and say, "I never knew that's what sines and cosines were used for!"
**DW:** How do you see your approach to math and programming encouraging STEM in schools?
**PF:** I love the idea of combining previously separated topics into an idea like STEM or STEAM! Unfortunately for us math folks, the "M" is very often neglected. I see lots of fun projects being done in STEM labs, even by very young children, and they're obviously getting an education in technology, engineering, and science. But I see precious little math material in the projects. STEM/[mechatronics][8] teacher extraordinaire Ken Hawthorn and I are creating projects to try to remedy that.
Hopefully, my book helps encourage students, girls and boys, to get creative with technology, real and virtual. There are a lot of beautiful graphics in the book, which I hope will inspire people to go through the coding adventure and make them. All the software I use ([Python Processing][9]) is available for free and can be easily installed, or is already installed, on the Raspberry Pi. Entry into the STEM world should not be cost-prohibitive to schools or individuals.
**DW:** What would you like to share with other math teachers?
**PF:** If the math establishment is really serious about teaching students the standards they have agreed upon, like numerical reasoning, logic, analysis, modeling, geometry, interpreting data, and so on, they're going to have to admit that coding can help with every single one of those goals. My approach was born, as I said before, from just trying to enrich a dry, traditional approach, and I think any teacher can do that. They just need somebody who can show them how to do everything they're already doing, just using code to automate the laborious stuff.
My graphics-heavy approach is made possible by the availability of free graphics software. Folks might need to be shown where to find these packages and how to get started. But a math teacher can soon be leading students through solving problems using 21st-century technology and visualizing progress or results and finding more patterns to pursue.
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/hacking-math
作者:[Don Watkins][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/don-watkins
[b]: https://github.com/lujun9972
[1]: https://twitter.com/hackingmath
[2]: https://en.wikipedia.org/wiki/Seymour_Papert
[3]: https://en.wikipedia.org/wiki/Turtle_graphics
[4]: https://opensource.com/life/15/8/python-turtle-graphics
[5]: https://nostarch.com/mathadventures
[6]: https://en.wikipedia.org/wiki/Mindstorms_(book)
[7]: http://vpython.org/
[8]: https://en.wikipedia.org/wiki/Mechatronics
[9]: https://processing.org/

View File

@ -1,383 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 3 OK03)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
Computer Laboratory Raspberry Pi: Lesson 3 OK03
======
The OK03 lesson builds on OK02 by teaching how to use functions in assembly to make more reusable and rereadable code. It is assumed you have the code for the [Lesson 2: OK02][1] operating system as a basis.
### 1 Reusable Code
So far we've made code for our operating system by typing the things we want to happen in order. This is fine for such tiny programs, but if we wrote the whole system like this, the code would be completely unreadable. Instead we use functions.
```
A function is a piece of code that can be reused to compute a certain kind of answer, or perform a certain action. You may also hear them called procedures, routines or subroutines. Although these are all different, people rarely use the correct term.
You should already be happy with the concept of a function from mathematics. For example the cosine function applied to a number gives another number between -1 and 1 which is the cosine of the angle. Notationally we write cos(x) to be the cosine function applied to the value x.
In code, functions can take multiple inputs (including none), give multiple outputs (including none), and may cause side effects. For example a function might create a file on the file system, named after the first input, with length based on the second.
```
![Function as black boxes][2]
```
Functions are said to be 'black boxes'. We put inputs in, and outputs come out, but we don't need to know how they work.
```
In higher level code such as C or C++, functions are part of the language itself. In assembly code, functions are just ideas we have.
Ideally we want to be able to set our registers to some input values, branch to an address, and expect that at some point the code will branch back to our code having set the registers to output values. This is what a function is in assembly code. The difficulty comes in what system we use for setting the registers. If we just used any system we felt like, each programmer may use a different system, and would find other programmers' work hard to understand. Further, compilers would not be able to work with assembly code as easily, as they would not know how to use the functions. To prevent confusion, a standard called the Application Binary Interface (ABI) was devised for each assembly language which is an agreement on how functions should be run. If everyone makes functions in the same way, then everyone will be able to use each others' functions. I will teach that standard here, and from now on I will code all of my functions to meet the standard.
The standard says that r0,r1,r2 and r3 will be used as inputs to a function in order. If a function needs no inputs, then it doesn't matter what value it takes. If it needs only one it always goes in r0, if it needs two, the first goes in r0, and the second goes on r1, and so on. The output will always be in r0. If a function has no output, it doesn't matter what value r0 takes.
Further, it also requires that after a function is run, r4 to r12 must have the same values as they had when the function started. This means that when you call a function, you can be sure the r4 to r12 will not change value, but you cannot be so sure about r0 to r3.
When a function completes it has to branch back to the code that started it. This means it must know the address of the code that started it. To facilitate this, there is a special register called lr (link register) which always holds the address of the instruction after the one that called this function.
Table 1.1 ARM ABI register usage
| Register | Brief | Preserved | Rules |
| -------- | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| r0 | Argument and result | No | r0 and r1 are used for passing the first two arguments to functions, and returning the results of functions. If a function does not use them for a return value, they can take any value after a function. |
| r1 | Argument and result | No | |
| r2 | Argument | No | r2 and r3 are used for passing the second two arguments to functions. There values after a function is called can be anything. |
| r3 | Argument | No | |
| r4 | General purpose | Yes | r4 to r12 are used for working values, and their value after a function is called must be the same as before. |
| r5 | General purpose | Yes | |
| r6 | General purpose | Yes | |
| r7 | General purpose | Yes | |
| r8 | General purpose | Yes | |
| r9 | General purpose | Yes | |
| r10 | General purpose | Yes | |
| r11 | General purpose | Yes | |
| r12 | General purpose | Yes | |
| lr | Return address | No | lr is the address to branch back to when a function is finished, but this does have to contain the same address after the function has finished. |
| sp | Stack pointer | Yes | sp is the stack pointer, described below. Its value must be the same after the function has finished. |
Often functions need to use more registers than just r0 to r3. But, since r4 to r12 must stay the same after the method has run, they must be saved somewhere. We save them on something called the stack.
![Stack diagram][3]
```
A stack is a metaphor we use in computing for a method of storing values. Just like in a stack of plates, you can only remove items from the top of a stack, and only add items to the top of the stack.
The stack is a brilliant idea for storing registers on when functions are running. For example if I have a function which needs to use registers r4 and r5, it could place the current values of those registers on a stack. At the end of the method it could take them back off again. What is most clever is that if my function had to run another function in order to complete and that function needed to save some registers, it could put those on the top of the stack while it ran, and then take them off again at the end. That wouldn't affect the values of r4 and r5 that my method had to save, as they would be added to the top of the stack, and then taken off again.
The terminology we used to refer to the values put on the stack by a particular method is that methods 'stack frame'. Not every method needs a stack frame, some don't need to store values.
```
Because the stack is so useful, it has been implemented in the ARMv6 instruction set directly. A special register called sp (stack pointer) holds the address of the stack. When items are added to the stack, the sp register updates so that it always holds the address of the first item on the stack. push {r4,r5} would put the values in r4 and r5 onto the top of the stack and pop {r4,r5} would take them back off again (in the correct order).
### 2 Our First Function
Now that we have some idea about how functions work, let's try to make one. For a basic first example, we are going to make a function that takes no input, and gives an output of the GPIO address. In the last lesson, we just wrote in this value, but it would be better as a function, since it is something we might need to do often in a real operating system, and we might not always remember the address.
Copy the following code into a new file called 'gpio.s'. Just make the new file in the 'source' directory with 'main.s'. We're going to put all functions related to the GPIO controller in one file to make them easier to find.
```
.globl GetGpioAddress
GetGpioAddress:
ldr r0,=0x20200000
mov pc,lr
```
```
.globl lbl makes the label lbl accessible from other files.
mov reg1,reg2 copies the value in reg2 into reg1.
```
This is a very simple complete function. The .globl GetGpioAddress command is a message to the assembler to make the label GetGpioAddress accessible to all files. This means that in our main.s file we can branch to the label GetGpioAddress even though it is not defined in that file.
You should recognise the ldr r0,=0x20200000 command, which stores the GPIO controller address in r0. Since this is a function, we have to give the output in r0, so we are not as free to use any register as we once were.
mov pc,lr copies the value in lr to pc. As mentioned earlier lr always contains the address of the code that we have to go back to when a method finishes. pc is a special register which always contains the address of the next instruction to be run. A normal branch command just changes the value of this register. By copying the value in lr to pc we just change the next line to be run to be the one we were told to go back to.
A reasonable question would now be, how would we actually run this code? A special type of branch bl does what we need. It branches to a label like a normal branch, but before it does it updates lr to contain the address of the line after the branch. That means that when the function finishes, the line it will go back to will be the one after the bl command. This makes a function running just look like any other command, it simply runs, does whatever it needs to do, and then carries on to the next line. This is a really useful way of thinking about functions. We treat them as 'black boxes' in that when we use them, we don't need to think about how they work, we just need to know what inputs they need, and what outputs they give.
For now, don't worry about using the function, we will use it in the next section.
### 3 A Big Function
Now we're going to implement a bigger function. Our first job was to enable output on GPIO pin 16. It would be nice if this was a function. We could simply specify a pin and a function as the input, and the function would set the function of that pin to that value. That way, we could use the code to control any GPIO pin, not just the LED.
Copy the following commands below the GetGpioAddress function in gpio.s.
```
.globl SetGpioFunction
SetGpioFunction:
cmp r0,#53
cmpls r1,#7
movhi pc,lr
```
```
Suffix ls causes the command to be executed only if the last comparison determined that the first number was less than or the same as the second. Unsigned.
Suffix hi causes the command to be executed only if the last comparison determined that the first number was higher than the second. Unsigned.
```
One of the first things we should always think about when writing functions is our inputs. What do we do if they are wrong? In this function, we have one input which is a GPIO pin number, and so must be a number between 0 and 53, since there are 54 pins. Each pin has 8 functions, numbered 0 to 7 and so the function code must be too. We could just assume that the inputs will be correct, but this is very dangerous when working with hardware, as incorrect values could cause very bad side effects. Therefore, in this case, we wish to make sure the inputs are in the right ranges.
To do this we need to check that r0 <= 53 and r1 <= 7. First of all, we can use the comparison we've seen before to compare the value of r0 with 53. The next instruction, cmpls is a normal comparison instruction that will only be run if r0 was lower than or the same as 53. If that was the case, it compares r1 with 7, otherwise the result of the comparison is the same as before. Finally we go back to the code that ran the function if the result of the last comparison was that the register was higher than the number.
The effect of this is exactly what we want. If r0 was bigger than 53, then the cmpls command doesn't run, but the movhi does. If r0 is <= 53, then the cmpls command does run, and so r1 is compared with 7, and then if it is higher than 7, movhi is run, and the function ends, otherwise movhi does not run, and we know for sure that r0 <= 53 and r1 <= 7.
There is a subtle difference between the ls (lower or same) and le (less or equal) as well as between hi (higher) and gt (greater) suffixes, but I will cover this later.
Copy these commands below the above.
```
push {lr}
mov r2,r0
bl GetGpioAddress
```
```
push {reg1,reg2,...} copies the registers in the list reg1,reg2,... onto the top of the stack. Only general purpose registers and lr can be pushed.
bl lbl sets lr to the address of the next instruction and then branches to the label lbl.
```
These next three commands are focused on calling our first method. The push {lr} command copies the value in lr onto the top of the stack, so that we can retrieve it later. We must do this because when we call GetGpioAddress, we will need to use lr to store the address to come back to in our function.
If we did not know anything about the GetGpioAddress function, we would have to assume it changes r0,r1,r2 and r3, and would have to move our values to r4 and r5 to keep them the same after it finishes. Fortunately, we do know about GetGpioAddress, and we know it only changes r0 to the address, it doesn't affect r1,r2 or r3. Thus, we only have to move the GPIO pin number out of r0 so it doesn't get overwritten, but we know we can safely move it to r2, as GetGpioAddress doesn't change r2.
Finally we use the bl instruction to run GetGpioAddress. Normally we use the term 'call' for running a function, and I will from now. As discussed earlier bl calls a function by updating the lr to the next instruction's address, and then branching to the function.
When a function ends we say it has 'returned'. When the call to GetGpioAddress returns, we now know that r0 contains the GPIO address, r1 contains the function code and r2 contains the GPIO pin number. I mentioned earlier that the GPIO functions are stored in blocks of 10, so first we need to determine which block of ten our pin number is in. This sounds like a job we would use a division for, but divisions are very slow indeed, so it is better for such small numbers to do repeated subtraction.
Copy the following code below the above.
```
functionLoop$:
cmp r2,#9
subhi r2,#10
addhi r0,#4
bhi functionLoop$
```
```
add reg,#val adds the number val to the contents of the register reg.
```
This simple loop code compares the pin number to 9. If it is higher than 9, it subtracts 10 from the pin number, and adds 4 to the GPIO Controller address then runs the check again.
The effect of this is that r2 will now contain a number from 0 to 9 which represents the remainder of dividing the pin number by 10. r0 will now contain the address in the GPIO controller of this pin's function settings. This would be the same as GPIO Controller Address + 4 × (GPIO Pin Number ÷ 10).
Finally, copy the following code below the above.
```
add r2, r2,lsl #1
lsl r1,r2
str r1,[r0]
pop {pc}
```
```
Argument shift reg,lsl #val shifts the binary representation of the number in reg left by val before using it in the operation before.
lsl reg,amt shifts the binary representation of the number in reg left by the number in amt.
str reg,[dst] is the same as str reg,[dst,#0].
pop {reg1,reg2,...} copies the values from the top of the stack into the register list reg1,reg2,.... Only general purpose registers and pc can be popped.
```
This code finishes off the method. The first line is actually a multiplication by 3 in disguise. Multiplication is a big and slow instruction in assembly code, as the circuit can take a long time to come up with the answer. It is much faster sometimes to use some instructions which can get the answer quicker. In this case, I know that r2 × 3 is the same as r2 × 2 + r2. It is very easy to multiply a register by 2 as this is conveniently the same as shifting the binary representation of the number left by one place.
One of the very useful features of the ARMv6 assembly code language is the ability to shift an argument before using it. In this case, I add r2 to the result of shifting the binary representation of r2 to the left by one place. In assembly code, you often use tricks such as this to compute answers more easily, but if you're uncomfortable with this, you could also write something like mov r3,r2; add r2,r3; add r2,r3.
Now we shift the function value left by a number of places equal to r2. Most instructions such as add and sub have a variant which uses a register rather than a number for the amount. We perform this shift because we want to set the bits that correspond to our pin number, and there are three bits per pin.
We then store the the computed function value at the address in the GPIO controller. We already worked out the address in the loop, so we don't need to store it at an offset like we did in OK01 and OK02.
Finally, we can return from this method call. Since we pushed lr onto the stack, if we pop pc, it will copy the value that was in lr at the time we pushed it into pc. This would be the same as having used mov pc,lr and so the function call will return when this line is run.
The very keen may notice that this function doesn't actually work correctly. Although it sets the function of the GPIO pin to the requested value, it causes all the pins in the same block of 10's functions to go back to 0! This would likely be quite annoying in a system which made heavy use of the GPIO pins. I leave it as a challenge to the interested to fix this function so that it does not overwrite other pins values by ensuring that all bits other than the 3 that must be set remain the same. A solution to this can be found on the downloads page for this lesson. Functions that you may find useful are and which computes the Boolean and function of two registers, mvns which computes the Boolean not and orr which computes the Boolean or.
### 4 Another Function
So, we now have a function which takes care of the GPIO pin function setting. We now need to make a function to turn a GPIO pin on or off. Rather than having one function for off and one function for on, it would be handy to have a single function which does either.
We will make a function called SetGpio which takes a GPIO pin number as its first input in r0, and a value as its second in r1. If the value is 0 we will turn the pin off, and if it is not zero we will turn it on.
Copy and paste the following code at the end of 'gpio.s'.
```
.globl SetGpio
SetGpio:
pinNum .req r0
pinVal .req r1
```
```
alias .req reg sets alias to mean the register reg.
```
Once again we need the .globl command and the label to make the function accessible from other files. This time we're going to use register aliases. Register aliases allow us to use a name other than just r0 or r1 for registers. This may not be so important now, but it will prove invaluable when writing big methods later, and you should try to use aliases from now on. pinNum .req r0 means that pinNum now means r0 when used in instructions.
Copy and paste the following code after the above.
```
cmp pinNum,#53
movhi pc,lr
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
```
```
.unreq alias removes the alias alias.
```
Like in SetGpioFunction the first thing we must do is check that we were actually given a valid pin number. We do this in exactly the same way by comparing pinNum (r0) with 53, and returning immediately if it is higher. Once again we wish to call GetGpioAddress, so we have to preserve lr by pushing it onto the stack, and to move pinNum to r2. We then use the .unreq statement to remove our alias from r0. Since the pin number is now stored in r2 we want our alias to reflect this, so we remove the alias from r0 and remake it on r2. You should always .unreq every alias as soon as it is done with, so that you cannot make the mistake of using it further down the code when it no longer exists.
We then call GetGpioAddress, and we create an alias for r0 to reflect this.
Copy and paste the following code after the above.
```
pinBank .req r3
lsr pinBank,pinNum,#5
lsl pinBank,#2
add gpioAddr,pinBank
.unreq pinBank
```
```
lsr dst,src,#val shifts the binary representation of the number in src right by val, but stores the result in dst.
```
The GPIO controller has two sets of 4 bytes each for turning pins on and off. The first set in each case controls the first 32 pins, and the second set controls the remaining 22. In order to determine which set it is in, we need to divide the pin number by 32. Fortunately this is very easy, at is the same as shifting the binary representation of the pin number right by 5 places. Hence, in this case I've named r3 as pinBank and then computed pinNum ÷ 32. Since it is a set of 4 bytes, we then need to multiply the result of this by 4. This is the same as shifting the binary representation left by 2 places, which is the command that follows. You may wonder if we could just shift it right by 3 places, as we went right then left. This won't work however, as some of the answer may have been rounded away when we did ÷ 32 which may not be if we just ÷ 8.
The result of this is that gpioAddr now contains either 2020000016 if the pin number is 0-31, and 2020000416 if the pin number is 32-53. This means if we add 2810 we get the address for turning the pin on, and if we add 4010 we get the address for turning the pin off. Since we are done with pinBank, I use .unreq immediately afterwards.
Copy and paste the following code after the above.
```
and pinNum,#31
setBit .req r3
mov setBit,#1
lsl setBit,pinNum
.unreq pinNum
```
```
and reg,#val computes the Boolean and function of the number in reg with val.
```
This next part of the function is for generating a number with the correct bit set. For the GPIO controller to turn a pin on or off, we give it a number with a bit set in the place of the remainder of that pin's number divided by 32. For example, to set pin 16, we need a number with the 16th bit a 1. To set pin 45 we would need a number with the 13th bit 1 as 45 ÷ 32 = 1 remainder 13.
The and command computes the remainder we need. How it does this is that the result of an and operation is a number with 1s in all binary digits which had 1s in both of the inputs, and 0s elsewhere. This is a fundamental binary operation, and is very quick. We have given it inputs of pinNum and 3110 = 111112. This means that the answer can only have 1 bits in the last 5 places, and so is definitely between 0 and 31. Specifically it only has 1s where there were 1s in pinNum's last 5 places. This is the same as the remainder of a division by 32. It is no coincidence that 31 = 32 - 1.
![binary division example][4]
The rest of this code simply uses this value to shift the number 1 left. This has the effect of creating the binary number we need.
Copy and paste the following code after the above.
```
teq pinVal,#0
.unreq pinVal
streq setBit,[gpioAddr,#40]
strne setBit,[gpioAddr,#28]
.unreq setBit
.unreq gpioAddr
pop {pc}
```
```
teq reg,#val checks if the number in reg is equal to val.
```
This code ends the method. As stated before, we turn the pin off if pinVal is zero, and on otherwise. teq (test equal) is another comparison operation that can only be used to test for equality. It is similar to cmp but it does not work out which number is bigger. If all you wish to do is test if to numbers are the same, you can use teq.
If pinVal is zero, we store the setBit at 40 away from the GPIO address, which we already know turns the pin off. Otherwise we store it at 28, which turns the pin on. Finally, we return by popping the pc, which sets it to the value that we stored when we pushed the link register.
### 5 A New Beginning
Finally, after all that work we have our GPIO functions. We now need to alter 'main.s' to use them. Since 'main.s' is now getting a lot bigger and more complicated, it is better design to split it into two sections. The '.init' we've been using so far is best kept as small as possible. We can change the code to reflect this easily.
Insert the following just after _start: in main.s:
```
b main
.section .text
main:
mov sp,#0x8000
```
The key change we have made here is to introduce the .text section. I have designed the makefile and linker scripts such that code in the .text section (which is the default section) is placed after the .init section which is placed at address 800016. This is the default load address and gives us some space to store the stack. As the stack exists in memory, it has to have an address. The stack grows down memory, so that each new value is at a lower address, thus making the 'top' of the stack, the lowest address.
```
The 'ATAGs' section in the diagram is a place where information about the Raspberry Pi is stored such as how much memory it has, and what its default screen resolution is.
```
![Layout diagram of operating system][5]
Replace all the code that set the function of the GPIO pin with the following:
```
pinNum .req r0
pinFunc .req r1
mov pinNum,#16
mov pinFunc,#1
bl SetGpioFunction
.unreq pinNum
.unreq pinFunc
```
This code calls SetGpioFunction with the pin number 16 and the pin function code 1. This has the effect of enabling output to the OK LED.
Replace any code which turns the OK LED on with the following:
```
pinNum .req r0
pinVal .req r1
mov pinNum,#16
mov pinVal,#0
bl SetGpio
.unreq pinNum
.unreq pinVal
```
This code uses SetGpio to turn off GPIO pin 16, thus turning on the OK LED. If we instead used mov pinVal,#1, it would turn the LED off. Replace your old code to turn the LED off with that.
### 6 Onwards
Hopefully now, you should be able to test what you have made on the Raspberry Pi. We've done a large amount of code this time, so there is a lot that can go wrong. If it does, head to the troubleshooting page.
When you get it working, congratulations. Although our operating system does nothing more than it did in [Lesson 2: OK02][1], we've learned a lot about functions and formatting, and we can now code new features much more quickly. It would be very simple now to make an Operating System that alters any GPIO register, which could be used to control hardware!
In [Lesson 4: OK04][6], we will address our wait function, which is currently imprecise, so that we can gain better control over our LED, and ultimately over all of the GPIO pins.
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.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/ok02.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/functions.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/stack.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/osLayout.png
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html

View File

@ -1,161 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 4 OK04)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
Computer Laboratory Raspberry Pi: Lesson 4 OK04
======
The OK04 lesson builds on OK03 by teaching how to use the timer to flash the 'OK' or 'ACT' LED at precise intervals. It is assumed you have the code for the [Lesson 3: OK03][1] operating system as a basis.
### 1 A New Device
The timer is the only way the Pi can keep time. Most computers have a battery powered clock to keep time when off.
So far, we've only looked at one piece of hardware on the Raspberry Pi, namely the GPIO Controller. I've simply told you what to do, and it happened. Now we're going to look at the timer, and I'm going to lead you through understanding how it works.
Just like the GPIO Controller, the timer has an address. In this case, the timer is based at 2000300016. Reading the manual, we find the following table:
Table 1.1 GPIO Controller Registers
| Address | Size / Bytes | Name | Description | Read or Write |
| -------- | ------------ | ---------------- | ---------------------------------------------------------- | ---------------- |
| 20003000 | 4 | Control / Status | Register used to control and clear timer channel comparator matches. | RW |
| 20003004 | 8 | Counter | A counter that increments at 1MHz. | R |
| 2000300C | 4 | Compare 0 | 0th Comparison register. | RW |
| 20003010 | 4 | Compare 1 | 1st Comparison register. | RW |
| 20003014 | 4 | Compare 2 | 2nd Comparison register. | RW |
| 20003018 | 4 | Compare 3 | 3rd Comparison register. | RW |
![Flowchart of the system timer's operation][2]
This table tells us a lot, but the descriptions in the manual of the various fields tell us the most. The manual explains that the timer fundamentally just increments the value in Counter by 1 every 1 micro second. Each time it does so, it compares the lowest 32 bits (4 bytes) of the counter's value with the 4 comparison registers, and if it matches any of them, it updates Control / Status to reflect which ones matched.
For more information about bits, bytes, bit fields, and data sizes expand the box below.
```
A bit is a name for a single binary digit. As you may recall, a single binary digit is either a 1 or a 0.
A byte is the name we give for a collection of 8 bits. Since each bit can be one of two values, there are 28 = 256 different possible values for a byte. We normally interpret a byte as a binary number between 0 and 255 inclusive.
![Diagram of GPIO function select controller register 0.][3]
A bit field is another way of interpreting binary. Rather than interpreting it as a number, binary can be interpreted as many different things. A bit field treats binary as a series of switches which are either on (1) or off (0). If we have a meaning for each of these little switches, we can use them to control things. We have actually already met bitfields with the GPIO controller, with the setting a pin on or off. The bit that was a 1 was the GPIO pin to actually turn on or off. Sometimes we need more options than just on or off, so we group several of the switches together, such as with the GPIO controller function settings (pictured), in which every group of 3 bits controls one GPIO pin function.
```
Our goal is to implement a function that we can call with an amount of time as an input that will wait for that amount of time and then return. Think for a moment about how we could do this, given what we have.
I see there being two options:
1. Read a value from the counter, and then keep branching back into the same code until the counter is the amount of time to wait more than it was.
2. Read a value from the counter, add the amount of time to wait, store this in one of the comparison registers and then keep branching back into the same code until the Control / Status register updates.
```
Issues like these are called concurrency problems, and can be almost impossible to fix.
```
Both of these strategies would work fine, but in this tutorial we will only implement the first. The reason is because the comparison registers are more likely to go wrong, as during the time it takes to add the wait time and store it in the comparison register, the counter may have increased, and so it would not match. This could lead to very long unintentional delays if a 1 micro second wait is requested (or worse, a 0 microsecond wait).
### 2 Implementation
```
Large Operating Systems normally use the Wait function as an opportunity to perform background tasks.
```
I will largely leave the challenge of creating the ideal wait method to you. I suggest you put all code related to the timer in a file called 'systemTimer.s' (for hopefully obvious reasons). The complicated part about this method, is that the counter is an 8 byte value, but each register only holds 4 bytes. Thus, the counter value will span two registers.
The following code blocks are examples.
```
ldrd r0,r1,[r2,#4]
```
```
ldrd regLow,regHigh,[src,#val] loads 8 bytes from the address given by the number in src plus val into regLow and regHigh .
```
An instruction you may find useful is the ldrd instruction above. It loads 8 bytes of memory across 2 registers. In this case, the 8 bytes of memory starting at the address in r2 would be copied into r0 and r1. What is slightly complicated about this arrangement is that r1 actually holds the highest 4 bytes. In other words, if the counter had a value of 999,999,999,99910 = 11101000110101001010010100001111111111112, r1 would contain 111010002 and r0 would contain 110101001010010100001111111111112.
The most sensible way to implement this would be to compute the difference between the current counter value and the one from when the method started, and then to compare this with the requested amount of time to wait. Conveniently, unless you wish to support wait times that were 8 bytes, the value in r1 in the example above could be discarded, and only the low 4 bytes of the counter need be used.
When waiting you should always be sure to use higher comparisons not equality comparisons, as if you try to wait for the gap between the time the method started and the time it ends to be exactly the amount requested, you could miss the value, and wait forever.
If you cannot figure out how to code the wait function, expand the box below for a guide.
```
Borrowing the idea from the GPIO controller, the first function we should write should be to get the address of this system timer. An example of this is shown below:
.globl GetSystemTimerBase
GetSystemTimerBase:
ldr r0,=0x20003000
mov pc,lr
Another function that will prove useful would be one that returns the current counter value in registers r0 and r1:
.globl GetTimeStamp
GetTimeStamp:
push {lr}
bl GetSystemTimerBase
ldrd r0,r1,[r0,#4]
pop {pc}
This function simply uses the GetSystemTimerBase function and loads in the counter value using ldrd like we have just learned.
Now we actually want to code our wait method. First of all, we need to know the counter value when the method started, which we can now get using GetTimeStamp.
delay .req r2
mov delay,r0
push {lr}
bl GetTimeStamp
start .req r3
mov start,r0
This code copies our method's input, the amount of time to delay, into r2, and then calls GetTimeStamp, which we know will return the current counter value in r0 and r1. It then copies the lower 4 bytes of the counter's value to r3.
Next we need to compute the difference between the current counter value and the reading we just took, and then keep doing so until the gap between them is at least the size of delay.
loop$:
bl GetTimeStamp
elapsed .req r1
sub elapsed,r0,start
cmp elapsed,delay
.unreq elapsed
bls loop$
This code will wait until the requested amount of time has passed. It takes a reading from the counter, subtracts the initial value from this reading and then compares that to the requested delay. If the amount of time that has elapsed is less than the requested delay, it branches back to loop$.
.unreq delay
.unreq start
pop {pc}
This code finishes off the function by returning.
```
### 3 Another Blinking Light
Once you have what you believe to be a working wait function, change 'main.s' to use it. Alter everywhere you wait to set the value of r0 to some big number (remember it is in microseconds) and then test it on the Raspberry Pi. If it does not function correctly please see our troubleshooting page.
Once it is working, congratulations you have now mastered another device, and with it, time itself. In the next and final lesson in the OK series, [Lesson 5: OK05][4] we shall use all we have learned to flash out a pattern on the LED.
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.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/ok03.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/systemTimer.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioControllerFunctionSelect.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (oska874)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
@ -7,88 +7,83 @@
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
Computer Laboratory Raspberry Pi: Lesson 5 OK05
translating by ezio
树莓派计算机实验室 课程 5 OK05
======
The OK05 lesson builds on OK04 using it to flash the SOS Morse Code pattern (...---...). It is assumed you have the code for the [Lesson 4: OK04][1] operating system as a basis.
OK05 课程构建于课程 OK04 的基础,使用更多代码方式烧、保存写莫尔斯码的 SOS 序列(`...---...`)。这里假设你已经有了 [课程 4: OK04][1] 操作系统的代码基础。
### 1 Data
### 1 数据
So far, all we've had to do with our operating system is provide instructions to be followed. Sometimes however, instructions are only half the story. Our operating systems may need data.
到目前为止,我们与操作系统有关的所有内容都提供了遵循的说明。然而有时候,说明只是一半。我们的操作系统可能需要数据
> 一些早期的操作系统确实只允许特定文件中的特定类型的数据,但是这通常被认为太严格了。现代方法确实使程序变得复杂的多。
通常,只是数据的值很重要。你可能经过训练,认为数据是指定类型,比如,一个文本文件包含文章,一个图像文件包含一幅图片,等等。说实话,这只是一个理想罢了。计算机上的全部数据都是二进制数字,重要的是我们选择用什么来解释这些数据。在这个例子中,我们会将一个闪灯序列作为数据保存下来。
`main.s` 结束处复制下面的代码:
```
Some early Operating Systems did only allow certain types of data in certain files, but this was generally found to be too restrictive. The modern way does make programs a lot more complicated however.
```
In general data is just values that are important. You are probably trained to think of data as being of a specific type, e.g. a text file contains text, an image file contains an image, etc. This is, in truth, just an idea. All data on a computer is just binary numbers, how we choose to interpret them is what counts. In this example we're going to store a light flashing sequence as data.
At the end of 'main.s' copy the following code:
```
.section .data
.align 2
pattern:
.section .data %定义 .data 段
.align 2 %对齐
pattern: %定义整形变量
.int 0b11111111101010100010001000101010
```
```
.align num ensures the address of the next line is a multiple of 2num .
>`.align num` 保证下一行代码的地址是 `2^num` 的整数倍。
.int val outputs the number val .
```
>`.int val` 输出数值 `val`
To differentiate between data and code, we put all the data in the .data. I've included this on the operating system memory layout diagram here. I've just chosen to put the data after the end of the code. The reason for keeping our data and instructions separate is so that if we eventually implement some security on our operating system, we need to know what parts of the code can be executed, and what parts can't.
要区分数据和代码,我们将数据都放在 `.data` 区域。我已经将该区域包含在操作系统的内存布局图。我已经选择将数据放到代码后面。将我们的指令和数据分开保存的原因是,如果最后我们在自己的操作系统上实现一些安全措施,我们就需要知道代码的那些部分是可以执行的,而那些部分是不行的。
I've used two new commands here. .align and .int. .align ensures alignment of the following data to a specified power of 2. In this case I've used .align 2 which means that this data will definitely be placed at an address which is a multiple of 22 = 4. It is really important to do this, because the ldr instruction we used to read memory only works at addresses that are multiples of 4.
我在这里使用了两个新命令 `.align``.int`。`.align` 保证下来的数据是按照 2 的乘方对齐的。在这个里,我使用 `.align 2` ,意味着数据最终存放的地址是 `2^2=4` 的整数倍。这个操作是很重要的,因为我们用来读取内寸的指令 `ldr` 要求内存地址是 4 的倍数。
The .int command copies the constant after it into the output directly. That means that 111111111010101000100010001010102 will be placed into the output, and so the label pattern actually labels this piece of data as pattern.
```
One challenge with data is finding an efficient and useful representation. This method of storing the sequence as on and off units of time is easy to run, but would be difficult to edit, as the concept of a Morse - or . is lost.
```
命令 `.int` 直接复制它后面的常量到输出。这意味着 `11111111101010100010001000101010`(二进制数) 将会被存放到输出,所以标签模式实际将标记这段数据作为模式。
As I mentioned, data can mean whatever you want. In this case I've encoded the Morse Code SOS sequence, which is ...---... for those unfamiliar. I've used a 0 to represent a unit of time with the LED off, and a 1 to represent a unit of time with the LED on. That way, we can write some code which just displays a sequence in data like this one, and then all we have to do to make it display a different sequence is change the data. This is a very simple example of what operating systems must do all the time; interpret and display data.
> 关于数据的一个挑战是寻找一个高效和有用的展示形式。这种保存一个开、关的时间单元的序列的方式,运行起来很容易,但是将很难编辑,因为摩尔斯的原理 `-``.` 丢失了。
Copy the following lines before the loop$ label in 'main.s'.
如我提到的,数据可以意味这你想要的所有东西。在这里我编码了摩尔斯代码 SOS 序列,对于不熟悉的人,就是 `...---...`。我使用 0 表示一个时间单元的 LED 灭灯,而 1 表示一个时间单元的 LED 亮。这样,我们可以像这样编写一些代码在数据中显示一个序列,然后要显示不同序列,我们所有需要做的就是修改这段数据。下面是一个非常简单的例子,操作系统必须一直执行这段程序,解释和展示数据。
复制下面几行到 `main.s` 中的标记 `loop$` 之前。
```
ptrn .req r4
ldr ptrn,=pattern
ldr ptrn,[ptrn]
seq .req r5
mov seq,#0
ptrn .req r4 %重命名 r4 为 ptrn
ldr ptrn,=pattern %加载 pattern 的地址到 ptrn
ldr ptrn,[ptrn] %加载地址 ptrn 所在内存的值
seq .req r5 %重命名 r5 为 seq
mov seq,#0 %seq 赋值为 0
```
This code loads the pattern into r4, and loads 0 into r5. r5 will be our sequence position, so we can keep track of how much of the pattern we have displayed.
这段代码加载 `pattrern` 到寄存器 `r4`,并加载 0 到寄存器 `r5`。`r5` 将是我们的序列位置,所以我们可以追踪有多少 `pattern` 我们已经展示了。
The following code puts a non-zero into r1 if and only if there is a 1 in the current part of the pattern.
下面的代码将非零值放入 `r1` ,如果仅仅是如果,这里有个 1 在当前位置的 `pattern`
```
mov r1,#1
lsl r1,seq
and r1,ptrn
mov r1,#1 %加载1到 r1
lsl r1,seq %对r1 的值逻辑左移 seq 次
and r1,ptrn %按位与
```
This code is useful for your calls to SetGpio, which must have a non-zero value to turn the LED off, and a value of zero to turn the LED on.
这段代码对你调用 `SetGpio` 很有用,它必须有一个非零值来关掉 LED而一个0值会打开 LED。
Now modify all of your code in 'main.s' so that each loop the code sets the LED based on the current sequence number, waits for 250000 micro seconds (or any other appropriate delay), and then increments the sequence number. When the sequence number reaches 32, it needs to go back to 0. See if you can implement this, and for an extra challenge, try to do it using only 1 instruction (solution in the download).
现在修改 `main.s` 中全部你的代码,这样代码中每次循环会根据当前的序列数设置 LED等待 250000 毫秒(或者其他合适的延时),然后增加序列数。当这个序列数到达 32 就需要返回 0.看看你是否能实现这个功能,作为额外的挑战,也可以试着只使用一条指令。
### 2 Time Flies When You're Having Fun...
### 2 Time Flies When You're Having Fun... 当你玩得开心时,过得很快
You're now ready to test this on the Raspberry Pi. It should flash out a sequence of 3 short pulses, 3 long pulses and then 3 more short pulses. After a delay, the pattern should repeat. If it doesn't work please see our troubleshooting page.
你现在准备好在树莓派上实验。应该闪烁一串包含 3 个短脉冲3 个长脉冲,然后 3 个更短脉冲的序列。在一次延时之后,这种模式应该重复。如果这部工作,请查看我们的问题页。
Once it works, congratulations you have reached the end of the OK series of tutorials.
一旦它工作,祝贺你已经达到 OK 系列教程的结束。
In this series we've learnt about assembly code, the GPIO controller and the System Timer. We've learnt about functions and the ABI, as well as several basic Operating System concepts, and also about data.
在这个谢列我们学习了汇编代码GPIO 控制器和系统定时器。我们已经学习了函数和 ABI以及几个基础的操作系统原理和关于数据的知识。
You're now ready to move onto one of the more advanced series.
* The [Screen][2] series is next and teaches you how to use the screen with assembly code.
* The [Input][3] series teaches you how to use the keyboard and mouse.
By now you already have enough information to make Operating Systems that interact with the GPIO in other ways. If you have any robot kits, you may want to try writing a robot operating system controlled with the GPIO pins!
你现在已经准备好下面几个更高级的课程的某一个。
* [Screen][2] 系列是接下来的,会教你如何通过汇编代码使用屏幕。
* [Input][3] 系列教授你如何使用键盘和鼠标。
到现在,你已经有了足够的信息来制作操作系统,用其它方法和 GPIO 交互。如果你有任何机器人工具,你可能会想尝试编写一个通过 GPIO 管教控制的机器人操作系统。
--------------------------------------------------------------------------------
@ -96,7 +91,7 @@ via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html
作者:[Robert Mullins][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
译者:[ezio](https://github.com/oska874)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,3 +1,4 @@
tomjlw is translating
Top 5 Linux Music Players
======
@ -114,7 +115,7 @@ Learn more about Linux through the free ["Introduction to Linux" ][22]course fro
via: https://www.linux.com/learn/intro-to-linux/2017/12/top-5-linux-music-players
作者:[][a]
译者:[译者ID](https://github.com/译者ID)
译者:[tomjlw](https://github.com/tomjlw)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,3 +1,4 @@
beamrolling is translating.
Introduction to the Pony programming language
======

View File

@ -1,177 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (dianbanjiu )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Dcp (Dat Copy) Easy And Secure Way To Transfer Files Between Linux Systems)
[#]: via: (https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/)
[#]: author: (Vinoth Kumar https://www.2daygeek.com/author/vinoth/)
Dcp (Dat Copy) Easy And Secure Way To Transfer Files Between Linux Systems
======
Linux has native command to perform this task nicely using scp and rsync. However, we need to try new things.
Also, we need to encourage the developers who is working new things with different concept and new technology.
We also written few articles about these kind of topic, you can navigate those by clicking the below appropriate links.
Those are **[OnionShare][1]** , **[Magic Wormhole][2]** , **[Transfer.sh][3]** and **ffsend**.
### Whats Dcp?
[dcp][4] copies files between hosts on a network using the peer-to-peer Dat network.
dcp can be seen as an alternative to tools like scp, removing the need to configure SSH access between hosts.
This lets you transfer files between two remote hosts, without you needing to worry about the specifics of how said hosts reach each other and regardless of whether hosts are behind NATs.
dcp requires zero configuration and is secure, fast, and peer-to-peer. Also, this is not production-ready software. Use at your own risk.
### Whats Dat Protocol?
Dat is a peer-to-peer protocol. A community-driven project powering a next-generation Web.
### How dcp works:
dcp will create a dat archive for a specified set of files or directories and, using the generated public key, lets you download said archive from a second host.
Any data shared over the network is encrypted using the public key of the archive, meaning data access is limited to those who have access to said key.
### dcp Use cases:
* Send files to multiple colleagues just send the generated public key via chat and they can receive the files on their machine.
* Sync files between two physical computers on your local network, without needing to set up SSH access.
* Easily send files to a friend without needing to create a zip and upload it the cloud.
* Copy files to a remote server when you have shell access but not SSH, for example on a kubernetes pod.
* Share files between Linux/macOS and Windows, which isnt exactly known for great SSH support.
### How To Install NodeJS & npm in Linux?
dcp package was written in JavaScript programming language so, we need to install NodeJS as a prerequisites to install dcp. Use the following command to install NodeJS in Linux.
For **`Fedora`** system, use **[DNF Command][5]** to install NodeJS & npm.
```
$ sudo dnf install nodejs npm
```
For **`Debian/Ubuntu`** systems, use **[APT-GET Command][6]** or **[APT Command][7]** to install NodeJS & npm.
```
$ sudo apt install nodejs npm
```
For **`Arch Linux`** based systems, use **[Pacman Command][8]** to install NodeJS & npm.
```
$ sudo pacman -S nodejs npm
```
For **`RHEL/CentOS`** systems, use **[YUM Command][9]** to install NodeJS & npm.
```
$ sudo yum install epel-release
$ sudo yum install nodejs npm
```
For **`openSUSE Leap`** system, use **[Zypper Command][10]** to install NodeJS & npm.
```
$ sudo zypper nodejs6
```
### How To Install dcp in Linux?
Once you have installed the NodeJS, use the following npm command to install dcp.
npm is a package manager for the JavaScript programming language. It is the default package manager for the JavaScript runtime environment Node.js.
```
# npm i -g dat-cp
```
### How to Send Files Through dcp?
Enter the files or folders which you want to transfer to remote server followed by the dcp command, And no need to mention the destination machine name.
```
# dcp [File Name Which You Want To Transfer]
```
It will generate a dat archive for the given file when you ran the dcp command. Once its done then it will geerate a public key at the bottom of the page.
### How To Receive Files Through dcp?
Enter the generated the public key on remote server to receive the files or folders.
```
# dcp [Public Key]
```
To recursively copy directories.
```
# dcp [Folder Name Which You Want To Transfer] -r
```
In the following example, we are going to transfer a single file.
![][12]
Output for the above file transfer.
![][13]
If you want to send more than one file, use the following format.
![][14]
Output for the above file transfer.
![][15]
To recursively copy directories.
![][16]
Output for the above folder transfer.
![][17]
It wont allow you to download the files or folders in second time. It means once you downloaded the files or folders then immediately the link will be expired.
![][18]
Navigate to man page to know about other options.
```
# dcp --help
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/
作者:[Vinoth Kumar][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://www.2daygeek.com/author/vinoth/
[b]: https://github.com/lujun9972
[1]: https://www.2daygeek.com/onionshare-secure-way-to-share-files-sharing-tool-linux/
[2]: https://www.2daygeek.com/wormhole-securely-share-files-from-linux-command-line/
[3]: https://www.2daygeek.com/transfer-sh-easy-fast-way-share-files-over-internet-from-command-line/
[4]: https://github.com/tom-james-watson/dat-cp
[5]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
[6]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
[7]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
[8]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
[9]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
[10]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
[11]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[12]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-1.png
[13]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-2.png
[14]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-3.jpg
[15]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-4.jpg
[16]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-6.jpg
[17]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-7.jpg
[18]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-5.jpg

View File

@ -0,0 +1,71 @@
为 Linux 社区采用 snaps 搭建 Slack
======
![][1]
作为一个被数以百万计用户使用的企业级软件平台,[Slack][2] 允许任意规模的团队和企业有效地沟通。Slack 通过在一个单一集成环境中与其它软件工具无缝衔接,为一个组织内的通讯、信息和项目提供了一个易于接触的档案馆。尽管自从诞生后 Slack 就在过去四年中快速成长,但是他们负责该平台跨 Windows、MacOS 和 Linux 运行的桌面工程师团队仅由四人组成。我们通过与在这个团队中负责追踪[上月首发的 Slack snap][3] 的主任工程师 Felix Rieseberg 交谈,来探索更多有关该公司对于 Linux 社区的态度以及他们决定搭建一个 snap 的原因。
[安装 Slack snap][4]
### 你们能告诉我们更多关于已发布的 Slack snap 的信息吗?
我们上月发布了我们的第一个 snap 作为我们为Linux 社区的一种新的发布形式。在企业界,我们发现人们更倾向于以一种相对于个人消费者较慢的速度来采用新科技, 因此我们将会在未来继续提供 .deb 形式的 snap。
### 你们觉得 Linux 社区会对 Slack 有多大的兴趣呢?
在所有的平台上人们对 Slack 的兴趣都正在增长,这一点使我感到十分兴奋。因此这对于我们来说,很难说源自 Linux 社区的兴趣和我们大体上所见到的兴趣有什么区别。当然,不管用户们在什么平台上面工作,满足他们对我们都是很重要的。我们有一个专门负责 Linux 的测试工程师并且我们同时也尽全力提供最好的用户体验。只是我们发现总体相对于 Windows 来说,为 Linux 搭建 snap 略微有点难度,因为我们是在一个较难以预测的平台上工作——而这正是 Linux 社区之光照耀的领域。在汇报程序缺陷以及寻找程序崩溃原因方面,我们有相当多数极富帮助的用户。
### 你们是如何得知 snap 的?
Canonical 公司的 Martin Wimpress 和我接触并向我解释了 snap 的概念。说实话尽管我也用 Ubuntu 但最初我还是迟疑的,因为它看起来像需要搭建与维护的另一套标准。尽管如此,一当我了解到其中的好处之后,我确信这是一笔有回报的投入。
### snap 的什么方面吸引了你们并使你们决定投入其中?
毫无疑问,我们决定搭建 snap 最重要的原因是它的更新特性。在 Slack 上我们大量运用网页技术,这些技术反过来也使得我们提供大量的特性——比如将 YouTube 视频或者 Spotify 播放列表集成在 Slack 中。与浏览器十分相似,这意味着我们需要频繁更新应用。
在 MacOS 和 Windows 上,我们已经有了一个甚至无需用户考虑更新的专门的自动更新器。我们发现哪怕是为了更新,任何形式的中断都是一种我们需要避免的烦恼。因此通过 snap 自动化的更新就显得无缝和便捷得多。
### 相比于其它形式的打包方式,搭建 snap 感觉如何? 将它与现有的设施和进程集成在一起有多简便呢?
就 Linux 而言,我们尚未尝试其它新的打包方式,但我们迟早会的。鉴于我们的大多数用户都使用 Ubuntusnap 是一个很简便的选项。同时 snap 在其它发行版上同样也可以使用这也是一个巨大的加分项。Canonical 正将 snap 做到跨发行版而不是仅仅集中在 Ubuntu 上,这一点我认为是很好的。
搭建 snap 简单得出乎意料,我们有一个创建安装器和软件包的统一流程,我们的 snap 创建过程从一个 .deb 软件包炮制出一个 snap。对于其它技术而言有时候我们不得不为了支持搭建链先造一个内部工具。但是 snapcraft 工具正是我们需要的东西。在整个过程中 Canonical 的团队不可思议般得有助,因为我们一路上确实碰到了一些问题。
### 你们觉得 snap 商店是如何改变用户们寻找、安装你们软件的方式的呢?
Slack 真正的独特之处在于人们不仅仅是碰巧发现它,他们从别的地方知道它并积极地试图找到它。因此尽管我们已经有了相当高的觉悟,我希望对于我们的用户来说,在商店中可以获得 snap 能够让安装过程变得简单一点。
### 你们对用 snap 而不是为了其它发行版不得不再发行软件包有什么期待,或者有什么已经是你们可见的节省呢?
我们希望 snap 可以给予我们的用户更多的便利并确保他们能够更加享受使用 Slack。在我们看来鉴于用户们不必被困在之前的版本这自然而然地解决了许多问题因此 snap 可以让我们在客户支持方面节约时间。有 snap 对我们来说也是一个额外的加分项,因为我们能有一个可供搭建的平台而不是替换我们现有的东西。
### 如果存在的话,你们正使用或者准备使用边缘 (edge)、测试 (beta)、候选 (candidate)、稳定 (stable) 中的哪种发行频道?
我们仅仅在开发中使用边缘 (edge) 频道以与 Canonical 的团队共享。为 Linux 打造的 Slack 总体任在测试 (beta) 频道中。但是长远来看,拥有不同频道的选项十分有意思,同时能够提早一点为感兴趣的客户发行版本也肯定是有好处的。
### 你们认为将软件打包成一个 snap 是如何能够帮助用户的?你们从用户那边得到了什么反馈吗?
对我们的用户来说一个很大的好处是安装和更新总体来说都会变得简便一点。长远来看,问题在于“那些安装 snap 的用户是不是比其它用户少碰到一些困难?”,我十分期望 snap 自带的依赖关系能够使其变成可能。
### 你们有什么会和刚使用 snap 的新用户们分享的建议或知识呢?
我会推荐从 Debian 软件包来着手搭建你们的 snap——那出乎意料得简单。这同样也缩小了开始的范围避免变得不堪重负。这只需要投入相当少的时间并且很大可能是一笔值得的投入。同样如果你们可以的话尽量试着找到 Canonical 的人员来协作——他们拥有了不起的工程师。
### 对于开发来说,你们在什么地方看到了最大的机遇?
我们现在正一步步来,先是让人们用上 snap再从那里开始搭建。正在使用 snap 的人们将会感到更加稳健因为他们将会得益于最新的更新。
--------------------------------------------------------------------------------
via: https://insights.ubuntu.com/2018/02/06/building-slack-for-the-linux-community-and-adopting-snaps/
作者:[Sarah][a]
译者:[tomjlw](https://github.com/tomjlw)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://insights.ubuntu.com/author/sarahfd/
[1]:https://insights.ubuntu.com/wp-content/uploads/a115/Slack_linux_screenshot@2x-2.png
[2]:https://slack.com/
[3]:https://insights.ubuntu.com/2018/01/18/canonical-brings-slack-to-the-snap-ecosystem/
[4]:https://snapcraft.io/slack/

View File

@ -0,0 +1,86 @@
[#]: collector: (lujun9972)
[#]: translator: (HankChow)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Hacking math education with Python)
[#]: via: (https://opensource.com/article/19/1/hacking-math)
[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
将 Python 结合到数学教育中
======
> 身兼教师、开发者、作家数职的 Peter Farrell 来讲述为什么使用 Python 来讲数学课会比传统方法更加好。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/getting_started_with_python.png?itok=MFEKm3gl)
数学课一直都是很讨厌的一件事情,尤其对于在传统教学方法上吃过苦头的人(例如我)来说。传统教学方法强调的是死记硬背和理论知识,这种形式与学生们的现实世界似乎相去甚远。
[Peter Farrell][1] 作为一位 Python 开发者和数学教师,发现学生在数学课程中遇到了困难,于是决定尝试使用 Python 来帮助介绍数学概念。
Peter 的灵感来源于 Logo 语言之父 [Seymour Papert][2],他的 Logo 语言现在还存在于 Python 的 [Turtle 模块][3]中。Logo 语言中的海龟形象让 Peter 喜欢上了 Python并且进一步将 Python 应用到数学教学中。
Peter 在他的新书《[<ruby>Python 数学奇遇记<rt>Math Adventures with Python</rt></ruby>][5]》中分享了他的方法:“图文并茂地指导如何用代码探索数学”。因此我最近对他进行了一次采访,向他了解更多这方面的情况。
**Don Watkins译者注本文作者** 你的教学背景是什么?
**Peter Farrell** 我曾经当过八年的数学老师,之后又教了十年的数学。我还在当老师的时候,就阅读过 Papert 的 《[<ruby>头脑风暴<rt>Mindstorms</rt></ruby>][6]》并从中受到了启发,将 Logo 语言和海龟引入到了我所有的数学课上。
**DW** 你为什么开始使用 Python 呢?
**PF** 在我当家教的时候,需要教学一门枯燥刻板的数学课程,这是一个痛苦的过程。后来我引入了 Logo 语言和海龟,我的学生刚好是一个编程爱好者,他非常喜欢这样的方式。在接触到函数和实际的编程之后,他还提议改用 Python。尽管当时我还不了解 Python但看起来好像和 Logo 语言差别不大,我就同意了。后来我甚至坚持在 Python 上一条道走到黑了!
我还曾经寻找过 3D 图形方面的软件包,用来模拟太阳系行星的运动轨迹,让学生们理解行星是如何在牛顿的万有引力定律作用下运动的。很多图形软件包都需要用到 C 语言编程或者其它一些很复杂的内容,后来我发现了一个叫做 VisualPython 的软件包,它非常方便使用。于是在那之后的几年里,我就一直在用 [Vpython][7] 这个软件包。
所以,我是在和学生一起学习数学的时候被介绍使用 Python 的。在那段时间里,他是我的编程老师,而我则是他的数学老师。
**DW** 是什么让你对数学感兴趣?
**PF** 我是通过传统的方法学习数学的,那时候都是用手写、用纸记、在黑板上计算。我擅长代数和几何,在大学的时候也接触过 Basic 和 Fortran 编程,但那个时候也没有从中获取到灵感。直到后来在从编程中收到了启发,编程可以让你将数学课上一些晦涩难懂的内容变得简单直观,也能让你轻松地绘图、调整、探索,进而发现更多乐趣。
**DW** 是什么启发了你使用 Python 教学?
**PF** 还是在我当家教的时候,我惊奇地发现可以通过循环来计算对同一个函数输入不同参数的结果。如果用人手计算,可能要花半个小时的时间,但计算机瞬间就完成了。在这样的基础上,我们只要将一些计算的过程抽象成一个函数,再对其进行一些适当的扩展,就可以让计算机来计算了。
**DW** 你的教学方法如何帮助学生,特别是在数学上感觉吃力的学生?如何将 Python 编程和数学结合起来
**PF** 很多学生,尤其是高中生,都认为通过手工计算和画图来解决问题的方式在当今已经没有必要了,我并不反对这样的观点。例如,使用 Excel 来处理数据确实应该算是办公室工作的基本技能。学习任何一种编程语言,对公司来说都是一项非常有价值的技能。因此,使用计算机计算确实是有实际意义的。
而使用代码来为数学课创造艺术,则是一项革命性的改变。例如,仅仅是把某个形状显示到屏幕上,就需要使用到数学,因为位置需要用 x-y 坐标去表示,而尺寸、颜色等等都是数字。如果想要移动或者更改某些内容,会需要用到变量。更特殊地,如果需要改变位置,就需要更有效的向量来实现。这样的最终结果是,类似向量、矩阵这些难以捉摸的空洞概念会转变成实打实有意义的数学工具。
那些看起来在数学上吃力的学生,或许只是不太容易接受“书本上的数学”。因为“书本上的数学”过分强调了死记硬背和循规蹈矩,而有些忽视了创造力和实际应用能力。有些学生其实擅长数学,但并不适应学校的教学方式。我的方法会让父母们看到他们的孩子通过代码画出了很多有趣的图形,然后说:“我从来不知道正弦和余弦还能这样用!”
**DW** 你的教学方法是如何在学校里促进 STEM 教育的呢?
**PF** 我喜欢将这几个学科统称为 STEM<ruby>科学、技术、工程、数学<rt>Science, Technology, Engineering and Mathematics</rt></ruby> 或 STEAM<ruby>科学、技术、工程、艺术、数学<rt>Science, Technology, Engineering, Art and Mathematics</rt></ruby>)。但作为数学工作者,我很不希望其中的 M 被忽视。我经常看到很多很小的孩子在 STEM 实验室里参与一些有趣的项目,这表明他们已经在接受科学、技术和工程方面的教育。与此同时,我发现数学方面的材料和项目却很少。因此,我和[机电一体化][8]领域的优秀教师 Ken Hawthorn 正在着手解决这个问题。
希望我的书能够帮助鼓励学生们在技术上有所创新,无论在形式上是切实的还是虚拟的。同时书中还有很多漂亮的图形,希望能够激励大家去体验编程的过程,并且应用到实际中来。我使用的软件([Python Processing][9])是免费的,在树莓派等系统上都可以轻松安装。因为我认为,个人或者学校的成本问题不应该成为学生进入 STEM 世界的门槛。
**DW** 你有什么想要跟其他的数学老师分享?
**PF** 如果数学教学机构决定要向学生教导数字推理、逻辑、分析、建模、几何、数据解释这些内容,那么它们应该承认,可以通过编程来实现这些目标。正如我上面所说的,我的教学方法是在尝试使传统枯燥的方法变得直观,我认为任何一位老师都可以做到这一点。他们只需要知道其中的本质做法,就可以使用代码来完成大量重复的工作了。
我的教学方法依赖于一些免费的图形软件,因此只需要知道在哪里找到这些软件包,以及如何使用这些软件包,就可以开始引导学生使用 21 世纪的技术来解决实际问题,将整个过程和结果可视化,并找到更多可以以此实现的模式。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/1/hacking-math
作者:[Don Watkins][a]
选题:[lujun9972][b]
译者:[HankChow](https://github.com/HankChow)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/don-watkins
[b]: https://github.com/lujun9972
[1]: https://twitter.com/hackingmath
[2]: https://en.wikipedia.org/wiki/Seymour_Papert
[3]: https://en.wikipedia.org/wiki/Turtle_graphics
[4]: https://opensource.com/life/15/8/python-turtle-graphics
[5]: https://nostarch.com/mathadventures
[6]: https://en.wikipedia.org/wiki/Mindstorms_(book)
[7]: http://vpython.org/
[8]: https://en.wikipedia.org/wiki/Mechatronics
[9]: https://processing.org/

View File

@ -0,0 +1,383 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 3 OK03)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室 树莓派:课程 3 OK03
======
OK03 课程基于 OK02 课程来构建,它教你在汇编中如何使用函数让代码可复用和可读性更好。假设你已经有了 [课程 2OK02][1] 的操作系统,我们将以它为基础。
### 1、可复用的代码
到目前为止,我们所写的代码都是以我们希望发生的事为顺序来输入的。对于非常小的程序来说,这种做法很好,但是如果我们以这种方式去写一个完整的系统,所写的代码可读性将非常差。我们应该去使用函数。
```
一个函数是一段可复用的代码片断,可以用于去计算某些答案,或执行某些动作。你也可以称它们为程序、整套动作或子动作。虽然它们都是不同的,但人们几乎都没有正确地使用这个术语。
你应该在数学上遇到了函数的概念。例如,余弦函数应用于一个给定的数时,会得到介于 -1 到 1 之间的另一个数,这个数就是角的余弦。一般我们写成 cos(x) 来表示应用到一个值 x 上的余弦函数。
在代码中,函数可以有多个输入(也可以没有输入),然后函数给出多个输出(也可以没有输出),并可能导致负面效应。例如一个函数可以在一个文件系统上创建一个文件,第一个输入是它的名字,第二个输入是文件的长度。
```
![Function as black boxes][2]
```
函数可以认为是一个“黑匣子”。我们给它输入,然后它给我们输出,而我们不需要知道它是如何工作的。
```
在像 C 或 C++ 这样的高级代码中,函数是语言的组成部分。在汇编代码中,函数只是我们的创意。
理想情况下我们希望能够在我们的寄存器中设置一些值分支地址以及预期在某个时刻分支将返回并通过代码来设置输出值到寄存器。这就是我们所设想的汇编代码中的函数。困难之处在于我们用什么样的方式去设置寄存器。如果我们只是使用平时所接触到的任意方法去设置寄存器每个程序可能使用不同的方法这样你将会发现你很难理解其他程序员所写的代码。另外编译器也不能像使用汇编代码那样轻松地工作因为它们压根不知道如何去使用函数。为避免这种困惑为每个汇编语言设计了一个称为应用程序二进制接口ABI的标准由它来规范函数如何去运行。如果每个人都使用相同的方法去写函数这样每个人都可以去使用其他人写的函数。在这里我将教你们这个标准而从现在开始我所写的函数将全部遵循这个标准。
标准规定,寄存器 `r0`、`r1`、`r2` 和 `r3` 将被依此用于函数的输入。如果函数没有输入,那么它有没有值就无关紧要了。如果只需要一个输入,那么它应该总是在寄存器 `r0` 中,如果它需要两个输入,那么第一个输入在寄存器 `r0` 中,而第二个输入在寄存器 `r1` 中,依此类推。输出值也总是在寄存器 `r0` 中。如果函数没有输出,那么 `ro` 中是什么值就不重要了。
另外,标准要求当一个函数运行之后,寄存器 `r4``r12` 的值必须与函数启动时的值相同。这意味着当你调用一个函数时,你可以确保寄存器 `r4``r12` 中的值没有发生变化,但是不能确保寄存器 `r0``r3` 中的值也没有发生变化。
当一个函数运行完成后,它将返回到启动它的代码分支处。这意味着它必须知道启动它的代码的地址。为此,需要一个称为`lr`(链接寄存器)的专用寄存器,它总是在保存调用这个函数的指令的地址。
表 1.1 ARM ABI 寄存器用法
| 寄存器 | 简介 | 保留 | 规则 |
| ------ | ---------- | ---- | ------------------------------------------------------------ |
| r0 | 参数和结果 | 否 | r0 和 r1 用于给函数传递前两个参数,以及函数返回的结果。如果函数返回值不使用它,那么在函数运行之后,它们可以携带任何值。 |
| r1 | 参数和结果 | 否 | |
| r2 | 参数 | 否 | r2 和 r3 用去给函数传递后两个参数。在函数运行之后,它们可以携带任何值。 |
| r3 | 参数 | 否 | |
| r4 | 通用寄存器 | 是 | r4 到 r12 用于保存函数运行过程中的值,它们的值在函数调用之后必须与调用之前相同。 |
| r5 | 通用寄存器 | 是 | |
| r6 | 通用寄存器 | 是 | |
| r7 | 通用寄存器 | 是 | |
| r8 | 通用寄存器 | 是 | |
| r9 | 通用寄存器 | 是 | |
| r10 | 通用寄存器 | 是 | |
| r11 | 通用寄存器 | 是 | |
| r12 | 通用寄存器 | 是 | |
| lr | 返回地址 | 否 | 当函数运行完成后lr 中保存了分支的返回地址,但在函数运行完成之后,它将保存相同的地址。 |
| sp | 栈指针 | 是 | sp 是栈指针,在下面有详细描述。它的值在函数运行完成后,必须是相同的。 |
通常,函数需要使用很多的寄存器,而不仅是 `r0``r3`。但是,由于 `r4``r12` 必须在系列动作完成之后值必须保持相同,因此它们需要被保存到某个地方。我们将它们保存到称为栈的地方。
![Stack diagram][3]
```
一个栈就是我们在计算中用来保存值的一个很形象的方法。就像是摞起来的一堆盘子,你可以从上到下来移除它们,而添加它们时,你只能从下到上来添加。
在函数运行时,使用栈来保存寄存器值是个非常好的创意。例如,如果我有一个函数需要去使用寄存器 r4 和 r5它将在一个栈上存放这些寄存器的值。最后用这种方式它可以再次将它拿回来。更高明的是如果为完成运行我的函数需要去运行另一个函数并且那个函数需要保存一些寄存器在它运行时它将把寄存器保存在栈顶上然后在结束后再将它们拿走。而这并不会影响我保存在寄存器 r4 和 r5 中的值,因为它们是在栈顶上添加的,拿走时也是从栈顶上取出的。
我们用专用的术语“栈帧”来表示使用特定的方法放到栈上的值。不是每种方法都使用一个栈帧,有些是不需要存储值的。
```
因为栈非常有用,它被直接实现在 ARMv6 的指令集中。一个名为 `sp` (栈指针)的专用寄存器用来保存栈的地址。当需要有东西添加到栈上时,`sp` 寄存器被更新,这样就总是保证它保存的是栈上前一个东西的地址。`push {r4,r5}` 将推送 `r4``r5` 中的值到栈顶上,而 `pop {r4,r5}` 将(以正确的次序)取回它们。
### 2、我们的第一个函数
现在,关于函数的原理我们已经有了一些概念,我们尝试来写一个函数。由于是我们的第一个很基础的例子,我们写一个没有输入的函数,它将输出 GPIO 的地址。在上一节课程中,我们就是写到这个值上,但将它写成函数更好,因为我们在真实的操作系统中经常需要用到它,而我们不可能总是能够记住这个地址。
复制下列代码到一个名为 `gpio.s` 的新文件中。就像在`source` 目录中使用的 `main.s` 一样。我们将把与 GPIO 控制器相关的所有函数放到一个文件中,这样更好查找。
```assembly
.globl GetGpioAddress
GetGpioAddress:
ldr r0,=0x20200000
mov pc,lr
```
```assembly
.globl lbl 使标签 lbl 从其它文件中可访问。
mov reg1,reg2 复制 reg2 中的值到 reg1 中。
```
这就是一个很简单的完整的函数。`.globl GetGpioAddress` 命令是通知汇编器,让标签 `GetGpioAddress` 在所有文件中全局可访问。这意味着在我们的 `main.s` 文件中,我们可以使用分支指令到标签 `GetGpioAddress` 上,即便这个标签在那个文件中没有定义也没有问题。
你应该认得 `ldr r0,=0x20200000` 命令,它将 GPIO 控制器地址保存到 r0 中。由于这是一个函数,我们要让它输出寄存器 `r0` 中的值,因此我们不能再像以前那样随意使用任意一个寄存器了。
`mov pc,lr` 将寄存器 `lr` 中的值复制到 `pc` 中。正如前面所提到的,寄存器 `lr` 总是保存着方法完成后我们要返回的代码的地址。`pc` 是一个专用寄存器,它总是包含下一个要运行的指令的地址。一个普通的分支命令只需要改变这个寄存器的值即可。通过将 `lr` 中的值复制到 `pc` 中,我们就可以将运行的下一行命令改变成我们将要返回的那一行。
现在这里存在一个合乎常理的问题,那就是我们如何去运行这个代码?我们将需要一个特殊的分支类型 `bl`。它像一个普通的分支一样切换到一个标签,但它在切换之前先更新 `lr` 的值去包含一个分支之后的行的地址。这意味着当函数完成后,将返回到 `bl` 命令之后的那一行上。这就确保了函数能够像任何其它命令那样运行,它简单地运行,做任何需要做的事情,然后推进到下一行。这是函数最有用的方法。当我们使用它时,就将它们按“黑匣子”处理即可,不需要了解它是如何运行的,我们只了解它需要什么输入,以及它给我们什么输出即可。
到现在为止,我们已经明白了函数如何使用,下一节我们将使用它。
### 3、一个大的函数
现在,我们继续去实现一个更大的函数。我们的第一项任务是启用 GPIO 第 16 号针脚的输出。如果它是一个函数那就太好了。我们能够简单地指定针脚号作为函数的输入,然后函数将设置那个针脚的值。那样,我们就可以使用这个代码去控制任意的 GPIO 针脚,而不只是 LED 了。
将下列的命令复制到 `gpio.s` 文件中的 GetGpioAddress 函数中。
```assembly
.globl SetGpioFunction
SetGpioFunction:
cmp r0,#53
cmpls r1,#7
movhi pc,lr
```
```
带后缀 ls 的命令只有在上一个比较命令的结果是第一个数字小于或等于第二个数字的情况下才会被运行。它是无符号的。
带后缀 hi 的命令只有上一个比较命令的结果是第一个数字大于第二个数字的情况下才会被运行。它是无符号的。
```
在写一个函数时,我们首先要考虑的事情就是输入,如果输入错了我们怎么办?在这个函数中,我们有一个输入是 GPIO 针脚号,而它必须是介于 0 到 53 之间的数字,因为只有 54 个针脚。每个针脚有 8 个函数,被编号为 0 到 7因此函数代码也必须是 0 到 7 之间的数字。我们可能假设输入应该是正确的,但是当在硬件上使用时,这种做法是非常危险的,因为不正确的值将导致极大的负面效应。所以,在这个案例中,我们希望确保输入值在正确的范围。
为了确保输入值在正确的范围,我们需要做一个检查,即 r0 <= 53 并且 r1 <= 7。首先我们使用前面看到的比较命令去将 `r0` 的值与 53 做比较。下一个指令 `cmpls` 仅在前一个比较指令结果是小于等于 53 时才会去运行。如果一切正常,它将寄存器 `r1` 的值与 7 进行比较,其它的部分都和前面的是一样的。如果最后的比较结果是寄存器值大于那个数字,最后我们将返回到运行函数的代码处。
这正是我们所希望的效果。如果 r0 中的值大于 53那么 `cmpls` 命令将不会去运行,但是 `movhi` 会运行。如果 r0 中的值 <= 53那么 `cmpls` 命令会运行,将 r1 中的值与 7 进行比较,如果它大于 7`movhi` 会运行,函数结束,否则 `movhi` 不会运行,这样我们就确定 r0 <= 53 并且 r1 <= 7。
`ls`(低于或相同)与 `le`(小于或等于)有一些细微的差别,以及后缀 `hi` (高于)和 `gt` (大于)也一样有一些细微差别,我们在后面将会讲到。
将这些命令复制到上面的代码的下面位置。
```assembly
push {lr}
mov r2,r0
bl GetGpioAddress
```
```assembly
push {reg1,reg2,...} 复制列出的寄存器 reg1、reg2、... 到栈顶。该命令仅能用于通用寄存器和 lr 寄存器。
bl lbl sets lr 设置下一个指令的地址并切换到标签 lbl。
```
这三个命令用于调用我们第一个方法。`push {lr}` 命令复制 `lr` 中的值到栈顶,这样我们在后面可以检索到它。当我们调用 GetGpioAddress 时必须要这样做,我们将需要使用 `lr` 去保存我们函数的返回地址。
如果我们对 `GetGpioAddress` 函数一无所知,我们应该假设它改变了 `r0`、`r1`、`r2` 和 `r3` 的值 ,我们将移动我们的值到 r4 和 r5 中,以保持在它完成之后寄存器的值相同。幸运的是,我们知道 `GetGpioAddress` 做了什么,并且我们也知道它仅改变了 `r0` 到地址,它并没有影响 `r1`、`r2` 或 `r3` 的值。因此,我们仅去将 GPIO 针脚号从 `r0` 中移出,这样它就不会被覆盖掉,但我们知道,可以将它安全地移到 `r2` 中,因为 `GetGpioAddress` 并不去改变 `r2`
最后我们使用 `bl` 指令去运行 `GetGpioAddress`。通常,运行一个函数,我们使用一个术语叫“调用”,从现在开始我们将一直使用这个术语。正如我们前面讨论过的,`bl` 通过更新 `lr` 中的下一个指令的地址,去调用一个函数,接着切换到函数。
当一个函数结束时,我们称为“返回”。当一个 `GetGpioAddress` 调用返回时,我们已经知道了 `r0` 中包含了 GPIO 的地址,`r1` 中包含了函数代码,而 `r2` 中包含了 GPIO 针脚号。我前面说过GPIO 函数每 10 个保存在一个块中,因此首先我们需要去判断我们的针脚在哪个块中。这似乎听起来像是要使用一个除法,但是除法做起来非常慢,因此对于这些比较小的数来说,不停地做减法要比除法更好。
将下面的代码复制到上面的代码中最下面的位置。
```assembly
functionLoop$:
cmp r2,#9
subhi r2,#10
addhi r0,#4
bhi functionLoop$
```
```assembly
add reg,#val 将数字 val 加到寄存器 reg 的内容上。
```
这个简单的循环代码将针脚号与 9 进行比较。如果它大于 9它将从针脚号上减去 10并且将 GPIO 控制器地址加上 4然后再次运行检查。
这样做的效果就是,现在,`r2` 中将包含一个 0 到 9 之间的数字,它是针脚号除以 9 的余数。`r0` 将包含这个针脚的函数所设置的 GPIO 控制器的地址。它就如同是 “GPIO 控制器地址 + 4 × (GPIO Pin Number ÷ 10)”。
最后,将下面的代码复制到上面的代码中最下面的位置。
```assembly
add r2, r2,lsl #1
lsl r1,r2
str r1,[r0]
pop {pc}
```
```assembly
移位参数 reg,lsl #val 表示将寄存器 reg 中二进制表示的数逻辑左移 val 位之后的结果作为与前面运算的操作数。
lsl reg,amt 将寄存器 reg 中的二进制数逻辑左移 amt 中的位数。
str reg,[dst] 与 str reg,[dst,#0] 相同。
pop {reg1,reg2,...} 从栈顶复制值到寄存器列表 reg1、reg2、.... 仅有通用寄存器与 pc 可以这样弹出值。
```
这个代码完成了这个方法。第一行其实是乘以 3 的变体。乘法在汇编中是一个大而慢的指令,因为电路需要很长时间才能给出答案。有时使用一些能够很快给出答案的指令会让它变得更快。在本案例中,我们知道 r2 × 3 与 r2 × 2 + r2 是相同的。一个寄存器乘以 2 是非常容易的,因为它可以通过将二进制表示的数左移一位来很方便地实现。
ARMv6 汇编语言其中一个非常有用的特性就是,在使用它之前可以先移动参数所表示的位数。在本案例中,我将 `r2` 加上 `r2` 中二进制表示的数左移一位的结果。在汇编代码中,你可以经常使用这个技巧去更快更容易地计算出答案,但如果你觉得这个技巧使用起来不方便,你也可以写成类似 `mov r3,r2` `add r2,r3` `add r2,r3` 这样的代码。
现在,我们可以将一个函数的值左移 `r2` 中所表示的位数。大多数对数量的指令(比如加法和减法)都有一个可以使用寄存器而不是数字的变体。我们执行这个移位是因为我们想去设置表示针脚号的位,并且每个针脚有三个位。
然后,我们将函数计算后的值保存到 GPIO 控制器的地址上。我们在循环中已经算出了那个地址,因此我们不需要像 OK01 和 OK02 中那样在一个偏移量上保存它。
最后,我们从这个方法调用中返回。由于我们将 `lr` 推送到了栈上,因此我们 `pop pc`,它将复制 `lr` 中的值并将它推送到 `pc` 中。这个操作类似于 `mov pc,lr`,因此函数调用将返回到运行它的那一行上。
敏锐的人可能会注意到,这个函数其实并不能正确工作。虽然它将 GPIO 针脚函数设置为所要求的值,但它会导致在同一个块中的 10 个函数的所有针脚都归 0在一个大量使用 GPIO 针脚的系统中,这将是一个很恼人的问题。我将这个问题留给有兴趣去修复这个函数的人,以确保只设置相关的 3 个位而不去覆写其它位,其它的所有位都保持不变。关于这个问题的解决方案可以在本课程的下载页面上找到。你可能会发现非常有用的几个函数是 `and`,它是计算两个寄存器的布尔与函数,`mvns` 是计算布尔非函数,而 `orr` 是计算布尔或函数。
### 4、另一个函数
现在,我们已经有了能够设置 GPIO 针脚的函数。我们还需要写一个能够打开或关闭 GPIO 针脚的函数。我们不需要写一个打开的函数和一个关闭的函数,只需要一个函数就可以做这两件事情。
我们将写一个名为 `SetGpio` 的函数,它用 `r0` 中的值作为第一个输入,`r1` 中的值作为第二个输入。如果值为 `0`,我们将关闭针脚,而如果为非零则打开针脚。
将下列的代码复制粘贴到 `gpio.s` 文件的结尾部分。
```assembly
.globl SetGpio
SetGpio:
pinNum .req r0
pinVal .req r1
```
```assembly
alias .req reg 设置寄存器 reg 的别名为 alias。
```
我们再次需要 `.globl` 命令,标记它为其它文件可访问的全局函数。这次我们将使用寄存器别名。寄存器别名允许我们为寄存器使用名字而不仅是 `r0``r1`。到目前为止,寄存器别名还不是很重要,但随着我们后面写的方法越来越大,它将被证明非常有用,现在开始我们将尝试使用别名。当在指令中使用到 `pinNum .req r0` 时,它的意思是 `pinNum` 表示 `r0`
将下面的代码复制粘贴到上述的代码下面位置。
```assembly
cmp pinNum,#53
movhi pc,lr
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
```
```assembly
.unreq alias 删除别名 alias。
```
就像在函数 `SetGpio` 中所做的第一件事情是检查给定的针脚号是否有效一样。我们需要同样的方式去将 `pinNum (r0)` 与 53 进行比较,如果它大于 53 将立即返回。一旦我们再次调用 `GetGpioAddress`,我们就需要将 `lr`推送到栈上来保护它,将将 `pinNum` 移动到 `r2` 中。然后我们使用 `.unreq` 语句来删除我们给 `r0` 定义的别名。因为针脚号现在保存在寄存器 `r2` 中,我们希望通过别名能够映射到它,因此我们重新定义到 `r2` 的别名。你应该每次在别名使用结束后,立即删除它,这样当它不再存在时,你就不会在后面的代码中因它而产生错误。
然后,我们调用了 `GetGpioAddress`,并且我们创建了一个指向 `r0`的别名。
将下面的代码复制粘贴到上述代码的后面位置。
```assembly
pinBank .req r3
lsr pinBank,pinNum,#5a
lsl pinBank,#2
add gpioAddr,pinBank
.unreq pinBank
```
```assembly
lsr dst,src,#val 将 src 中二进制表示的数右移 val 位,并将结果保存到 dst。
```
对于打开和关闭 GPIO 针脚,每个针脚在 GPIO 控制器上有两个 4 字节组。在每个场景下,第一个 4 字节组控制前 32 个针脚,而第二个 4 字节组控制剩下的 22 个针脚。为了判断我们要设置的针脚在哪个 4 字节组中,我们需要将针脚号除以 32。幸运的是这很容易因为它等价于将二进制表示的针脚号右移 5 位。因此,在本案例中,我们将 `r3` 命名为 `pinBank`,然后计算 `pinNum ÷ 32`。因为它是一个 4 字节组,我们需要将它与 4 相乘的结果。它与二进制表示的数左移 2 位的相同的,这就是下一行的命令。你可能想知道我们能否将它右移 3 位呢,这样我们就可以先右移再左移。但是这样做是不行的,因为当我们做 ÷ 32 时有些答案可能是四舍五入的,而如果我们做 ÷ 8 时却不会这样。
现在,`gpioAddr` 的结果有可能是 20200000~16~(如果针脚号介于 0 到 31 之间),也有可能是 20200004~16~(如果针脚号介于 32 到 53 之间)。这意味着如果加上 28~10~ ,我们将得到打开针脚的地址,而如果加上 40~10~ ,我们将得到关闭针脚的地址。由于我们使用了 `pinBank` ,所以在它之后立即使用 `.unreq` 去删除它。、
将下面的代码复制粘贴到上述代码的下面位置。
```assembly
and pinNum,#31
setBit .req r3
mov setBit,#1
lsl setBit,pinNum
.unreq pinNum
```
```assembly
and reg,#val 计算寄存器中的数与 val 的布尔与。
```
函数的下一个部分是产生一个正确的设置数的位。至于 GPIO 控制器去打开或关闭针脚,我们在针脚号除以 32 的余数的位置,给它一个设置数字的位。例如,设置 16 号针脚,我们需要第 16 位设置数字为 1 。设置 45 号针脚,我们需要设置第 13 位数字为 1因为 45 ÷ 32 = 1 余数 13。
这个 `and` 命令计算我们需要的余数。它是这样计算的,在输入中所有的二进制位都是 1 时,这个 `and` 运算的结果就是 1否则就是 0。这是一个很基础的二进制操作`and` 操作非常快。我们给定的输入是 “pinNum and 31~10~ = 11111~2~”。这意味着答案的后 5 位中只有 1因此它肯定是在 0 到 31 之间。尤其是在 `pinNum` 的后 5 位的位置是 1 的地方它只有 1。这就如同被 32 整除的余数部分。就像 31 = 32 - 1 并不是巧合。
![binary division example][4]
代码的其余部分使用这个值去左移 1 位。这就有了创建我们所需要的二进制数的效果。
将下面的代码复制粘贴到上述代码的下面位置。
```assembly
teq pinVal,#0
.unreq pinVal
streq setBit,[gpioAddr,#40]
strne setBit,[gpioAddr,#28]
.unreq setBit
.unreq gpioAddr
pop {pc}
```
```assembly
teq reg,#val 检查寄存器 reg 中的数字与 val 是否相等。
```
这个代码是方法的结束部分。如前面所说,当 `pinVal` 为 0 时,我们关闭它,否则就打开它。`teq`(等于测试)是另一个比较操作,它仅能够测试是否相等。它类似于 `cmp` ,但它并不能算出哪个数大。如果你只是希望测试数字是否相同,你可以使用 `teq`
如果 `pinVal` 是 0我们将 `setBit` 保存在 GPIO 地址偏移 40 的位置,我们已经知道,这样会关闭那个针脚。否则将它保存在 GPIO 地址偏移 28 的位置,它将打开那个针脚。最后,我们通过弹出 `pc` 返回,这将设置它为我们推送链接寄存器时保存的值。
### 5、一个新的开始
在完成上述工作后,我们终于有了我们的 GPIO 函数。现在,我们需要去修改 `main.s` 去使用它们。因为 `main.s` 现在已经有点大了,也更复杂了。将它分成两节将是一个很好的设计。到目前为止,我们一直使用的 `.init` 应该尽可能的让它保持小。我们可以更改代码来很容易地反映出这一点。
将下列的代码插入到 `main.s` 文件中 `_start: ` 的后面:
```
b main
.section .text
main:
mov sp,#0x8000
```
在这里重要的改变是引入了 `.text` 节。我设计了 `makefile` 和链接器脚本,它将 `.text` 节(它是默认节)中的代码放在地址为 8000~16~ 的 `.init` 节之后。这是默认加载地址,并且它给我们提供了一些空间去保存栈。由于栈存在于内存中,它也有一个地址。栈向下增长内存,因此每个新值都低于前一个地址,所以,这便得栈顶是最低的一个地址。
```
图中的 'ATAGs' 节的位置保存了有关树莓派的信息,比如它有多少内存,默认屏幕分辨率是多少。
```
![Layout diagram of operating system][5]
用下面的代码替换掉所有设置 GPIO 函数针脚的代码:
```assembly
pinNum .req r0
pinFunc .req r1
mov pinNum,#16
mov pinFunc,#1
bl SetGpioFunction
.unreq pinNum
.unreq pinFunc
```
这个代码将使用针脚号 16 和函数代码 1 去调用 `SetGpioFunction`。它的效果就是启用了 OK LED 灯的输出。
用下面的代码去替换打开 OK LED 灯的代码:
```assembly
pinNum .req r0
pinVal .req r1
mov pinNum,#16
mov pinVal,#0
bl SetGpio
.unreq pinNum
.unreq pinVal
```
这个代码使用 `SetGpio` 去关闭 GPIO 第 16 号针脚,因此将打开 OK LED。如果我们将第 4 行)替换成 `mov pinVal,#1` 它将关闭 LED 灯。用以上的代码去替换掉你关闭 LED 灯的旧代码。
### 6、继续向目标前进
但愿你能够顺利地在你的树莓派上测试我们所做的这一切。到目前为止,我们已经写了一大段代码,因此不可避免会出现错误。如果有错误,可以去查看我们的排错页面。
如果你的代码已经正常工作,恭喜你。虽然我们的操作系统除了做 [课程 2OK02][1] 中的事情之外,还做不了别的任何事情,但我们已经学会了函数和格式有关的知识,并且我们现在可以更好更快地编写新特性了。现在,我们在操作系统上修改 GPIO 寄存器将变得非常简单,而它就是用于控制硬件的!
在 [课程 4OK04][6] 中,我们将处理我们的 `wait` 函数,目前,它的时间控制还不精确,这样我们就可以更好地控制我们的 LED 灯了,进而最终控制所有的 GPIO 针脚。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok03.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/ok02.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/functions.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/stack.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/binary3.png
[5]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/osLayout.png
[6]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html

View File

@ -0,0 +1,173 @@
[#]: collector: (lujun9972)
[#]: translator: (qhwdw)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Computer Laboratory Raspberry Pi: Lesson 4 OK04)
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.html)
[#]: author: (Robert Mullins http://www.cl.cam.ac.uk/~rdm34)
计算机实验室 树莓派:课程 4 OK04
======
OK04 课程在 OK03 的基础上进行构建,它教你如何使用定时器让 `OK``ACT` LED 灯按精确的时间间隔来闪烁。假设你已经有了 [课程 3OK03][1] 的操作系统,我们将以它为基础来构建。
### 1、一个新设备
定时器是树莓派保持时间的唯一方法。大多数计算机都有一个电池供电的时钟,这样当计算机关机后仍然能保持时间。
到目前为止,我们仅看了树莓派硬件的一小部分,即 GPIO 控制器。我只是简单地告诉你做什么,然后它会发生什么事情。现在,我们继续看定时器,并继续带你去了解它的工作原理。
和 GPIO 控制器一样,定时器也有地址。在本案例中,定时器的基地址在 20003000~16~。阅读手册我们可以找到下面的表:
表 1.1 GPIO 控制器寄存器
| 地址 | 大小 / 字节 | 名字 | 描述 | 读或写 |
| -------- | ------------ | ---------------- | ---------------------------------------------------------- | ---------------- |
| 20003000 | 4 | Control / Status | 用于控制和清除定时器通道比较器匹配的寄存器 | RW |
| 20003004 | 8 | Counter | 按 1 MHz 的频率递增的计数器 | R |
| 2000300C | 4 | Compare 0 | 0 号比较器寄存器 | RW |
| 20003010 | 4 | Compare 1 | 1 号比较器寄存器 | RW |
| 20003014 | 4 | Compare 2 | 2 号比较器寄存器 | RW |
| 20003018 | 4 | Compare 3 | 3 号比较器寄存器 | RW |
![Flowchart of the system timer's operation][2]
这个表只告诉我们一部分内容,在手册中描述了更多的字段。手册上解释说,定时器本质上是按每微秒将计数器递增 1 的方式来运行。每次它是这样做的,它将计数器的低 32 位4 字节)与 4 个比较器寄存器进行比较,如果匹配它们中的任何一个,它更新 `Control/Status` 以反映出其中有一个是匹配的。
关于<ruby><rt>bit</rt></ruby>、字节、<ruby>位字段<rt>bit field</rt></ruby>、以及数据大小的更多内容如下:
>
> 一个位是一个单个的二进制数的名称。你可能还记得,一个单个的二进制数即可能是一个 1也可能是一个 0。
>
> 一个字节是一个 8 位集合的名称。由于每个位可能是 1 或 0 这两个值的其中之一,因此,一个字节有 2^8^ = 256 个不同的可能值。我们一般解释一个字节为一个介于 0 到 255之间的二进制数。
>
> ![Diagram of GPIO function select controller register 0.][3]
>
> 一个位字段是解释二进制的另一种方式。二进制可以解释为许多不同的东西,而不仅仅是一个数字。一个位字段可以将二进制看做为一系列的 1 或 0的开关。对于每个小开关我们都有一个意义我们可以使用它们去控制一些东西。我们已经遇到了 GPIO 控制器使用的位字段,使用它设置一个针脚的开或关。位为 1 时 GPIO 针脚将准确地打开或关闭。有时我们需要更多的选项,而不仅仅是开或关,因此我们将几个开关组合到一起,比如 GPIO 控制器的函数设置(如上图),每 3 位为一组控制一个 GPIO 针脚的函数。
>
我们的目标是实现一个函数,这个函数能够以一个时间数量为输入来调用它,这个输入的时间数量将作为等待的时间,然后返回。想一想如何去做,想想我们都拥有什么。
我认为这将有两个选择:
1. 从计数器中读取一个值,然后保持分支返回到相同的代码,直到计数器的等待时间数量大于它。
2. 从计数器中读取一个值,加时间数量去等待,保存它到比较器寄存器,然后保持分支返回到相同的代码处,直到 `Control / Status` 寄存器更新。
```
像这样存在被称为"并发问题"的问题,并且几乎无法解决。
```
这两种策略都工作的很好,但在本教程中,我们将只实现第一个。原因是比较器寄存器更容易出错,因为在增加等待时间并保存它到比较器的寄存器期间,计数器可能已经增加了,并因此可能会不匹配。如果请求的是 1 微秒(或更糟糕的情况是 0 微秒)的等待,这样可能导致非常长的意外延迟。
### 2、实现
```
大型的操作系统通常使用等待函数来抓住机会在后台执行任务。
```
我将把这个创建完美的等待方法的挑战留给你。我建议你将所有与定时器相关的代码都放在一个名为 `systemTimer.s` 的文件中(理由很明显)。关于这个方法的复杂部分是,计数器是一个 8 字节值,而每个寄存器仅能保存 4 字节。所以,计数器值将分到 2 个寄存器中。
下列的代码块是一个示例。
```assembly
ldrd r0,r1,[r2,#4]
```
```assembly
ldrd regLow,regHigh,[src,#val] 从 src 加上 val 数的地址上加载 8 字节到寄存器 regLow 和 regHigh 中。
```
上面的代码中你可以发现一个很有用的指令是 `ldrd`。它从两个寄存器中加载 8 字节的内存。在本案例中,这 8 字节内存从寄存器 `r2` 中的地址开始,将被复制进寄存器 `r0``r1`。这种安排的稍微复杂之处在于 `r1` 实际上只持有了高位 4 字节。换句话说就是,如果如果计数器的值是 999,999,999,999~10~ = 1110100011010100101001010000111111111111~2~ ,那么寄存器 `r1` 中只有 11101000~2~,而寄存器 `r0` 中则是 11010100101001010000111111111111~2~。
实现它的更明智的方式应该是,去计算当前计数器值与来自方法启动后的那一个值的差,然后将它与要求的等待时间数量进行比较。除非恰好你希望的等待时间是支持 8 字节的,否则上面示例中寄存器 `r1` 中的值将会丢失,而计数器仅需要使用低位 4 字节。
当等待开始时,你应该总是确保使用大于比较,而不是使用等于比较,因为如果你尝试去等待一个时间,而这个时间正好等于方法开始的时间与结束的时间之差,那么你就错过这个值而永远等待下去。
如果你不明白如何编写等待函数的代码,可以参考下面的指南。
>
> 借鉴 GPIO 控制器的创意,第一个函数我们应该去写如何取得系统定时器的地址。示例如下:
>
> ```assembly
> .globl GetSystemTimerBase
> GetSystemTimerBase:
> ldr r0,=0x20003000
> mov pc,lr
> ```
>
> 另一个被证明非常有用的函数是在寄存器 `r0``r1` 中返回当前计数器值:
>
> ```assembly
> .globl GetTimeStamp
> GetTimeStamp:
> push {lr}
> bl GetSystemTimerBase
> ldrd r0,r1,[r0,#4]
> pop {pc}
> ```
>
> 这个函数简单地使用了 `GetSystemTimerBase` 函数,并像我们前面学过的那样,使用 `ldrd` 去加载当前计数器值。
>
> 现在,我们可以去写我们的等待方法的代码了。首先,在方法启动后,我们需要知道计数器值,当前计数器值我们现在已经可以使用 `GetTimeStamp` 来取得了。
>
> ```assembly
> delay .req r2
> mov delay,r0
> push {lr}
> bl GetTimeStamp
> start .req r3
> mov start,r0
> ```
>
> 这个代码复制我们的方法的输入,将延迟时间的数量放到寄存器 `r2` 中,然后调用 `GetTimeStamp`,这个函数将会在寄存器 `r0``r1` 中返回当前计数器值。接着复制计数器值的低位 4 字节到寄存器 `r3` 中。
>
> 接下来,我们需要计算当前计数器值与读入的值的差,然后持续这样做,直到它们的差至少是延迟大小为止。
>
> ```assembly
> loop$:
>
> bl GetTimeStamp
> elapsed .req r1
> sub elapsed,r0,start
> cmp elapsed,delay
> .unreq elapsed
> bls loop$
> ```
>
> 这个代码将一直等待,一直到等待到传递给它的时间数量为止。它从计数器中读取数值,减去最初从计数器中读取的值,然后与要求的延迟时间进行比较。如果过去的时间数量小于要求的延迟,它切换到 `loop$`
>
> ```assembly
> .unreq delay
> .unreq start
> pop {pc}
> ```
>
> 代码完成后,函数返回。
>
### 3、另一个闪灯程序
你一旦明白了等待函数的工作原理,修改 `main.s` 去使用它。修改各处 `r0` 的等待设置值为某个很大的数量(记住它的单位是微秒),然后在树莓派上测试。如果函数不能正常工作,请查看我们的排错页面。
如果正常工作,恭喜你学会控制另一个设备了,会使用它,则时间由你控制。在下一节课程中,我们将完成 OK 系列课程的最后一节 [课程 5OK05][4],我们将使用我们已经学习过的知识让 LED 按我们的模式进行闪烁。
--------------------------------------------------------------------------------
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok04.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/ok03.html
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/systemTimer.png
[3]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/images/gpioControllerFunctionSelect.png
[4]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html

View File

@ -1,336 +0,0 @@
如何搜索一个包是否在你的 Linux 发行版中
======
如果你知道包名称,那么你可以直接安装所需的包。
在某些情况下,如果你不知道确切的包名称或者你想搜索某些包,那么你可以在分发包管理器的帮助下轻松搜索该包。
自动搜索包括已安装和可用的包。
结果的格式取决于选项。如果查询没有生成任何信息,那么意味着没有匹配条件的包。
这可以通过具有各种选项的分发包管理器来完成。
我已经在本文中添加了所有可能的选项,你可以选择最好的和最合适你的选项。
或者,我们可以通过 **whohas** 命令实现这一点。它会从所有的主流发行版(例如 Debian, Ubuntu, Fedora 等)中搜索,而不仅仅是你自己的系统发行版。
**建议阅读:**
**(#)** [适用于 Linux 的命令行包管理器列表以及用法][1]
**(#)** [Linux 包管理器的图形前端工具][2]
### 如何在 Debian/Ubuntu 中搜索一个包
我们可以使用 apt, apt-cache 和 aptitude 包管理器在基于 Debian 的发行版上查找给定的包。我为这个包管理器中包括了大量的选项。
我们可以在基于 Debian 的系统中使用三种方式完成此操作。
* apt 命令
* apt-cache 命令
* aptitude 命令
### 如何使用 apt 命令搜索一个包
APT 代表高级包管理工具 Advanced Packaging ToolAPT它取代了 apt-get。它有功能丰富的命令行工具包括所有功能包含在一个命令APT包括 apt-cache, apt-search, dpkg, apt-cdrom, apt-config, apt-key 等,还有其他几个独特的功能。
APT 是一个强大的命令行工具,它可以访问 libapt-pkg 底层库的所有特性,它可以用于安装,下载,删除,搜索和管理以及查询关于包的信息,另外它还包含一些较少使用的与包管理相关的命令行实用程序。
```
$ apt -q list nano vlc
Listing...
nano/artful,now 2.8.6-3 amd64 [installed]
vlc/artful 2.2.6-6 amd64
```
或者,我们可以使用以下格式搜索指定的包。
```
$ apt search ^vlc
Sorting... Done
Full Text Search... Done
vlc/artful 2.2.6-6 amd64
multimedia player and streamer
vlc-bin/artful 2.2.6-6 amd64
binaries from VLC
vlc-data/artful,artful 2.2.6-6 all
Common data for VLC
vlc-l10n/artful,artful 2.2.6-6 all
Translations for VLC
vlc-plugin-access-extra/artful 2.2.6-6 amd64
multimedia player and streamer (extra access plugins)
vlc-plugin-base/artful 2.2.6-6 amd64
multimedia player and streamer (base plugins)
```
### 如何使用 apt-cache 命令搜索一个包
apt-cache 会在 APT 的包缓存上执行各种操作。它会显示有关指定包的信息。apt-cache 不会操纵系统的状态,但提供了从包的元数据中搜索和生成有趣输出的操作。
```
$ apt-cache search nano | grep ^nano
nano - small, friendly text editor inspired by Pico
nano-tiny - small, friendly text editor inspired by Pico - tiny build
nanoblogger - Small weblog engine for the command line
nanoblogger-extra - Nanoblogger plugins
nanoc - static site generator written in Ruby
nanoc-doc - static site generator written in Ruby - documentation
nanomsg-utils - nanomsg utilities
nanopolish - consensus caller for nanopore sequencing data
```
或者,我们可以使用以下格式搜索指定的包。
```
$ apt-cache policy vlc
vlc:
Installed: (none)
Candidate: 2.2.6-6
Version table:
2.2.6-6 500
500 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 Packages
```
或者,我们可以使用以下格式搜索给定的包。
```
$ apt-cache pkgnames vlc
vlc-bin
vlc-plugin-video-output
vlc-plugin-sdl
vlc-plugin-svg
vlc-plugin-samba
vlc-plugin-fluidsynth
vlc-plugin-qt
vlc-plugin-skins2
vlc-plugin-visualization
vlc-l10n
vlc-plugin-notify
vlc-plugin-zvbi
vlc-plugin-vlsub
vlc-plugin-jack
vlc-plugin-access-extra
vlc
vlc-data
vlc-plugin-video-splitter
vlc-plugin-base
```
### 如何使用 aptitude 命令搜索一个包
aptitude 一个基于文本的 Debian GNU/Linux 软件包系统的接口。它允许用户查看包列表,并执行包管理任务,例如安装,升级和删除包,它可以从可视化界面或命令行执行操作。
```
$ aptitude search ^vlc
p vlc - multimedia player and streamer
p vlc:i386 - multimedia player and streamer
p vlc-bin - binaries from VLC
p vlc-bin:i386 - binaries from VLC
p vlc-data - Common data for VLC
v vlc-data:i386 -
p vlc-l10n - Translations for VLC
v vlc-l10n:i386 -
p vlc-plugin-access-extra - multimedia player and streamer (extra access plugins)
p vlc-plugin-access-extra:i386 - multimedia player and streamer (extra access plugins)
p vlc-plugin-base - multimedia player and streamer (base plugins)
p vlc-plugin-base:i386 - multimedia player and streamer (base plugins)
p vlc-plugin-fluidsynth - FluidSynth plugin for VLC
p vlc-plugin-fluidsynth:i386 - FluidSynth plugin for VLC
p vlc-plugin-jack - Jack audio plugins for VLC
p vlc-plugin-jack:i386 - Jack audio plugins for VLC
p vlc-plugin-notify - LibNotify plugin for VLC
p vlc-plugin-notify:i386 - LibNotify plugin for VLC
p vlc-plugin-qt - multimedia player and streamer (Qt plugin)
p vlc-plugin-qt:i386 - multimedia player and streamer (Qt plugin)
p vlc-plugin-samba - Samba plugin for VLC
p vlc-plugin-samba:i386 - Samba plugin for VLC
p vlc-plugin-sdl - SDL video and audio output plugin for VLC
p vlc-plugin-sdl:i386 - SDL video and audio output plugin for VLC
p vlc-plugin-skins2 - multimedia player and streamer (Skins2 plugin)
p vlc-plugin-skins2:i386 - multimedia player and streamer (Skins2 plugin)
p vlc-plugin-svg - SVG plugin for VLC
p vlc-plugin-svg:i386 - SVG plugin for VLC
p vlc-plugin-video-output - multimedia player and streamer (video output plugins)
p vlc-plugin-video-output:i386 - multimedia player and streamer (video output plugins)
p vlc-plugin-video-splitter - multimedia player and streamer (video splitter plugins)
p vlc-plugin-video-splitter:i386 - multimedia player and streamer (video splitter plugins)
p vlc-plugin-visualization - multimedia player and streamer (visualization plugins)
p vlc-plugin-visualization:i386 - multimedia player and streamer (visualization plugins)
p vlc-plugin-vlsub - VLC extension to download subtitles from opensubtitles.org
p vlc-plugin-zvbi - VBI teletext plugin for VLC
p vlc-plugin-zvbi:i386
```
### 如何在 RHEL/CentOS 中搜索一个包
YumYellowdog Updater Modified是 Linux 操作系统中的包管理器实用程序之一。Yum 命令用于在一些基于 RedHat 的 Linux 发行版上,它用来安装,更新,搜索和删除软件包。
```
# yum search ftpd
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
* base: centos.hyve.com
* epel: mirrors.coreix.net
* extras: centos.hyve.com
* rpmforge: www.mirrorservice.org
* updates: mirror.sov.uk.goscomb.net
============================================================== N/S Matched: ftpd ===============================================================
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
vsftpd.x86_64 : Very Secure Ftp Daemon
Name and summary matches only, use "search all" for everything.
```
或者,我们可以使用以下命令搜索相同内容。
```
# yum list ftpd
```
### 如何在 Fedora 中搜索一个包
DNF 代表 Dandified yum。我们可以说 DNF 是下一代 yum 包管理器Yum 的衍生),它使用 hawkey/libsolv 库作为底层。自从 Fedora 18 开始以及它最终在 Fedora 22 中实施以来Aleš Kozumplík 就在开始研究 DNF。
```
# dnf search ftpd
Last metadata expiration check performed 0:42:28 ago on Tue Jun 9 22:52:44 2018.
============================== N/S Matched: ftpd ===============================
proftpd-utils.x86_64 : ProFTPD - Additional utilities
pure-ftpd-selinux.x86_64 : SELinux support for Pure-FTPD
proftpd-devel.i686 : ProFTPD - Tools and header files for developers
proftpd-devel.x86_64 : ProFTPD - Tools and header files for developers
proftpd-ldap.x86_64 : Module to add LDAP support to the ProFTPD FTP server
proftpd-mysql.x86_64 : Module to add MySQL support to the ProFTPD FTP server
proftpd-postgresql.x86_64 : Module to add PostgreSQL support to the ProFTPD FTP
: server
vsftpd.x86_64 : Very Secure Ftp Daemon
proftpd.x86_64 : Flexible, stable and highly-configurable FTP server
owfs-ftpd.x86_64 : FTP daemon providing access to 1-Wire networks
perl-ftpd.noarch : Secure, extensible and configurable Perl FTP server
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
pyftpdlib.noarch : Python FTP server library
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server
```
或者,我们可以使用以下命令搜索相同的内容。
```
# dnf list proftpd
Failed to synchronize cache for repo 'heikoada-terminix', disabling.
Last metadata expiration check: 0:08:02 ago on Tue 26 Jun 2018 04:30:05 PM IST.
Available Packages
proftpd.x86_64
```
### 如何在 Arch Linux 中搜索一个包
pacman 代表包管理实用程序pacman。它是一个用于安装构建删除和管理 Arch Linux 软件包的命令行实用程序。pacman 使用 libalpmArch Linux Package ManagementALPM作为底层来执行所有操作。
在本例中,我将要搜索 chromium 包。
```
# pacman -Ss chromium
extra/chromium 48.0.2564.116-1
The open-source project behind Google Chrome, an attempt at creating a safer, faster, and more stable browser
extra/qt5-webengine 5.5.1-9 (qt qt5)
Provides support for web applications using the Chromium browser project
community/chromium-bsu 0.9.15.1-2
A fast paced top scrolling shooter
community/chromium-chromevox latest-1
Causes the Chromium web browser to automatically install and update the ChromeVox screen reader extention. Note: This
package does not contain the extension code.
community/fcitx-mozc 2.17.2313.102-1
Fcitx Module of A Japanese Input Method for Chromium OS, Windows, Mac and Linux (the Open Source Edition of Google Japanese
Input)
```
默认情况下,`-s` 选项内置 ERE扩展正则表达式会导致很多不需要的结果。使用以下格式会仅匹配包名称。
```
# pacman -Ss '^chromium-'
```
pkgfile 是一个用于在 Arch Linux 官方仓库的包中搜索文件的工具。
```
# pkgfile chromium
```
### 如何在 openSUSE 中搜索一个包
Zypper 是 SUSE 和 openSUSE 发行版的命令行包管理器。它用于安装更新搜索和删除包以及管理仓库执行各种查询等。Zypper 命令行接口到 ZYpp 系统管理库libzypp
```
# zypper search ftp
or
# zypper se ftp
Loading repository data...
Reading installed packages...
S | Name | Summary | Type
--+----------------+-----------------------------------------+--------
| proftpd | Highly configurable GPL-licensed FTP -> | package
| proftpd-devel | Development files for ProFTPD | package
| proftpd-doc | Documentation for ProFTPD | package
| proftpd-lang | Languages for package proftpd | package
| proftpd-ldap | LDAP Module for ProFTPD | package
| proftpd-mysql | MySQL Module for ProFTPD | package
| proftpd-pgsql | PostgreSQL Module for ProFTPD | package
| proftpd-radius | Radius Module for ProFTPD | package
| proftpd-sqlite | SQLite Module for ProFTPD | package
| pure-ftpd | A Lightweight, Fast, and Secure FTP S-> | package
| vsftpd | Very Secure FTP Daemon - Written from-> | package
```
### 如何使用 whohas 命令搜索一个包
whohas 命令是一个智能工具,从所有主流发行版中搜索指定包,如 Debian, Ubuntu, Gentoo, Arch, AUR, Mandriva, Fedora, Fink, FreeBSD 和 NetBSD。
```
$ whohas nano
Mandriva nano-debug 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/0b33dc73bca710749ad14bbc3a67e15a
Mandriva nano-debug 2.2.4-1mdv2010.1.i http://sophie.zarb.org/rpms/d9dfb2567681e09287b27e7ac6cdbc05
Mandriva nano-debug 2.2.4-1mdv2010.1.x http://sophie.zarb.org/rpms/3299516dbc1538cd27a876895f45aee4
Mandriva nano 2.3.1-1mdv2010.2.x http://sophie.zarb.org/rpms/98421c894ee30a27d9bd578264625220
Mandriva nano 2.3.1-1mdv2010.2.i http://sophie.zarb.org/rpms/cea07b5ef9aa05bac262fc7844dbd223
Mandriva nano 2.2.4-1mdv2010.1.s http://sophie.zarb.org/rpms/d61f9341b8981e80424c39c3951067fa
Mandriva spring-mod-nanoblobs 0.65-2mdv2010.0.sr http://sophie.zarb.org/rpms/74bb369d4cbb4c8cfe6f6028e8562460
Mandriva nanoxml-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/287a4c37bc2a39c0f277b0020df47502
Mandriva nanoxml-manual-lite 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/17dc4f638e5e9964038d4d26c53cc9c6
Mandriva nanoxml-manual 2.2.3-4.1.4mdv2010 http://sophie.zarb.org/rpms/a1b5092cd01fc8bb78a0f3ca9b90370b
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 9999 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 2.9.8 http://packages.gentoo.org/package/app-editors/nano
Gentoo nano 2.9.7 http://packages.gentoo.org/package/app-editors/nano
```
如果你希望只从当前发行版仓库中搜索指定包,使用以下格式:
```
$ whohas -d Ubuntu vlc
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty/vlc
Ubuntu vlc 2.1.6-0ubuntu14.04 1M all http://packages.ubuntu.com/trusty-updates/vlc
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial/vlc
Ubuntu vlc 2.2.2-5ubuntu0.16. 1M all http://packages.ubuntu.com/xenial-updates/vlc
Ubuntu vlc 2.2.6-6 40K all http://packages.ubuntu.com/artful/vlc
Ubuntu vlc 3.0.1-3build1 32K all http://packages.ubuntu.com/bionic/vlc
Ubuntu vlc 3.0.2-0ubuntu0.1 32K all http://packages.ubuntu.com/bionic-updates/vlc
Ubuntu vlc 3.0.3-1 33K all http://packages.ubuntu.com/cosmic/vlc
Ubuntu browser-plugin-vlc 2.0.6-2 55K all http://packages.ubuntu.com/trusty/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/xenial/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/artful/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/bionic/browser-plugin-vlc
Ubuntu browser-plugin-vlc 2.0.6-4 47K all http://packages.ubuntu.com/cosmic/browser-plugin-vlc
Ubuntu libvlc-bin 2.2.6-6 27K all http://packages.ubuntu.com/artful/libvlc-bin
Ubuntu libvlc-bin 3.0.1-3build1 17K all http://packages.ubuntu.com/bionic/libvlc-bin
Ubuntu libvlc-bin 3.0.2-0ubuntu0.1 17K all http://packages.ubuntu.com/bionic-updates/libvlc-bin
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/how-to-search-if-a-package-is-available-on-your-linux-distribution-or-not/
作者:[Prakash Subramanian][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[MjSeven](https://github.com/MjSeven)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.2daygeek.com/author/prakash/
[1]:https://www.2daygeek.com/list-of-command-line-package-manager-for-linux/
[2]:https://www.2daygeek.com/list-of-graphical-frontend-tool-for-linux-package-manager/

View File

@ -0,0 +1,176 @@
[#]: collector: (lujun9972)
[#]: translator: (dianbanjiu )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Dcp (Dat Copy) Easy And Secure Way To Transfer Files Between Linux Systems)
[#]: via: (https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/)
[#]: author: (Vinoth Kumar https://www.2daygeek.com/author/vinoth/)
DcpDat Copy—— 在不同 Linux 系统之间传输文件的安全又容易的方式
======
Linux 本就有 scp 和 rsync 可以完美地完成这个任务。然而我们今天还是想试点新东西。
同时我们也很鼓励那些使用不同的理论和新技术开发新东西的开发者。
我们也写过其他很多有关这个主题的文章,你可以点击下面的链接访问这些内容。
它们分别是 **[OnionShare][1]****[Magic Wormhole][2]****[Transfer.sh][3]** 和 **ffsend**
### 什么是 Dcp
[dcp][4] 在不同主机之间使用对等网络复制文件。
dcp 被视作一个像是 scp 这样工具的替代品,无需在主机间进行 SSH 授权。
这可以让你在两个主机间传输文件时,无需操心所述主机之间互相访问的细节,以及这些主机是否使用了 NATs。
dcp 零配置、安全、快速、且是 P2P 传输。这并不是一个商用软件,使用产生的风险将由使用者自己承担。
### 什么是 Dat 协议
Dat 是一个 P2P 协议,是一个致力于下一代 Web 的社区驱动的项目。
### dcp 如何工作
dcp 将会为指定的文件或者文件夹创建一个 dat 归档,并生成一个公钥,使用这个公钥可以让其他人从另外一台主机上下载上面的文件。
使用网络共享的任何数据都使用归档的公钥加密,也就是说文件的接收权仅限于那些知道公钥的人。
### dcp 使用案例
* 向多个同事发送文件 —— 只需要告诉他们生成的公钥,然后他们就可以在他们的机器上收到对应的文件了。
* 无需设置 SSH 授权就可以在你本地网络的两个不同物理机上同步文件。
* 无需压缩文件并把文件上传到云端就可以轻松地发送文件。
* 当你有 shell 授权而没有 SSH 授权时也可以复制文件到远程服务器上。
* 在没有很好的 SSH 支持的 Linux/macOS 以及 Windows 系统之间分享文件。
### 如何在 Linux 上安装 NodeJS & npm
dcp 是用 JavaScript 写成的,所以在安装 dcp 前,需要先安装 NodeJS。在 Linux 上使用下面的命令安装 NodeJS。
**Fedora** 系统,使用 **[DNF 命令][5]** 安装 NodeJS & npm。
```
$ sudo dnf install nodejs npm
```
**`Debian/Ubuntu`** 系统,使用 **[APT-GET 命令][6]** 或者 **[APT 命令][6]** 安装 NodeJS & npm。
```
$ sudo apt install nodejs npm
```
**`Arch Linux`** 系统,使用 **[Pacman 命令][8]** 安装 NodeJS & npm。
```
$ sudo pacman -S nodejs npm
```
**`RHEL/CentOS`** 系统,使用 **[YUM 命令][9]** 安装 NodeJS & npm。
```
$ sudo yum install epel-release
$ sudo yum install nodejs npm
```
**`openSUSE Leap`** 系统,使用 **[Zypper 命令][10]** 安装 NodeJS & npm。
```
$ sudo zypper nodejs6
```
### 如何在 Linux 上安装 dcp
在安装好 NodeJS 后,使用下面的 npm 命令安装 dcp。
npm 是一个 JavaScript 的包管理。它是 JavaScript 的运行环境 Node.js 的默认包管理。
```
# npm i -g dat-cp
```
### 如何通过 dcp 发送文件?
在 dcp 命令后跟你想要传输的文件或者文件夹。而且无需注明目标机器的名字。
```
# dcp [File Name Which You Want To Transfer]
```
在你运行 dcp 命令时将会为传送的文件生成一个 dat 归档。一旦执行完成将会在页面底部生成一个公钥。
### 如何通过 dcp 接收文件
在远程服务器上输入公钥即可接收对应的文件或者文件夹。
```
# dcp [Public Key]
```
以递归形式复制目录。
```
# dcp [Folder Name Which You Want To Transfer] -r
```
下面这个例子我们将会传输单个文件。
![][12]
上述文件的输出。
![][13]
如果你想传输不止一个文件,使用下面的格式。
![][14]
上述文件的输出。
![][15]
递归复制文件夹。
![][16]
上述文件夹传输的输出。
![][17]
这种方式下你只能够下载一次文件或者文件夹,不可以多次下载。这也就意味着一旦你下载了这些文件或者文件夹,这个链接就会立即失效。
![][18]
也可以在手册页查看更多的相关选项。
```
# dcp --help
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/
作者:[Vinoth Kumar][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://www.2daygeek.com/author/vinoth/
[b]: https://github.com/lujun9972
[1]: https://www.2daygeek.com/onionshare-secure-way-to-share-files-sharing-tool-linux/
[2]: https://www.2daygeek.com/wormhole-securely-share-files-from-linux-command-line/
[3]: https://www.2daygeek.com/transfer-sh-easy-fast-way-share-files-over-internet-from-command-line/
[4]: https://github.com/tom-james-watson/dat-cp
[5]: https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
[6]: https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
[7]: https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
[8]: https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
[9]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
[10]: https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
[11]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[12]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-1.png
[13]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-2.png
[14]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-3.jpg
[15]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-4.jpg
[16]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-6.jpg
[17]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-7.jpg
[18]: https://www.2daygeek.com/wp-content/uploads/2019/01/Dcp-Dat-Copy-Easy-And-Secure-Way-To-Transfer-Files-Between-Linux-Systems-5.jpg