分类 技术 下的文章

以下提到的这些 Python 工具在编辑图像、操作图像底层数据方面都提供了简单直接的方法。

当今的世界充满了数据,而图像数据就是其中很重要的一部分。但只有经过处理和分析,提高图像的质量,从中提取出有效地信息,才能利用到这些图像数据。

常见的图像处理操作包括显示图像,基本的图像操作,如裁剪、翻转、旋转;图像的分割、分类、特征提取;图像恢复;以及图像识别等等。Python 作为一种日益风靡的科学编程语言,是这些图像处理操作的最佳选择。同时,在 Python 生态当中也有很多可以免费使用的优秀的图像处理工具。

下文将介绍 10 个可以用于图像处理任务的 Python 库,它们在编辑图像、查看图像底层数据方面都提供了简单直接的方法。

1、scikit-image

scikit-image 是一个结合 NumPy 数组使用的开源 Python 工具,它实现了可用于研究、教育、工业应用的算法和应用程序。即使是对于刚刚接触 Python 生态圈的新手来说,它也是一个在使用上足够简单的库。同时它的代码质量也很高,因为它是由一个活跃的志愿者社区开发的,并且通过了 同行评审 peer review

资源

scikit-image 的文档非常完善,其中包含了丰富的用例。

示例

可以通过导入 skimage 使用,大部分的功能都可以在它的子模块中找到。

图像滤波 image filtering

import matplotlib.pyplot as plt
%matplotlib inline

from skimage import data,filters

image = data.coins() # ... or any other NumPy array!
edges = filters.sobel(image)
plt.imshow(edges, cmap='gray')

 title=

使用 match\_template() 方法实现 模板匹配 template matching

 title=

展示页面可以看到更多相关的例子。

2、NumPy

NumPy 提供了对数组的支持,是 Python 编程的一个核心库。图像的本质其实也是一个包含像素数据点的标准 NumPy 数组,因此可以通过一些基本的 NumPy 操作(例如切片、 掩膜 mask 花式索引 fancy indexing 等),就可以从像素级别对图像进行编辑。通过 NumPy 数组存储的图像也可以被 skimage 加载并使用 matplotlib 显示。

资源

在 NumPy 的官方文档中提供了完整的代码文档和资源列表。

示例

使用 NumPy 对图像进行 掩膜 mask 操作:

import numpy as np
from skimage import data
import matplotlib.pyplot as plt
%matplotlib inline

image = data.camera()
type(image)
numpy.ndarray #Image is a NumPy array:

mask = image < 87
image[mask]=255
plt.imshow(image, cmap='gray')

 title=

3、SciPy

像 NumPy 一样,SciPy 是 Python 的一个核心科学计算模块,也可以用于图像的基本操作和处理。尤其是 SciPy v1.1.0 中的 scipy.ndimage 子模块,它提供了在 n 维 NumPy 数组上的运行的函数。SciPy 目前还提供了 线性和非线性滤波 linear and non-linear filtering 二值形态学 binary morphology B 样条插值 B-spline interpolation 对象测量 object measurements 等方面的函数。

资源

官方文档中可以查阅到 scipy.ndimage 的完整函数列表。

示例

使用 SciPy 的高斯滤波对图像进行模糊处理:

from scipy import misc,ndimage

face = misc.face()
blurred_face = ndimage.gaussian_filter(face, sigma=3)
very_blurred = ndimage.gaussian_filter(face, sigma=5)

#Results
plt.imshow(<image to be displayed>)

 title=

4、PIL/Pillow

PIL (Python Imaging Library) 是一个免费 Python 编程库,它提供了对多种格式图像文件的打开、编辑、保存的支持。但在 2009 年之后 PIL 就停止发布新版本了。幸运的是,还有一个 PIL 的积极开发的分支 Pillow,它的安装过程比 PIL 更加简单,支持大部分主流的操作系统,并且还支持 Python 3。Pillow 包含了图像的基础处理功能,包括像素点操作、使用内置卷积内核进行滤波、颜色空间转换等等。

资源

Pillow 的官方文档提供了 Pillow 的安装说明自己代码库中每一个模块的示例。

示例

使用 Pillow 中的 ImageFilter 模块实现图像增强:

from PIL import Image,ImageFilter
#Read image
im = Image.open('image.jpg')
#Display image
im.show()

from PIL import ImageEnhance
enh = ImageEnhance.Contrast(im)
enh.enhance(1.8).show("30% more contrast")

 title=

5、OpenCV-Python

OpenCV(Open Source Computer Vision 库)是计算机视觉领域最广泛使用的库之一,OpenCV-Python 则是 OpenCV 的 Python API。OpenCV-Python 的运行速度很快,这归功于它使用 C/C++ 编写的后台代码,同时由于它使用了 Python 进行封装,因此调用和部署的难度也不大。这些优点让 OpenCV-Python 成为了计算密集型计算机视觉应用程序的一个不错的选择。

资源

入门之前最好先阅读 OpenCV2-Python-Guide 这份文档。

示例

使用 OpenCV-Python 中的 金字塔融合 Pyramid Blending 将苹果和橘子融合到一起:

 title=

6、SimpleCV

SimpleCV 是一个开源的计算机视觉框架。它支持包括 OpenCV 在内的一些高性能计算机视觉库,同时不需要去了解 位深度 bit depth 、文件格式、 色彩空间 color space 之类的概念,因此 SimpleCV 的学习曲线要比 OpenCV 平缓得多,正如它的口号所说,“将计算机视觉变得更简单”。SimpleCV 的优点还有:

  • 即使是刚刚接触计算机视觉的程序员也可以通过 SimpleCV 来实现一些简易的计算机视觉测试
  • 录像、视频文件、图像、视频流都在支持范围内

资源

官方文档简单易懂,同时也附有大量的学习用例。

示例

 title=

7、Mahotas

Mahotas 是另一个 Python 图像处理和计算机视觉库。在图像处理方面,它支持滤波和形态学相关的操作;在计算机视觉方面,它也支持 特征计算 feature computation 兴趣点检测 interest point detection 局部描述符 local descriptors 等功能。Mahotas 的接口使用了 Python 进行编写,因此适合快速开发,而算法使用 C++ 实现,并针对速度进行了优化。Mahotas 尽可能做到代码量少和依赖项少,因此它的运算速度非常快。可以参考官方文档了解更多详细信息。

资源

文档包含了安装介绍、示例以及一些 Mahotas 的入门教程。

示例

Mahotas 力求使用少量的代码来实现功能。例如这个 Finding Wally 游戏:

 title=

 title=

8、SimpleITK

ITK(Insight Segmentation and Registration Toolkit)是一个为开发者提供普适性图像分析功能的开源、跨平台工具套件,SimpleITK 则是基于 ITK 构建出来的一个简化层,旨在促进 ITK 在快速原型设计、教育、解释语言中的应用。SimpleITK 作为一个图像分析工具包,它也带有大量的组件,可以支持常规的滤波、图像分割、 图像配准 registration 功能。尽管 SimpleITK 使用 C++ 编写,但它也支持包括 Python 在内的大部分编程语言。

资源

有很多 Jupyter Notebooks 用例可以展示 SimpleITK 在教育和科研领域中的应用,通过这些用例可以看到如何使用 Python 和 R 利用 SimpleITK 来实现交互式图像分析。

示例

使用 Python + SimpleITK 实现的 CT/MR 图像配准过程:

 title=

9、pgmagick

pgmagick 是使用 Python 封装的 GraphicsMagick 库。GraphicsMagick 通常被认为是图像处理界的瑞士军刀,因为它强大而又高效的工具包支持对多达 88 种主流格式图像文件的读写操作,包括 DPX、GIF、JPEG、JPEG-2000、PNG、PDF、PNM、TIFF 等等。

资源

pgmagick 的 GitHub 仓库中有相关的安装说明、依赖列表,以及详细的使用指引

示例

图像缩放:

 title=

边缘提取:

 title=

10、Pycairo

Cairo 是一个用于绘制矢量图的二维图形库,而 Pycairo 是用于 Cairo 的一组 Python 绑定。矢量图的优点在于做大小缩放的过程中不会丢失图像的清晰度。使用 Pycairo 可以在 Python 中调用 Cairo 的相关命令。

资源

Pycairo 的 GitHub 仓库提供了关于安装和使用的详细说明,以及一份简要介绍 Pycairo 的入门指南

示例

使用 Pycairo 绘制线段、基本图形、 径向渐变 radial gradients

 title=

总结

以上就是 Python 中的一些有用的图像处理库,无论你有没有听说过、有没有使用过,都值得试用一下并了解它们。


via: https://opensource.com/article/19/3/python-image-manipulation-tools

作者:Parul Pandey 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

一篇介绍如何在你的生活中和设备里去 Google 化的文章。

最近人们经常问我有关我手机的事情,比如安卓怎么安装,怎样绕过 Google Service 使用手机。好吧,这篇文章就来详细的解决那些问题。我尽可能让这篇文章适合初学者,因此我会慢慢介绍,一个一个来讲并且附上截图,你就能更好地看到它是怎样运作的。

首先我会告诉你为什么 Google Services(在我看来)对你的设备不好。我可以一言以概之,并让你看 Richard Stallman 写的这篇文章,但我决定抓住几个要点附在这。

  • 要用 非自由软件 Nonfree software

    • 大体上,大多数 Google Services 需要运行在非自由的 Javascript 代码之上。现如今,如果禁用掉 Javascript,什么都没有了,甚至 Google 帐号都需要运行非自由软件(由站点发送的 JavaScript),对于登录也是。
  • 被监视

    • Google 悄悄地把它的 广告跟踪方式 ad-tracking profiles 与浏览方式结合在一起,并存储了每个用户的大量数据。
  • 服务条款

    • Google 会终止转卖了 Pixel 手机的用户账户。他们无法访问帐户下保存在 Google Services 中的所有邮件和文档。
  • 审查

    • Amazon 和 Google 切断了 域前置 domain-fronting ,该技术能使身处某些国家的人们访问到在那里禁止的通信系统。
    • Google 已经同意为巴基斯坦政府执行特殊的 Youtube 审查,删除对立观点。这将有助于压制异议。
    • Youtube 的“content ID”会自动删除已发布的视频,这并不包含在版权法中。

这只是几个原因,你可以阅读上面我提到的 RMS 的文章,他详细解释了这几点。尽管听起来骇人听闻,但这些行为在现实生活中已经每天在发生。

下一步,我的搭建教程

我有一款小米红米 Note 5 Pro 智能手机(代号 whyred),生产于中国的小米。它是 4 个月之前(距写这篇文章的时候)我花了大约 185 欧元买的。

现在你也许会想,“但你为什么买中国品牌,他们不可靠”。是的,它不是通常你所期望的(品牌)所生产的,例如三星(人们通常会将它和安卓联系在一起,这显然是错的)、一加、诺基亚等。但你应当知道几乎所有的手机都生产于中国。

我选择这款手机有几个原因,首先当然是价格。它是一款 性价比 budget-friendly 相当高的产品,大多数人都能买得起。下一个原因是说明书上的规格(不仅仅是),在这个 价位 price tag 上相当合适。拥有 6 英尺屏幕( 全高清分辨率 Full HD resolution ),4000 毫安电池(一流的电池寿命),4GB RAM,64GB 存储,双后摄像头(12 MP + 5 MP),一个带闪光灯的前摄像头(13 MP)和一个高性能的 骁龙 Snapdragon 636,它可能是那时候最好的选择。

随之而来的问题是 MIUI,大多数小米设备所附带的安卓外壳(除了 Android One 项目设备)。是的,它没有那么可怕,它有一些额外的功能,但问题在更深的地方。小米设备如此便宜(据我所知销售利润仅有 5-10%)的一个原因是他们在系统里伴随 MIUI 添加了数据挖掘和广告。这样的话,系统应用需要额外不必要的权限来获取你的数据并且进行广告轰炸,从中获取利润。

更有趣的是,所包含的“天气”应用想要访问我的联系人并且拨打电话,如果它仅是显示天气的话为什么需要访问联系人呢。另一个例子是“录音机”应用,它也需要联系人和网络权限,可能想把录音发送回小米。

为了解决它,我不得不格式化手机并且摆脱 MIUI。在市场上近来的手机上这就变得极为艰难。

格式化手机的想法很简单,删除掉现有的系统然后安装一个新的喜欢的系统(这次是原生安卓)。为了实现它,你先得解锁 bootloader

bootloader 是一个在计算机完成自检后为其加载操作系统或者运行环境的计算机程序。—维基百科

问题是小米关于解锁 bootloader 有明确的政策。几个月之前,流程就像这样:你需向小米申请解锁代码,并提供真实的原因,但不是每次都成功,因为他们可以拒绝你的请求并且不提供理由。

现在,流程变了。你要从小米那下载一个软件,叫做 Mi Unlock,在 Windows 电脑上安装它,在手机的开发者模式中打开调试选项,重启到 bootloader 模式(关机状态下长按向下音量键 + 电源键)并将手机连接到电脑上,开始一个叫做“许可”的流程。这个过程会在小米的服务器上启动一个定时器,允许你在 15 天之后解锁手机(在一些少数情况下或者一个月,完全随机)。

15 天过去后,重新连接手机并重复之前的步骤,这时候按下解锁键,你的 bootloader 就会解锁,并且能够安装其他 ROM(系统)。注意,确保你已经备份好了数据,因为解锁 bootloader 会清空手机。

下一步就是找一个兼容的系统(ROM)。我在 XDA 开发者论坛上找了个遍,它是 Android 开发者和用户们交流想法、应用等东西的地方。幸运的是,我的手机相当流行,因此论坛上有它专门的版块。在那儿,我略过一些流行的 ROM 并决定使用 AOSiP ROM。(AOSiP 代表 安卓开源 illusion 项目 Android Open Source illusion Project

校订:有人发邮件告诉我说文章里写的就是/e/的目的与所做的事情。我想说谢谢你的帮助,但完全不是这样。我关于 /e/ 的看法背后的原因可以见此网站,但我仍会在此列出一些原因。

eelo 是一个从 Kickstarter 和 IndieGoGo 上集资并超过 200K € 的“基金会”,承诺创造一个开放、安全且保护隐私的移动 OS 和网页服务器。

  1. 他们的 OS 基于 LineageOS 14.1 (Android 7.1) 且搭载 microG 和其他开源应用,此系统已经存在很长一段时间了并且现在叫做 Lineage for microG
  2. 所有的应用程序并非从源代码构建,而是从 APKPure 上下载安装包并推送进 ROM,不知道那些安装包中是否包含 专有代码 proprietary code 恶意软件 malware
  3. 有一段时间,它们就那样随意地从代码中删除 Lineage 的 版权标头 copyright header 并加入自己的。
  4. 他们喜欢删除负面反馈并且监视用户 Telegram 群聊中的舆论。

总而言之,我不建议使用 /e/ ROM。(至少现在)

另一件你有可能要做的事情是获取手机的 root 权限,让它真正的成为你的手机,并且修改系统中的文件,例如使用系统范围的 adblocker 等。为了实现它,我决定使用 Magisk,一个天赐的应用,它由一个学生开发,可以帮你获取设备的 root 权限并安装一种叫做模块的东西,基本上是软件。

下载 ROM 和 Magisk 之后,我得在手机上安装它们。为了完成安装,我将文件移动到了 SD 卡上。现在,若要安装系统,我需要使用 恢复系统。我用的是较为普遍的 TWRP(代表 TeamWin Recovery Project)。

要安装恢复系统(听起来有点难,我知道),我需要将文件烧录进手机。为了完成烧录,我将手机用一个叫做 ADB 的工具连接上电脑(Fedora Linux 系统)。使用命令让自己定制的恢复系统覆盖掉原先的。

fastboot flash recovery twrp.img

完成之后,我关掉手机并按住音量上和电源键,直到 TWRP 界面显示。这意味着我进行顺利,并且它已经准备好接收我的指令。

下一步是发送擦除命令,在你第一次为手机安装自定义 ROM 时是必要的。如上图所示,擦除命令会清除掉 数据 Data 缓存 Cache 和 Dalvik 。(这里也有高级选项让我们可以勾选以删除掉系统,如果我们不再需要旧系统的话)

这需要几分钟去完成,之后,你的手机基本上就干净了。现在是时候安装系统了。通过按下主屏幕上的安装按钮,我们选择之前添加进的 zip 文件(ROM 文件)并滑动屏幕安装它。下一步,我们需要安装 Magisk,它可以给我们访问设备的 root 权限。

校订:一些有经验的安卓用户或发烧友也许注意到了,手机上不包含 [GApps](谷歌应用)。这在安卓世界里称之为 GApps-less,一个 GAps 应用也不安装。

注意有一个不好之处在于若不安装 Google Services 有的应用无法正常工作,例如它们的通知也许会花更长的时间到达或者根本不起作用。(对我来说这一点是最影响应用程序使用的)原因是这些应用使用了 Google Cloud Messaging(现在叫做 Firebase)唤醒手机并推送通知。

你可以通过安装使用 microG(部分地)解决它,microG 提供一些 Google Services 的特性且允许你拥有更多的控制。我不建议使用它,因为它仍然有助于 Google Services 并且你不一定信任它。但是,如果你没法 立刻放弃使用 go cold turkey on it ,只想慢慢地退出谷歌,这便是一个好的开始。

都成功地安装之后,现在我们重启手机,就进入了主屏幕。

下一个部分,安装应用并配置一切

事情开始变得简单了。为了安装应用,我使用了 F-Droid,一个可替代的应用商店,里面只包含自由及开源应用。如果这里没有你要的应用,你可以使用 Aurora Store,一个从应用商店里下载应用且不需要使用谷歌帐号或被追踪的客户端。

F-Droid 里面有名为 repos 的东西,它是一个包含你可以安装应用的“仓库”。我使用默认的仓库,并从 IzzyOnDroid 添加了另一个,它有更多默认仓库中没有的应用,并且它更新地更频繁。

从下面你可以发现我所安装的应用清单,它们替代的应用与用途。

  • AdAway > 系统广告拦截器,使用 hosts 文件拦截所有的广告
  • AfWall+ > 一个防火墙,可以阻止不想要的连接
  • Amaze > 替代系统的文件管理器,允许文件的 root 访问权限,并且拥有 zip/unzip 功能
  • Ameixa > 大多数应用的图标包
  • andOTP > 替代谷歌验证器/Authy,一个可以用来登录启用了 双因子验证 2FA 的网站账户的 TOTP 应用,可以使用 PIN 码备份和锁定
  • AnySoftKeyboard/AOSP Keyboard > 开源键盘,它有许多主题和语言包,我也是该项目的一员
  • Audio Recorder > 如其名字,允许你从麦克风录制不同格式的音频文件
  • Battery Charge Limit > 当到 80% 时自动停止充电,降低 电池磨损 battery wear 并增加寿命
  • DAVx5 > 这是我最常用的应用之一,对我来说它基本上替代了谷歌联系人、谷歌日历和谷歌 Tasks,它连接着我的 Nextcloud 环境可以让我完全控制自己的数据
  • Document Viewer > 一个可以打开数百种文件格式的查看器应用,快速、轻量
  • Deezloader Remix > 让我可以在 Deezer 上下载高质量 MP3 的应用
  • Easy xkcd > xkcd 漫画阅读器,我喜欢这些 xkcd 漫画
  • Etar > 日历应用,替代谷歌日历,与 DAVx5 一同工作
  • FastHub-Libre > 一个 GitHub 客户端,完全 FOSS(自由及开源软件),非常实用如果你像我一样喜欢使用 Github 的话
  • Fennec F-Droid > 替代谷歌 Chrome 和其他类似的应用,一个为 F-Droid 打造的火狐浏览器,不含专有二进制代码并允许安装扩展提升浏览体验
  • Gadgetbridge > 替代小米运动,可以用来配对小米硬件的应用,追踪你的健康、步数、睡眠等。
  • K-9 Mail > 邮件客户端,替代 GMail 应用,可定制并可以添加多个账户
  • Lawnchair > 启动器,可以替代 Nova Launcher 或 Pixel Launcher,允许自定义和各种改变,也支持图标包
  • Mattermost > 可以连接 Mattermost 服务器的应用。Mattermost 是一个 Slack 替代品
  • NewPipe > 最好的 YouTube 客户端(我认为),可以替代 YoubTube,它完全是 FOSS,免除 YouTube 广告,占用更少空间,允许背景播放,允许下载视频/音频等。试一试吧
  • Nextcloud SMS > 允许备份/同步 SMS 到我的 Nextcloud 环境
  • Nextcloud Notes > 允许我创建,修改,删除,分享笔记并同步/备份到 Nextcloud 环境
  • OpenTasks > 允许我创建、修改、删除任务并同步到我的 Nextcloud 环境
  • OsmAnd~ > 一个地图应用,使用 OpenStreetMap,允许下载离线地图和导航
  • QKSMS > 我最喜欢的短信应用,可以替代原来的 Messaging 应用,拥有漂亮的界面,拥有备份、个性化、延迟发送等特性。
  • Resplash/Mysplash > 允许你无限地从 Unsplash 下载无数的漂亮壁纸,全都可以免费使用和修改。
  • ScreenCam > 一个录屏工具,允许各样的自定义和录制模式,没有广告并且免费
  • SecScanQR > 二维码识别应用,快速轻量
  • Send Reduced Free > 这个应用可以在发送之前通过移除 PII( 个人识别信息 personally identifiable information )和减小尺寸,让你立即分享大图
  • Slide > 开源 Reddit 客户端
  • Telegram FOSS > 没有追踪和 Google Services 的纯净版 Telegram 安卓客户端
  • TrebleShot > 这个天才般的应用可以让你通过 WIFI 分享文件给其它设备,真的超快,甚至无需连接网络
  • Tusky > Tusky 是 Mastodon 平台的客户端(替代 Twitter)
  • Unit Converter Ultimate > 这款应用可以一键在 200 种单位之间来回转换,非常快并且完全离线
  • Vinyl Music Player > 我首选的音乐播放器,可以替代谷歌音乐播放器或其他你已经安装的音乐播放器,它有漂亮的界面和许多特性
  • VPN Hotspot > 这款应用可以让我打开热点的时候分享 VPN,因此我可以在笔记本上什么都不用做就可以安全地浏览网页

这些差不多就是我列出的一张最实用的 F-Droid 应用清单,但不巧,这些并不是所有应用。我使用的专有应用如下(我知道,我也许听起来是一个伪君子,但并不是所有的应用都可以替代,至少现在不是):

  • Google Camera(与 Camera API 2 结合起来,需要 F-Droid 的基本的 microG 才能工作)
  • Instagram
  • MyVodafoneAL (运营商应用)
  • ProtonMail (email 应用)
  • Titanium Backup(备份应用数据,wifi 密码,通话记录等)
  • WhatsApp (专有的端到端聊天应用,几乎我认识的所有人都有它)

差不多就是这样,这就是我用的手机上所有的应用。配置非常简单明了,我可以给几点提示

  1. 仔细阅读和检查应用的权限,不要无脑地点“安装”。
  2. 尽可能多地使用开源应用,它们即尊重你的隐私又是免费的(且自由)。
  3. 尽可能地使用 VPN,找一个有名气的,别用免费的,否则你将被收割数据然后成为产品。
  4. 不要一直打开 WIFI/移动数据/定位,有可能引起安全隐患。
  5. 不要只依赖指纹解锁,或者尽可能只用 PIN/密码/模式解锁,因为生物数据可以被克隆后针对你,例如解锁你的手机盗取你的数据。

作为坚持读到这儿的奖励,一张主屏幕的截图奉上。


via: https://lushka.al/my-android-setup/

作者:Anxhelo Lushka 选题:lujun9972 译者:LuuMing 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

欢迎进入输入课程系列。在本系列,你将会学会如何使用键盘接收输入给树莓派。我们将会从揭示输入开始本课,然后转向更传统的文本提示符。

这是第一堂输入课,会教授一些关于驱动和链接的理论,同样也包含键盘的知识,最后以在屏幕上显示文本结束。

1、开始

希望你已经完成了 OK 系列课程,这会对你完成屏幕系列课程很有帮助。很多 OK 课程上的文件会被使用而不会做解释。如果你没有这些文件,或者希望使用一个正确的实现,可以从该堂课的下载页下载模板。如果你使用你自己的实现,请删除调用了 SetGraphicsAddress 之后全部的代码。

2、USB

如你所知,树莓派 B 型有两个 USB 接口,通常用来连接一个鼠标和一个键盘。这是一个非常好的设计决策,USB 是一个非常通用的接口,很多种设备都可以使用它。这就很容易为它设计新外设,很容易为它编写设备驱动,而且通过 USB 集线器可以非常容易扩展。还能更好吗?当然是不能,实际上对一个操作系统开发者来说,这就是我们的噩梦。USB 标准太大了。我是说真的,在你思考如何连接设备之前,它的文档将近 700 页。

USB 标准的设计目的是通过复杂的软件来简化硬件交互。

我和很多爱好操作系统的开发者谈过这些,而他们全部都说几句话:不要抱怨。“实现这个需要花费很久时间”,“你不可能写出关于 USB 的教程”,“收益太小了”。在很多方面,他们是对的,我不可能写出一个关于 USB 标准的教程,那得花费几周时间。我同样不能教授如何为全部所有的设备编写外设驱动,所以使用自己写的驱动是没什么用的。然而,即便不能做到最好,我仍然可以获取一个正常工作的 USB 驱动,拿一个键盘驱动,然后教授如何在操作系统中使用它们。我开始寻找可以运行在一个甚至不知道文件是什么的操作系统的自由驱动,但是我一个都找不到,它们都太高层了,所以我尝试写一个。大家说的都对,这耗费了我几周时间。然而我可以高兴的说我做的这些工作没有获取操作系统以外的帮助,并且可以和鼠标和键盘通信。这绝不是完整的、高效的,或者正确的,但是它能工作。驱动是以 C 编写的,而且有兴趣的可以在下载页找到全部源代码。

所以,这一个教程不会是 USB 标准的课程(一点也没有)。实际上我们将会看到如何使用其他人的代码。

3、链接

既然我们要引进外部代码到操作系统,我们就需要谈一谈 链接 linking 。链接是一种过程,可以在程序或者操作系统中链接函数。这意味着当一个程序生成之后,我们不必要编写每一个函数(几乎可以肯定,实际上并非如此)。链接就是我们做的用来把我们程序和别人代码中的函数连结在一起。这个实际上已经在我们的操作系统进行了,因为链接器把所有不同的文件链接在一起,每个都是分开编译的。

链接允许我们制作可重用的代码库,所有人都可以在他们的程序中使用。

有两种链接方式:静态和动态。静态链接就像我们在制作自己的操作系统时进行的。链接器找到全部函数的地址,然后在链接结束前,将这些地址都写入代码中。动态链接是在程序“完成”之后。当程序加载后,动态链接器检查程序,然后在操作系统的库找到所有不在程序里的函数。这就是我们的操作系统最终应该能够完成的一项工作,但是现在所有东西都将是静态链接的。

程序经常调用调用库,这些库会调用其它的库,直到最终调用了我们写的操作系统的库。

我编写的 USB 驱动程序适合静态编译。这意味着我给你的是每个文件的编译后的代码,然后链接器找到你的代码中的那些没有实现的函数,就将这些函数链接到我的代码。在本课的 下载页 是一个 makefile 和我的 USB 驱动,这是接下来需要的。下载并使用这个 makefile 替换你的代码中的 makefile, 同事将驱动放在和这个 makefile 相同的文件夹。

4、键盘

为了将输入传给我们的操作系统,我们需要在某种程度上理解键盘是如何实际工作的。键盘有两种按键:普通键和修饰键。普通按键是字母、数字、功能键,等等。它们构成了键盘上几乎全部按键。修饰键是多达 8 个的特殊键。它们是左 shift、右 shift、左 ctrl、右 ctrl、左 alt、右 alt、左 GUI 和右 GUI。键盘可以检测出所有的组合中那个修饰键被按下了,以及最多 6 个普通键。每次一个按钮变化了(例如,是按下了还是释放了),键盘就会报告给电脑。通常,键盘也会有 3 个 LED 灯,分别指示大写锁定,数字键锁定,和滚动锁定,这些都是由电脑控制的,而不是键盘自己。键盘也可能有更多的灯,比如电源、静音,等等。

对于标准 USB 键盘,有一个按键值的表,每个键盘按键都一个唯一的数字,每个可能的 LED 也类似。下面的表格列出了前 126 个值。

表 4.1 USB 键盘值

序号描述序号描述序号描述序号描述
4aA5bB6cC7dD
8eE9fF10gG11hH
12iI13jJ14kK15lL
16mM17nN18oO19pP
20qQ21rR22sS23tT
24uU25vV26wW27xX
28yY29zZ301!312@
323#334$345%356^
367&378*389(390)
40ReturnEnter41Escape42DeleteBackspace43Tab
44Spacebar45-_46=+47[{
48]}49\ 和 ``50#~51;:
52'"53`~54,<55.>
56/?57Caps Lock58F159F2
60F361F462F563F6
64F765F866F967F10
68F1169F1270Print Screen71Scroll Lock
72Pause73Insert74Home75Page Up
76Delete forward77End78Page Down79Right Arrow
80Left Arrow81Down Arrow82Up Arrow83Num Lock
84小键盘 /85小键盘 *86小键盘 -87小键盘 +
88小键盘 Enter89小键盘 1End90小键盘 2Down Arrow91小键盘 3Page Down
92小键盘 4Left Arrow93小键盘 594小键盘 6Right Arrow95小键盘 7Home
96小键盘 8Up Arrow97小键盘 9Page Up98小键盘 0Insert99小键盘 .Delete
100\ 和 ``101Application102Power103小键盘 =
104F13105F14106F15107F16
108F17109F18110F19111F20
112F21113F22114F23115F24
116Execute117Help118Menu119Select
120Stop121Again122Undo123Cut
124Copy125Paste126Find127Mute
128Volume Up129Volume Down

完全列表可以在HID 页表 1.12的 53 页,第 10 节找到。

5、车轮后的螺母

通常,当你使用其他人的代码,他们会提供一份自己代码的总结,描述代码都做了什么,粗略介绍了是如何工作的,以及什么情况下会出错。下面是一个使用我的 USB 驱动的相关步骤要求。

这些总结和代码的描述组成了一个 API - 应用程序产品接口。

表 5.1 CSUD 中和键盘相关的函数

函数参数返回值描述
UsbInitialiser0 是结果码这个方法是一个集多种功能于一身的方法,它加载 USB 驱动程序,枚举所有设备并尝试与它们通信。这种方法通常需要大约一秒钟的时间来执行,但是如果插入几个 USB 集线器,执行时间会明显更长。在此方法完成之后,键盘驱动程序中的方法就可用了,不管是否确实插入了键盘。返回代码如下解释。
UsbCheckForChange本质上提供与 UsbInitialise 相同的效果,但不提供相同的一次初始化。该方法递归地检查每个连接的集线器上的每个端口,如果已经添加了新设备,则添加它们。如果没有更改,这应该是非常快的,但是如果连接了多个设备的集线器,则可能需要几秒钟的时间。
KeyboardCountr0 是计数返回当前连接并检测到的键盘数量。UsbCheckForChange 可能会对此进行更新。默认情况下最多支持 4 个键盘。可以通过这个驱动程序访问多达这么多的键盘。
KeyboardGetAddressr0 是索引r0 是地址检索给定键盘的地址。所有其他函数都需要一个键盘地址,以便知道要访问哪个键盘。因此,要与键盘通信,首先要检查计数,然后检索地址,然后使用其他方法。注意,在调用 UsbCheckForChange 之后,此方法返回的键盘顺序可能会改变。
KeyboardPollr0 是地址r0 是结果码从键盘读取当前键状态。这是通过直接轮询设备来操作的,与最佳实践相反。这意味着,如果没有频繁地调用此方法,可能会错过一个按键。所有读取方法只返回上次轮询时的值。
KeyboardGetModifiersr0 是地址r0 是修饰键状态检索上次轮询时修饰键的状态。这是两边的 shift 键、alt 键和 GUI 键。这回作为一个位字段返回,这样,位 0 中的 1 表示左控件被保留,位 1 表示左 shift,位 2 表示左 alt ,位 3 表示左 GUI,位 4 到 7 表示前面几个键的右版本。如果有问题,r0 包含 0。
KeyboardGetKeyDownCountr0 是地址r0 是计数检索当前按下键盘的键数。这排除了修饰键。这通常不能超过 6。如果有错误,这个方法返回 0。
KeyboardGetKeyDownr0 是地址,r1 键号r0 是扫描码检索特定按下键的扫描码(见表 4.1)。通常,要计算出哪些键是按下的,可以调用 KeyboardGetKeyDownCount,然后多次调用 KeyboardGetKeyDown ,将 r1 的值递增,以确定哪些键是按下的。如果有问题,返回 0。可以(但不建议这样做)在不调用 KeyboardGetKeyDownCount 的情况下调用此方法将 0 解释为没有按下的键。注意,顺序或扫描代码可以随机更改(有些键盘按数字排序,有些键盘按时间排序,没有任何保证)。
KeyboardGetKeyIsDownr0 是地址,r1 扫描码r0 是状态除了 KeyboardGetKeyDown 之外,还可以检查按下的键中是否有特定的扫描码。如果没有,返回 0;如果有,返回一个非零值。当检测特定的扫描码(例如寻找 ctrl+c)时更快。出错时,返回 0。
KeyboardGetLedSupportr0 是地址r0 是 LED检查特定键盘支持哪些 LED。第 0 位代表数字锁定,第 1 位代表大写锁定,第 2 位代表滚动锁定,第 3 位代表合成,第 4 位代表假名,第 5 位代表电源,第 6 位代表 Shift ,第 7 位代表静音。根据 USB 标准,这些 LED 都不是自动更新的(例如,当检测到大写锁定扫描代码时,必须手动设置大写锁定 LED)。
KeyboardSetLedsr0 是地址, r1 是 LEDr0 是结果码试图打开/关闭键盘上指定的 LED 灯。查看下面的结果代码值。参见 KeyboardGetLedSupport 获取 LED 的值。

有几种方法返回“返回值”。这些都是 C 代码的老生常谈了,就是用数字代表函数调用发生了什么。通常情况, 0 总是代表操作成功。下面的是驱动用到的返回值。

返回值是一种处理错误的简单方法,但是通常更优雅的解决途径会出现于更高层次的代码。

表 5.2 - CSUD 返回值

代码描述
0方法成功完成。
-2参数:函数调用了无效参数。
-4设备:设备没有正确响应请求。
-5不匹配:驱动不适用于这个请求或者设备。
-6编译器:驱动没有正确编译,或者被破坏了。
-7内存:驱动用尽了内存。
-8超时:设备没有在预期的时间内响应请求。
-9断开连接:被请求的设备断开连接,或者不能使用。

驱动的通常用法如下:

  1. 调用 UsbInitialise
  2. 调用 UsbCheckForChange
  3. 调用 KeyboardCount
  4. 如果返回 0,重复步骤 2。
  5. 针对你支持的每个键盘:

    1. 调用 KeyboardGetAddress
    2. 调用 KeybordGetKeyDownCount
    3. 针对每个按下的按键:

      1. 检查它是否已经被按下了
      2. 保存按下的按键
    4. 针对每个保存的按键:

      1. 检查按键是否被释放了
      2. 如果释放了就删除
  6. 根据按下/释放的案件执行操作
  7. 重复步骤 2

最后,你可以对键盘做所有你想做的任何事了,而这些方法应该允许你访问键盘的全部功能。在接下来的两节课,我们将会着眼于完成文本终端的输入部分,类似于大部分的命令行电脑,以及命令的解释。为了做这些,我们将需要在更有用的形式下得到一个键盘输入。你可能注意到我的驱动是(故意的)没有太大帮助,因为它并没有方法来判断是否一个按键刚刚按下或释放了,它只有方法来判断当前那个按键是按下的。这就意味着我们需要自己编写这些方法。

6、可用更新

首先,让我们实现一个 KeyboardUpdate 方法,检查第一个键盘,并使用轮询方法来获取当前的输入,以及保存最后一个输入来对比。然后我们可以使用这个数据和其它方法来将扫描码转换成按键。这个方法应该按照下面的说明准确操作:

重复检查更新被称为“轮询”。这是针对驱动 IO 中断而言的,这种情况下设备在准备好后会发一个信号。
  1. 提取一个保存好的键盘地址(初始值为 0)。
  2. 如果不是 0 ,进入步骤 9.
  3. 调用 UsbCheckForChange 检测新键盘。
  4. 调用 KeyboardCount 检测有几个键盘在线。
  5. 如果返回 0,意味着没有键盘可以让我们操作,只能退出了。
  6. 调用 KeyboardGetAddress 参数是 0,获取第一个键盘的地址。
  7. 保存这个地址。
  8. 如果这个值是 0,那么退出,这里应该有些问题。
  9. 调用 KeyboardGetKeyDown 6 次,获取每次按键按下的值并保存。
  10. 调用 KeyboardPoll
  11. 如果返回值非 0,进入步骤 3。这里应该有些问题(比如键盘断开连接)。

要保存上面提到的值,我们将需要下面 .data 段的值。

.section .data
.align 2
KeyboardAddress:
.int 0
KeyboardOldDown:
.rept 6
.hword 0
.endr
.hword num 直接将半字的常数插入文件。
.rept num [commands] .endr 复制 `commands` 命令到输出 num 次。

试着自己实现这个方法。对此,我的实现如下:

1、我们加载键盘的地址。

.section .text
.globl KeyboardUpdate
KeyboardUpdate:
push {r4,r5,lr}

kbd .req r4
ldr r0,=KeyboardAddress
ldr kbd,[r0]

2、如果地址非 0,就说明我们有一个键盘。调用 UsbCheckForChanges 慢,所以如果一切正常,我们要避免调用这个函数。

teq kbd,#0
bne haveKeyboard$

3、如果我们一个键盘都没有,我们就必须检查新设备。

getKeyboard$:
bl UsbCheckForChange

4、如果有新键盘添加,我们就会看到这个。

bl KeyboardCount

5、如果没有键盘,我们就没有键盘地址。

teq r0,#0
ldreq r1,=KeyboardAddress
streq r0,[r1]
beq return$

6、让我们获取第一个键盘的地址。你可能想要支持更多键盘。

mov r0,#0
bl KeyboardGetAddress

7、保存键盘地址。

ldr r1,=KeyboardAddress
str r0,[r1]

8、如果我们没有键盘地址,这里就没有其它活要做了。

teq r0,#0
beq return$
mov kbd,r0

9、循环查询全部按键,在 KeyboardOldDown 保存下来。如果我们询问的太多了,返回 0 也是正确的。

saveKeys$:
  mov r0,kbd
  mov r1,r5
  bl KeyboardGetKeyDown
  
  ldr r1,=KeyboardOldDown
  add r1,r5,lsl #1
  strh r0,[r1]
  add r5,#1
  cmp r5,#6
  blt saveKeys$

10、现在我们得到了新的按键。

mov r0,kbd
bl KeyboardPoll

11、最后我们要检查 KeyboardOldDown 是否工作了。如果没工作,那么我们可能是断开连接了。

teq r0,#0
bne getKeyboard$

return$:
pop {r4,r5,pc}
.unreq kbd

有了我们新的 KeyboardUpdate 方法,检查输入变得简单,固定周期调用这个方法就行,而它甚至可以检查键盘是否断开连接,等等。这是一个有用的方法,因为我们实际的按键处理会根据条件不同而有所差别,所以能够用一个函数调以它的原始方式获取当前的输入是可行的。下一个方法我们希望它是 KeyboardGetChar,简单的返回下一个按下的按钮的 ASCII 字符,或者如果没有按键按下就返回 0。这可以扩展到支持如果它按下一个特定时间当做多次按下按键,也支持锁定键和修饰键。

如果我们有一个 KeyWasDown 方法可以使这个方法有用起来,如果给定的扫描代码不在 KeyboardOldDown 值中,它只返回 0,否则返回一个非零值。你可以自己尝试一下。与往常一样,可以在下载页面找到解决方案。

7、查找表

KeyboardGetChar 方法如果写得不好,可能会非常复杂。有 100 多种扫描码,每种代码都有不同的效果,这取决于 shift 键或其他修饰符的存在与否。并不是所有的键都可以转换成一个字符。对于一些字符,多个键可以生成相同的字符。在有如此多可能性的情况下,一个有用的技巧是查找表。查找表与物理意义上的查找表非常相似,它是一个值及其结果的表。对于一些有限的函数,推导出答案的最简单方法就是预先计算每个答案,然后通过检索返回正确的答案。在这种情况下,我们可以在内存中建立一个序列的值,序列中第 n 个值就是扫描代码 n 的 ASCII 字符代码。这意味着如果一个键被按下,我们的方法只需要检测到,然后从表中检索它的值。此外,我们可以为当按住 shift 键时的值单独创建一个表,这样按下 shift 键就可以简单地换个我们用的表。

在编程的许多领域,程序越大,速度越快。查找表很大,但是速度很快。有些问题可以通过查找表和普通函数的组合来解决。

.section .data 命令之后,复制下面的表:

.align 3
KeysNormal:
    .byte 0x0, 0x0, 0x0, 0x0, 'a', 'b', 'c', 'd'
    .byte 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'
    .byte 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'
    .byte 'u', 'v', 'w', 'x', 'y', 'z', '1', '2'
    .byte '3', '4', '5', '6', '7', '8', '9', '0'
    .byte '\n', 0x0, '\b', '\t', ' ', '-', '=', '['
    .byte ']', '\\\', '#', ';', '\'', '`', ',', '.'
    .byte '/', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+'
    .byte '\n', '1', '2', '3', '4', '5', '6', '7'
    .byte '8', '9', '0', '.', '\\\', 0x0, 0x0, '='

.align 3
KeysShift:
    .byte 0x0, 0x0, 0x0, 0x0, 'A', 'B', 'C', 'D'
    .byte 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'
    .byte 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'
    .byte 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '"'
    .byte '£', '$', '%', '^', '&', '*', '(', ')'
    .byte '\n', 0x0, '\b', '\t', ' ', '_', '+', '{'
    .byte '}', '|', '~', ':', '@', '¬', '<', '>'
    .byte '?', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
    .byte 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+'
    .byte '\n', '1', '2', '3', '4', '5', '6', '7'
    .byte '8', '9', '0', '.', '|', 0x0, 0x0, '='

这些表直接将前 104 个扫描码映射到 ASCII 字符作为一个字节表。我们还有一个单独的表来描述 shift 键对这些扫描码的影响。我使用 ASCII null 字符(0)表示所有没有直接映射的 ASCII 键(例如功能键)。退格映射到 ASCII 退格字符(8 表示 \b),enter 映射到 ASCII 新行字符(10 表示 \n), tab 映射到 ASCII 水平制表符(9 表示 \t)。

.byte num 直接插入字节常量 num 到文件。

.

大部分的汇编器和编译器识别转义序列;如 \t 这样的字符序列会插入该特殊字符。

KeyboardGetChar 方法需要做以下工作:

  1. 检查 KeyboardAddress 是否返回 0。如果是,则返回 0。
  2. 调用 KeyboardGetKeyDown 最多 6 次。每次:

    1. 如果按键是 0,跳出循环。
    2. 调用 KeyWasDown。 如果返回是,处理下一个按键。
    3. 如果扫描码超过 103,进入下一个按键。
    4. 调用 KeyboardGetModifiers
    5. 如果 shift 是被按着的,就加载 KeysShift 的地址,否则加载 KeysNormal 的地址。
    6. 从表中读出 ASCII 码值。
    7. 如果是 0,进行下一个按键,否则返回 ASCII 码值并退出。
  3. 返回 0。

试着自己实现。我的实现展示在下面:

1、简单的检查我们是否有键盘。

.globl KeyboardGetChar
KeyboardGetChar:
ldr r0,=KeyboardAddress
ldr r1,[r0]
teq r1,#0
moveq r0,#0
moveq pc,lr

2、r5 将会保存按键的索引,r4 保存键盘的地址。

push {r4,r5,r6,lr}
kbd .req r4
key .req r6
mov r4,r1
mov r5,#0
keyLoop$:
  mov r0,kbd
  mov r1,r5
  bl KeyboardGetKeyDown

2.1、 如果扫描码是 0,它要么意味着有错,要么说明没有更多按键了。

teq r0,#0
beq keyLoopBreak$

2.2、如果按键已经按下了,那么他就没意义了,我们只想知道按下的按键。

mov key,r0
bl KeyWasDown
teq r0,#0
bne keyLoopContinue$

2.3、如果一个按键有个超过 104 的扫描码,它将会超出我们的表,所以它是无关的按键。

cmp key,#104
bge keyLoopContinue$

2.4、我们需要知道修饰键来推断字符。

mov r0,kbd
bl KeyboardGetModifiers

2.5、当将字符更改为其 shift 变体时,我们要同时检测左 shift 键和右 shift 键。记住,tst 指令计算的是逻辑和,然后将其与 0 进行比较,所以当且仅当移位位都为 0 时,它才等于 0。

tst r0,#0b00100010
ldreq r0,=KeysNormal
ldrne r0,=KeysShift

2.6、现在我们可以从查找表加载按键了。

ldrb r0,[r0,key]

2.7、如果查找码包含一个 0,我们必须继续。为了继续,我们要增加索引,并检查是否到 6 次了。

teq r0,#0
bne keyboardGetCharReturn$
keyLoopContinue$:
add r5,#1
cmp r5,#6
blt keyLoop$

3、在这里我们返回我们的按键,如果我们到达 keyLoopBreak$ ,然后我们就知道这里没有按键被握住,所以返回 0。

keyLoopBreak$:
mov r0,#0
keyboardGetCharReturn$:
pop {r4,r5,r6,pc}
.unreq kbd
.unreq key

8、记事本操作系统

现在我们有了 KeyboardGetChar 方法,可以创建一个操作系统,只打印出用户对着屏幕所写的内容。为了简单起见,我们将忽略所有非常规的键。在 main.s,删除 bl SetGraphicsAddress 之后的所有代码。调用 UsbInitialise,将 r4r5 设置为 0,然后循环执行以下命令:

  1. 调用 KeyboardUpdate
  2. 调用 KeyboardGetChar
  3. 如果返回 0,跳转到步骤 1
  4. 复制 r4r5r1r2 ,然后调用 DrawCharacter
  5. r0 加到 r4
  6. 如果 r4 是 1024,将 r1 加到 r5,然后设置 r4 为 0。
  7. 如果 r5 是 768,设置 r5 为0
  8. 跳转到步骤 1

现在编译,然后在树莓派上测试。你几乎可以立即开始在屏幕上输入文本。如果没有工作,请参阅我们的故障排除页面。

当它工作时,祝贺你,你已经实现了与计算机的接口。现在你应该开始意识到,你几乎已经拥有了一个原始的操作系统。现在,你可以与计算机交互、发出命令,并在屏幕上接收反馈。在下一篇教程输入02中,我们将研究如何生成一个全文本终端,用户在其中输入命令,然后计算机执行这些命令。


via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html

作者:Alex Chadwick 选题:lujun9972 译者:ezio 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是一个很重要的话题,不仅对 Linux 管理员而言,对于我们大家而言也非常有帮助。我的意思是说对于工作在 IT 基础设施行业的用户来说,了解这个话题也是非常有用的。他们需要在执行下一步操作前,检查 Linux 服务器上某个端口是否开启。

假如这个端口没有被开启,则他们会直接找 Linux 管理员去开启它。如果这个端口已经开启了,则我们需要和应用团队来商量下一步要做的事。

在本篇文章中,我们将向你展示如何检查某个端口是否开启的 3 种方法。

这个目标可以使用下面的 Linux 命令来达成:

  • nc:netcat 是一个简单的 Unix 工具,它使用 TCP 或 UDP 协议去读写网络连接间的数据。
  • nmap:(“Network Mapper”)是一个用于网络探索和安全审计的开源工具,被设计用来快速地扫描大规模网络。
  • telnet:被用来交互地通过 TELNET 协议与另一台主机通信。

如何使用 nc(netcat)命令来查看远程 Linux 系统中某个端口是否开启?

ncnetcatnetcat 是一个简单的 Unix 工具,它使用 TCP 或 UDP 协议去读写网络连接间的数据。

它被设计成为一个可信赖的后端工具,可被直接使用或者简单地被其他程序或脚本调用。

与此同时,它也是一个富含功能的网络调试和探索工具,因为它可以创建你所需的几乎所有类型的连接,并且还拥有几个内置的有趣功能。

netcat 有三类功能模式,它们分别为连接模式、监听模式和隧道模式。

ncnetcat)命令的一般语法:

$ nc [-options] [HostName or IP] [PortNumber]

在下面的例子中,我们将检查远程 Linux 系统中的 22 端口是否开启。

假如端口是开启的,你将获得类似下面的输出。

# nc -zvw3 192.168.1.8 22
Connection to 192.168.1.8 22 port [tcp/ssh] succeeded!

命令详解:

  • nc:即执行的命令主体;
  • z:零 I/O 模式(被用来扫描);
  • v:显式地输出;
  • w3:设置超时时间为 3 秒;
  • 192.168.1.8:目标系统的 IP 地址;
  • 22:需要验证的端口。

当检测到端口没有开启,你将获得如下输出:

# nc -zvw3 192.168.1.95 22
nc: connect to 192.168.1.95 port 22 (tcp) failed: Connection refused

如何使用 nmap 命令来查看远程 Linux 系统中某个端口是否开启?

nmap(“Network Mapper”)是一个用于网络探索和安全审计的开源工具,被设计用来快速地扫描大规模网络,尽管对于单个主机它也同样能够正常工作。

nmap 以一种新颖的方式,使用裸 IP 包来决定网络中的主机是否可达,这些主机正提供什么服务(应用名和版本号),它们运行的操作系统(系统的版本),它们正在使用的是什么包过滤软件或者防火墙,以及其他额外的特性。

尽管 nmap 通常被用于安全审计,许多系统和网络管理员发现在一些日常任务(例如罗列网络资产、管理服务升级的计划、监视主机或者服务是否正常运行)中,它也同样十分有用。

nmap 的一般语法:

$ nmap [-options] [HostName or IP] [-p] [PortNumber]

假如端口是开启的,你将获得如下的输出:

# nmap 192.168.1.8 -p 22

Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-16 03:37 IST Nmap scan report for 192.168.1.8 Host is up (0.00031s latency).

PORT STATE SERVICE

22/tcp open ssh 

Nmap done: 1 IP address (1 host up) scanned in 13.06 seconds

假如端口没有开启,你将得到类似下面的结果:

# nmap 192.168.1.8 -p 80
Starting Nmap 7.70 ( https://nmap.org ) at 2019-03-16 04:30 IST
Nmap scan report for 192.168.1.8
Host is up (0.00036s latency).

PORT   STATE  SERVICE
80/tcp closed http

Nmap done: 1 IP address (1 host up) scanned in 13.07 seconds

如何使用 telnet 命令来查看远程 Linux 系统中某个端口是否开启?

telnet 命令被用来交互地通过 TELNET 协议与另一台主机通信。

telnet 命令的一般语法:

$ telnet [HostName or IP] [PortNumber]

假如探测成功,你将看到类似下面的输出:

$ telnet 192.168.1.9 22
Trying 192.168.1.9...
Connected to 192.168.1.9.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.3
^]
Connection closed by foreign host.

假如探测失败,你将看到类似下面的输出:

$ telnet 192.168.1.9 80
Trying 192.168.1.9...
telnet: Unable to connect to remote host: Connection refused

当前,我们只找到上面 3 种方法来查看远程 Linux 系统中某个端口是否开启,假如你发现了其他方法可以达到相同的目的,请在下面的评论框中告知我们。


via: https://www.2daygeek.com/how-to-check-whether-a-port-is-open-on-the-remote-linux-system-server/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:FSSlc 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

众所周知,如果没有 cd 命令,我们无法 Linux 中切换目录。这个没错,但我们有一个名为 shopt 的 Linux 内置命令能帮助我们解决这个问题。

shopt 是一个 shell 内置命令,用于设置和取消设置各种 bash shell 选项,由于它已安装,因此我们不需要再次安装它。

是的,我们可以在启用此选项后,可以不使用 cd 命令切换目录。

我们将在本文中向你展示如何操作。这是一个小的调整,但对于那些从 Windows 迁移到 Linux 的新手来说非常有用。

这对 Linux 管理员没用,因为我们不会在没有 cd 命令的情况下切换到该目录,因为我们对此有经验。

如果你尝试在没有 cd 命令的情况下切换 Linux 的目录/文件夹,你将看到以下错误消息。这在 Linux 中很常见。

$ Documents/
bash: Documents/: Is a directory

为此,我们需要在用户 .bashrc 中追加以下值。

什么是 .bashrc ?

.bashrc 是一个 shell 脚本,每次用户以交互模式打开新 shell 时都会运行该脚本。

你可以在该文件中添加要在命令提示符下输入的任何命令。

.bashrc 文件本身包含终端会话的一系列配置。包括设置和启用:着色、补全,shell 历史,命令别名等。

$ vi ~/.bashrc

加入这一行:

shopt -s autocd

运行以下命令使更改生效。

$ source ~/.bashrc

我们已完成所有配置。简单地对此进行测试以确认这是否有效。

$ Documents/
cd -- Documents/

$ daygeek/
cd -- daygeek/

$ /home/daygeek/Documents/daygeek
cd -- /home/daygeek/Documents/daygeek

$ pwd
/home/daygeek/Documents/daygeek

是的,它正如预期的那样正常工作。

而且,它在 fish shell 中工作正常,而无需对 .bashrc 进行任何更改。

如果要暂时执行此操作,请使用以下命令(设置或取消设置)。重启系统时,它将消失。

# shopt -s autocd

# shopt | grep autocd
autocd  on

# shopt -u autocd

# shopt | grep autocd
autocd  off

shopt 命令提供了许多其他选项,如果要验证这些选项,请运行以下命令。

$ shopt
autocd  on
assoc_expand_once   off
cdable_vars     off
cdspell     on
checkhash   off
checkjobs   off
checkwinsize    on
cmdhist     on
compat31    off
compat32    off
compat40    off
compat41    off
compat42    off
compat43    off
compat44    off
complete_fullquote  on
direxpand   off
dirspell    off
dotglob     off
execfail    off
expand_aliases  on
extdebug    off
extglob     off
extquote    on
failglob    off
force_fignore   on
globasciiranges on
globstar    off
gnu_errfmt  off
histappend  on
histreedit  off
histverify  off
hostcomplete    on
huponexit   off
inherit_errexit off
interactive_comments    on
lastpipe    off
lithist     off
localvar_inherit    off
localvar_unset  off
login_shell     off
mailwarn    off
no_empty_cmd_completion off
nocaseglob  off
nocasematch     off
nullglob    off
progcomp    on
progcomp_alias  off
promptvars  on
restricted_shell    off
shift_verbose   off
sourcepath  on
xpg_echo    off

此外,我找到了一些其他程序,它们可以帮助我们在 Linux 中比 cd 命令更快地切换目录。

它们是 pushdpopdup shell 脚本和 bd 工具。我们将在接下来的文章中介绍这些主题。


via: https://www.2daygeek.com/navigate-switch-directory-without-using-cd-command-in-linux/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在我们的树莓派使用入门的第八篇文章中,我们将学习如何使用树莓派观看 Netflix 上的影片和用它来听音乐。

到目前为止,本系列文章已经学习了很多话题 — 如何 挑选购买设置、和 更新 你的树莓派,以及 儿童成人 如何使用它来做的不同的事情(包括学习 Linux)。今天我们换一个话题,将学习一些娱乐方面的内容!我们将学习如何使用树莓派来做一些娱乐方面的事情,明天我们继续这个话题,将用它来玩游戏。

观看电视和电影

你可以使用你的树莓派和 开源媒体中心 (OSMC) 去 观看 Netflix!OSMC 是一个基于 Kodi 项目的系统,你可以使用它来播放来自本地网络、附加存储以及互联网上的多媒体。它因为良好的功能特性而在媒体播放应用界中拥有非常好的口碑。

NOOBS(我们在本系列的 第三篇文章 中介绍过它)可以让你在你的树莓派中很容易地 安装 OSMC。在 NOOBS 中也提供了另外一个基于 Kodi 项目的媒体播放系统,它的名字叫 LibreELEC

听音乐

你还可以让你的树莓派借助 Pi Music Box 项目通过网络来播放来自附加存储或像 Spotify 服务上的流媒体音乐。以前我 写过关于这个主题的文章,但是你可以在 Pi Music Box 网站 上找到最新的指导,包括如何使用和 DIY 项目。


via: https://opensource.com/article/19/3/raspberry-pi-entertainment

作者:Anderson Silva 选题:lujun9972 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出