新贝彩票注册 - 文章 – 伯乐在线 http://www.cswhw.com.cn Sat, 27 Jan 2018 12:23:30 +0000 zh-CN hourly 1 http://www.cswhw.com.cn/?v=4.5.13 新贝彩票注册 - 三款简单而优秀的 Linux 网络监视工具 http://www.cswhw.com.cn/113549/ http://www.cswhw.com.cn/113549/#respond Sat, 27 Jan 2018 12:23:30 +0000 http://www.cswhw.com.cn/?p=113549 通过 iftop、 nethogs 和 vnstat 详细了解你的网络连接状态。

三款简单而优秀的 Linux 网络监视工具,首发于新贝彩票注册。

]]>

通过 iftop、 nethogsvnstat 详细了解你的网络连接状态。

你可以通过这三个 Linux 命令了解当前网络的大量信息。iftop 通过进程号跟踪网络连接,nethogs 快速告知你哪些进程在占用你的带宽,而 vnstat 以一个良好的轻量级守护进程在后台运行,并实时记录你的网络使用情况。

iftop

令人称赞的 iftop 可以监听您指定的网络接口,并以 top 的样式呈现。

这是一个不错的小工具,可以用于找出网络拥塞,测速和维持网络流量总量??吹阶约旱降自谟枚嗌俅硗欠浅>说?,尤其是对于我们这些仍然记得电话线路、调制解调器,“高速”到令人惊叫的 kb 和实时波特率的老人们。我们在很久之前就不再使用波特率,转而钟情于比特率。波特率用于衡量信号变化,尽管有时候与比特率相同,但大多数情况下并非如此。

如果你只有一个网络接口,直接运行 iftop 即可。不过 iftop 需要 root 权限:

$ sudo iftop

如果你有多个网络接口,那就指定你要监控的接口:

$ sudo iftop -i wlan0

就像 top 命令一样,你可以在命令运行时更改显示选项:

  • h?切换帮助界面。
  • n?是否解析域名。
  • s 切换源地址的显示,d 则切换目的地址的显示。
  • S?是否显示端口号。
  • N?是否解析端口;若关闭解析则显示端口号。
  • t 切换文本显示界面。默认的显示方式需要 ncurses。我个人认为图 1 的显示方式在组织性和可读性都更加良好。
  • p?暂停显示更新。
  • q?退出程序。

text display

图 1:组织性和可读性良好的文本显示。

当你切换显示设置的时候,iftop 并不会中断监测流量。当然你也可以单独监测一台主机。而这需要该主机的 IP 地址和子网掩码。现在,我很好奇 Pandora(LCTT 译注:一家美国的电台公司)能给我贫瘠的带宽带来多大的负载。因此我首先使用 dig 命令找到他们的 IP 地址:

$ dig A pandora.com
[...]
;; ANSWER SECTION:
pandora.com.            267     IN      A       208.85.40.20
pandora.com.            267     IN      A       208.85.40.50

那子网掩码呢?ipcalc 会告诉我们:

$ ipcalc -b 208.85.40.20
Address:   208.85.40.20   
Netmask:   255.255.255.0 = 24
Wildcard:  0.0.0.255  
=>
Network:   208.85.40.0/24

现在,将 IP 地址和子网掩码提供给 iftop

$ sudo iftop -F 208.85.40.20/24 -i wlan0

很棒的不是么?而我也很惊奇地发现,Pandora 在我的网络上,每小时大约使用 500kb。并且就像大多数流媒体服务一样,Pandora 的流量在迅速增长,并依靠缓存稳定下来。

你可以使用 -G 选项对 IPv6 地址执行相同的操作。查阅友好的 man 可以帮助你了解 iftop 的其他功能,包括使用个人配置文件自定义你的默认选项,以及使用自定义过滤(请参阅?PCAP-FILTER?来获取过滤指南)。

nethogs

当你想要快速了解是谁在吸取你的带宽的时候,nethogs 是个快速而简单的方法。你需要以 root 身份运行并指定要监听的接口。它会给你显示大量的应用程序及其进程号,所以如果你想的话,你可以借此杀死任一进程。

$ sudo nethogs wlan0

nethogs version 0.8.1

PID USER   PROGRAM              DEV    SENT   RECEIVED       
7690 carla /usr/lib/firefox     wlan0 12.494 556.580 KB/sec
5648 carla .../chromium-browser wlan0  0.052   0.038 KB/sec
TOTAL                                 12.546 556.618 KB/sec

nethogs 并没有多少选项:在 kb/s、kb、b、mb之间循环,按接收和发送的数据包排序,调整刷新延迟。具体请看man nethogs,或者是运行 nethogs -h。

vnstat

vnstat是最容易使用的网络数据收集工具。它十分轻量并且不需要 root 权限。它以守护进程在后台运行,因此可以实时地记录你的网络数据。单个 vnstat 命令就可以显示所累计的数据。

$ vnstat -i wlan0
Database updated: Tue Oct 17 08:36:38 2017

   wlan0 since 10/17/2017

          rx:  45.27 MiB      tx:  3.77 MiB      total:  49.04 MiB

   monthly
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
       Oct '17     45.27 MiB |    3.77 MiB |   49.04 MiB |    0.28 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated        85 MiB |       5 MiB |      90 MiB |

   daily
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
         today     45.27 MiB |    3.77 MiB |   49.04 MiB |   12.96 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated       125 MiB |       8 MiB |     133 MiB |

默认情况下它会显示所有的网络接口。使用 -i 选项来选择某个接口。也可以像这样合并多个接口的数据:

$ vnstat -i wlan0+eth0+eth1

你可以通过这几种方式过滤数据显示:

  • -h?按小时显示统计信息。
  • -d?按天显示统计信息.
  • -w-m 分别按周和月份来显示统计信息。
  • 使用 -l 选项查看实时更新。

以下这条命令将会删除 wlan1 的数据库并不再监视它:

$ vnstat -i wlan1 --delete

而下面这条命令将会为你的一个网络接口创建一个别名。这个例子使用了 Ubuntu 16.04 的一个有线接口名称:

$ vnstat -u -i enp0s25 --nick eth0

默认情况下,vnstat 会监视 eth0。你可以在 /etc/vnstat.conf 对它进行修改,或者在你的家目录下创建你自己的个人配置文件。请参阅 man vnstat 以获取完整的指南。

你也可以安装 vnstati 来创建简单的彩图(图 2):

$ vnstati -s -i wlx7cdd90a0a1c2 -o vnstat.png

vnstati

图 2:你可以使用vnstati来创建简单的彩图。

请参阅 man vnstati 以获取完整的选项。

三款简单而优秀的 Linux 网络监视工具,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113549/feed/ 0
新贝彩票注册 - 分析了 7500w+ GitHub 代码仓库 哪门语言热度最高? http://www.cswhw.com.cn/113546/ http://www.cswhw.com.cn/113546/#respond Sat, 27 Jan 2018 12:06:41 +0000 http://www.cswhw.com.cn/?p=113546 近日,有开发者在 reddit 发布了一个帖子,内容是通过对 GitHub 用户的数据进行分析得到的编程语言排序榜。作者认为,通过计算 GitHub 上有多少人使用每种语言来对所有的编程语言进行排序会很有趣。

分析了 7500w+ GitHub 代码仓库 哪门语言热度最高?,首发于新贝彩票注册。

]]>
近日,有开发者在 reddit?发布了一个帖子,内容是通过对 GitHub 用户的数据进行分析得到的编程语言排序榜。作者认为,通过计算 GitHub 上有多少人使用每种语言来对所有的编程语言进行排序会很有趣。

下面我们不妨看看这份数据源“独特”的排行榜有哪些值得关注的东西。

首先,作者表示这次分析的数据主要来源于?GitHub Archive?和?GHTorrent。他通过分析 GitHub Archive 上?7500w+ 个不同的仓库中超过 12.5 亿次的事件(包括推送新代码、fork、star、issue 处理等),每月汇总一次,计算了每种语言的 MAU(月活跃用户数量),详细的分析说明可点此查看。

先看看总体数据,截至 2018 年 1 月 24 日,通过统计 GitHub 上活跃用户的活动情况,对每种语言的排名结果如下(TOP 25):

整体排名十分有趣,但我们应该深入了解这些语言随着时间的推移有着怎么的演变。(数据可以追溯到 7 年前)

主流编程语言

可以看到,主流编程语言都有着相对稳定的用户群,而且大多数也都是你意料之中的。

从追踪的数据来看,JavaScript, Python, Java, C++ 和 C 保持这种热度的势头已经超过 7 年,所以近段时间依然不会有所改变。

JavaScript 保持它的“龙头”地位是可以解释的,因为它基本上是所有程序员都需要使用的一门语言。

不过随着时间的推移,Python 的使用者越来越多,最近已超过 Java 成为 GitHub 上第二大流行的编程语言。Python 的增长大部分似乎都来自开发者对机器学习的兴趣。事实上,Python 的整体流行度在这里可能被低估了(以后可能会更多)。

C++?似乎也正在超越 C 的地位,而这也是有根据的,像 GCC 这种项目都已经从 C 转换到 C++,以便使用 C++ 的一些特性。由于 C++ 基本上是 C 的超集,GCC 团队发现使用 C++ 的有限子集可让他们编写更干净的代码。

2018 年要学习的编程语言

观察这种编程语言趋势的最好方法就是,确定具有快速增长的用户群的新兴编程语言:

明显能看到,用户群增长最快的语言分别有:Go,TypeScript,Kotlin 和 Rust。

作者表示,在过去的几周里他也一直在学习 Go 和 Typescript。他发现,对于编写并发的服务器端程序,Go 确实非常有用,而在使用 TypeScript 几个星期后,自己可能再也不会乐意使用 JavaScript 了。

Kotlin 的崛起是意料之中的,Kotlin 主要用于 Android 应用程序开发,当被宣布成为 Android 开发的官方支持语言后,看看图中的斜率变化情况。

对于 Rust,在这里的增长虽然比其他语言慢,但其中依然有许多令人惊叹的项目。作者推荐了两个用 Rust 编写的两个项目 —— 用于 Ruby 的采样分析器autodifferentiation 框架。

事实上,所有这些语言都有一个共同点,它们背后都有大公司在支持着。正如谷歌之于?Go,微软之于?TypeScript,JetBrains 之于 Kotlin,Mozilla 之于 Rust。成功推广一门新的语言需要不少的付出 —— 至少仅仅开发出一门优雅的语言是不够的,还必须扩大语言背后的社区和生态系统。诸如 IDE 支持,用于常见任务的库和软件包、工具和文档,这些对于让用户使用某种语言都非常重要,而且都需要付出巨大的努力。

出现下滑趋势的语言

在过去的 7 年里,Ruby,PHP,Objective-C,CoffeeScript 和 Perl 在 GitHub 上的用户比例都显着下降。

不过值得注意的是,这些数据是以 GitHub 用户群的百分比得出的,而 GitHub 的用户数量正在快速增长。在过去的 7 年中,GitHub 的用户增长已经超过了 20 倍。这意味着即使是市场份额下降的语言也可能拥有不断增长的用户群。

这样来看,相比 2011 年,使用 Ruby 语言的活跃用户数量已经超过了3倍。它的增长没有其他语言那么快,导致它在这个分析上的表现相对较差。

此外要注意的是,某些较新的语言似乎在蚕食旧版语言的用户群。例如,Objective-C 用户的下降与 Swift 的上升相对应。另外,CoffeeScript 似乎已经被 TypeScript 取代:

虽然 Objective-C 正在下滑,但整体上 iOS 开发相对稳定。同样的,CoffeeScript 似乎已经为 TypeScript 铺平了道路,因为它让程序员习惯于将代码编译成 JavaScript。

函数式编程语言

作者表示,这里的数据相对较少,排名中的干扰因素较多,他不相信随着时间的推移,Clojure 和 Haskell 会出现这样明显的下滑。而 Elixir 这门语言值得大家留意,虽然未能排在前 25 名。

文中作者还对用于科学领域的语言进行了分析,详情可查看原文。作者还表示未来对编程语言流行度的跟踪将会参考其他一些数据,如?TIOBE 指数、Stack Overflow 上的标签趋势图、GitHub Octoverse 等。

源码和整体排名可在 GitHub 上查看。

最后,reddit 帖子的回帖中,有用户给出了自己统计的数据以进行对比参考,他统计了 reddit 上十大最受欢迎的编程语言的 subreddits 数量( subreddits 是 reddit 中的子版块,用户可根据自己的兴趣和需要进行订阅)

Python – 213594
JavaScript – 199592
Java – 81241
PHP – 58794
C++ – 58788
C# – 52103
Go – 39529
Ruby – 38405
Rust – 33124
C – 32351

分析了 7500w+ GitHub 代码仓库 哪门语言热度最高?,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113546/feed/ 0
新贝彩票注册 - 与 C 语言长别离 http://www.cswhw.com.cn/113538/ http://www.cswhw.com.cn/113538/#respond Fri, 26 Jan 2018 07:05:06 +0000 http://www.cswhw.com.cn/?p=113538 我意识到了一个让我震惊的事实 —— 我有着 35 年的 C 语言经验。每周我都要写很多 C 代码,但是我已经记不清楚上一次我 创建一个新的 C 语言项目 是在什么时候了。

与 C 语言长别离,首发于新贝彩票注册。

]]>
?这几天来,我在思考那些正在挑战 C 语言的系统编程语言领袖地位的新潮语言,尤其是 Go 和 Rust。思考的过程中,我意识到了一个让我震惊的事实 —— 我有着 35 年的 C 语言经验。每周我都要写很多 C 代码,但是我已经记不清楚上一次我 创建一个新的 C 语言项目 是在什么时候了。
timg

如果你完全不认为这种情况令人震惊,那你很可能不是一个系统程序员。我知道有很多程序员使用更高级的语言工作。但是我把大部分时间都花在了深入打磨像 NTPsec、 GPSD 以及 giflib 这些东西上。熟练使用 C 语言在这几十年里一直就是我的专长。但是,现在我不仅是不再使用 C 语言写新的项目,甚至我都记不清我是什么时候开始这样做的了,而且……回头想想,我觉得这都不是本世纪发生的事情。

这个对于我来说是件大事,因为如果你问我,我的五个最核心软件开发技能是什么,“C 语言专家” 一定是你最有可能听到的之一。这也激起了我的思考。C 语言的未来会怎样 ?C 语言是否正像当年的 COBOL 语言一样,在辉煌之后,走向落幕?

我恰好是在 C 语言迅猛发展,并把汇编语言以及其它许多编译型语言挤出主流存在的前几年开始编程的。那场过渡大约是在 1982 到 1985 年之间。在那之前,有很多编译型语言争相吸引程序员的注意力,那些语言中还没有明确的领导者;但是在那之后,小众的语言就直接毫无声息的退出了舞台。主流的语言(FORTRAN、Pascal、COBOL)则要么只限于老代码,要么就是固守单一领域,再就是在 C 语言的边缘领域顶着愈来愈大的压力苟延残喘。

而在那以后,这种情形持续了近 30 年。尽管在应用程序开发上出现了新的动向: Java、 Perl、 Python, 以及许许多多不是很成功的竞争者。起初我很少关注这些语言,这很大一部分是因为在它们的运行时的开销对于当时的实际硬件来说太大。因此,这就使得 C 的成功无可撼动;为了使用和对接大量已有的 C 语言代码,你得使用 C 语言写新代码(一部分脚本语言尝试过打破这种壁垒,但是只有 Python 有可能取得成功)。

回想起来,我在 1997 年使用脚本语言写应用时本应该注意到这些语言的更重要的意义的。当时我写的是一个名为 SunSITE 的帮助图书管理员做源码分发的辅助软件,当时使用的是 Perl 语言。

这个应用完全是用来处理文本输入的,而且只需要能够应对人类的反应速度即可(大概 0.1 秒),因此使用 C 或者别的没有动态内存分配以及字符串类型的语言来写就会显得很傻。但是在当时,我仅仅是把其视为一个试验,而完全没有想到我几乎再也不会在一个新项目的第一个文件里敲下 int main(int argc, char **argv) 这样的 C 语言代码了。

我说“几乎”,主要是因为 1999 年的 SNG。 我想那是我最后一个用 C 从头开始写的项目了。

在那之后我写的所有的 C 代码都是在为那些上世纪已经存在的老项目添砖加瓦,或者是在维护诸如 GPSD 以及 NTPsec 一类的项目。

当年我本不应该使用 C 语言写 SNG 的。因为在那个年代,摩尔定律的快速迭代使得硬件愈加便宜,使得像 Perl 这样的语言的执行效率也不再是问题。仅仅三年以后,我可能就会毫不犹豫地使用 Python 而不是 C 语言来写 SNG。

在 1997 年我学习了 Python, 这对我来说是一道分水岭。这个语言很美妙 —— 就像我早年使用的 Lisp 一样,而且 Python 还有很酷的库!甚至还完全遵循了 POSIX!还有一个蛮好用的对象系统!Python 没有把 C 语言挤出我的工具箱,但是我很快就习惯了在只要能用 Python 时就写 Python ,而只在必须使用 C 语言时写 C。

(在此之后,我开始在我的访谈中指出我所谓的 “Perl 的教训” ,也就是任何一个没能实现和 C 语言语义等价的遵循 POSIX 的语言都注定要失败。在计算机科学的发展史上,很多学术语言的骨骸俯拾皆是,原因是这些语言的设计者没有意识到这个重要的问题。)

显然,对我来说,Python 的主要优势之一就是它很简单,当我写 Python 时,我不再需要担心内存管理问题或者会导致核心转储的程序崩溃 —— 对于 C 程序员来说,处理这些问题烦的要命。而不那么明显的优势恰好在我更改语言时显现,我在 90 年代末写应用程序和非核心系统服务的代码时,为了平衡成本与风险都会倾向于选择具有自动内存管理但是开销更大的语言,以抵消之前提到的 C 语言的缺陷。而在仅仅几年之前(甚至是 1990 年),那些语言的开销还是大到无法承受的;那时硬件产业的发展还在早期阶段,没有给摩尔定律足够的时间来发挥威力。

尽量地在 C 语言和 Python 之间选择 C —— 只要是能的话我就会从 C 语言转移到 Python 。这是一种降低工程复杂程度的有效策略。我将这种策略应用在了 GPSD 中,而针对 NTPsec , 我对这个策略的采用则更加系统化。这就是我们能把 NTP 的代码库大小削减四分之一的原因。

但是今天我不是来讲 Python 的。尽管我觉得它在竞争中脱颖而出,Python 也未必真的是在 2000 年之前彻底结束我在新项目上使用 C 语言的原因,因为在当时任何一个新的学院派的动态语言都可以让我不再选择使用 C 语言。也有可能是在某段时间里在我写了很多 Java 之后,我才慢慢远离了 C 语言。

我写这个回忆录是因为我觉得我并非特例,在世纪之交,同样的发展和转变也改变了不少 C 语言老手的编码习惯。像我一样,他们在当时也并没有意识到这种转变正在发生。

在 2000 年以后,尽管我还在使用 C/C++ 写之前的项目,比如 GPSD ,游戏韦诺之战以及 NTPsec,但是我的所有新项目都是使用 Python 的。

有很多程序是在完全无法在 C 语言下写出来的,尤其是 reposurgeon?以及?doclifter 这样的项目。由于 C 语言受限的数据类型本体论以及其脆弱的底层数据管理问题,尝试用 C 写的话可能会很恐怖,并注定失败。

甚至是对于更小的项目 —— 那些可以在 C 中实现的东西 —— 我也使用 Python 写,因为我不想花不必要的时间以及精力去处理内核转储问题。这种情况一直持续到去年年底,持续到我创建我的第一个 Rust 项目,以及成功写出第一个使用 Go 语言的项目。

如前文所述,尽管我是在讨论我的个人经历,但是我想我的经历体现了时代的趋势。我期待新潮流的出现,而不是仅仅跟随潮流。在 98 年的时候,我就是 Python 的早期使用者。来自 TIOBE 的数据则表明,在 Go 语言脱胎于公司的实验项目并刚刚从小众语言中脱颖而出的几个月内,我就开始实现自己的第一个 Go 语言项目了。

总而言之:直到现在第一批有可能挑战 C 语言的传统地位的语言才出现。我判断这个的标准很简单 —— 只要这个语言能让我等 C 语言老手接受不再写 C 的事实,这个语言才 “有可能” 挑战到 C 语言的地位 —— 来看啊,这有个新编译器,能把 C 转换到新语言,现在你可以让他完成你的全部工作了 —— 这样 C 语言的老手就会开心起来。

Python 以及和其类似的语言对此做的并不够好。使用 Python 实现 NTPsec(以此举例)可能是个灾难,最终会由于过高的运行时开销以及由于垃圾回收机制导致的延迟变化而烂尾。如果需求是针对单个用户且只需要以人类能接受的速度运行,使用 Python 当然是很好的,但是对于以 机器的速度 运行的程序来说就不总是如此了 —— 尤其是在很高的多用户负载之下。这不只是我自己的判断 —— 因为拿 Go 语言来说,它的存在主要就是因为当时作为 Python 语言主要支持者的 Google 在使用 Python 实现一些工程的时候也遭遇了同样的效能痛点。

Go 语言就是为了解决 Python 搞不定的那些大多由 C 语言来实现的任务而设计的。尽管没有一个全自动语言转换软件让我很是不爽,但是使用 Go 语言来写系统程序对我来说不算麻烦,我发现我写 Go 写的还挺开心的。我的很多 C 编码技能还可以继续使用,我还收获了垃圾回收机制以及并发编程机制,这何乐而不为?

这里有关于我第一次写 Go 的经验的更多信息)

本来我想把 Rust 也视为 “C 语言要过时了” 的例证,但是在学习并尝试使用了这门语言编程之后,我觉得这种语言现在还没有做好准备。也许 5 年以后,它才会成为 C 语言的对手。

随着 2017 的尾声来临,我们已经发现了一个相对成熟的语言,其和 C 类似,能够胜任 C 语言的大部分工作场景(我在下面会准确描述),在几年以后,这个语言界的新星可能就会取得成功。

这件事意义重大。如果你不长远地回顾历史,你可能看不出来这件事情的伟大性。三十年了 —— 这几乎就是我作为一个程序员的全部生涯,我们都没有等到一个 C 语言的继任者,也无法遥望 C 之后的系统编程会是什么样子的。而现在,我们面前突然有了后 C 时代的两种不同的展望和未来……

……另一种展望则是下面这个语言留给我们的。我的一个朋友正在开发一个他称之为 “Cx” 的语言,这个语言在 C 语言上做了很少的改动,使得其能够支持类型安全;他的项目的目的就是要创建一个能够在最少人力参与的情况下把古典 C 语言修改为新语言的程序。我不会指出这位朋友的名字,免得给他太多压力,让他做出太多不切实际的保证。但是他的实现方法真的很是有意思,我会尽量给他募集资金。

现在,我们看到了可以替代 C 语言实现系统编程的三种不同的可能的道路。而就在两年之前,我们的眼前还是一片漆黑。我重复一遍:这件事情意义重大。

我是在说 C 语言将要灭绝吗?不是这样的,在可预见的未来里,C 语言还会是操作系统的内核编程以及设备固件编程的主流语言,在这些场景下,尽力压榨硬件性能的古老规则还在奏效,尽管它可能不是那么安全。

现在那些将要被 C 的继任者攻破的领域就是我之前提到的我经常涉及的领域 —— 比如 GPSD 以及 NTPsec、系统服务以及那些因为历史原因而使用 C 语言写的进程?;褂芯褪且?DNS 服务器以及邮件传输代理 —— 那些需要以机器速度而不是人类的速度运行的系统程序。

现在我们可以对后 C 时代的未来窥见一斑,即上述这类领域的代码都可以使用那些具有强大内存安全特性的 C 语言的替代者实现。Go 、Rust 或者 Cx ,无论是哪个,都可能使 C 的存在被弱化。比如,如果我现在再来重新实现一遍 NTP ,我可能就会毫不犹豫的使用 Go 语言去完成。

与 C 语言长别离,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113538/feed/ 0
新贝彩票注册 - 一个技术大牛对程序员招聘的吐槽和建议 http://www.cswhw.com.cn/113532/ http://www.cswhw.com.cn/113532/#respond Fri, 26 Jan 2018 05:59:47 +0000 http://www.cswhw.com.cn/?p=113532 作为软件人,找工作有时候似乎挺苦逼的。说真的,让我去掉前面这句中“似乎”二字吧。就是苦逼!很多人都曾抱怨处在招聘的一方很糟糕,我们没有任何可靠的方式来甄别会写代码并且写得好的人。但其实应聘方也很苦逼!招聘方遇到的困境,也恰恰是造成痛苦流程的原因。

一个技术大牛对程序员招聘的吐槽和建议,首发于新贝彩票注册。

]]>
【导读】:James Bennett 是一个来自美国西弗吉尼亚州的程序员,Python Web 框架 Django 的核心团队成员之一。做过自由职业者,也做过全职工作。前端、后端都干过。James 对好工具充满热情,所以他一直参与 Django 框架的开发贡献,还有其他开源软件。

本文是他对程序员招聘的吐槽,最后给了一些建议。


作为软件人,找工作有时候似乎挺苦逼的。

说真的,让我去掉前面这句中“似乎”二字吧。就是苦逼!很多人都曾抱怨处在招聘的一方很糟糕——我们没有任何可靠的方式来甄别会写代码并且写得好的人。这的确是真的,我们这行在这方面做得很糟糕。即使是在最常见的开发者群体(美国人、男性、白人、较为年轻和中产背景)当中,我们的甄别能力也绝对是一败涂地,而当面对更广泛的人群时,我们只会干得更差。但我们不得不扩大范围,因为就算我们没有道德感,我们也面临着数量的问题,职位岗位比上述“精英”多,总共只有那么多美国中产二十多岁的白人男性,然后其中一半根本不会应聘你们只发股权的“支持Uber、23andme、推特、部落冲突的无人机运输”公司,因为他们正在你创业的星巴克马路对面的另一家星巴克成立自己的公司。另一方面称职并且想要技术岗位却没得到的女性、非白人、外国人数量简直太多了。

但是应聘的一方(我现在所在的一方)也很苦逼。招聘方遇到的困境,也恰恰是造成痛苦流程的原因。

教育很烂

我们尝试过的其中一个方法是看学历。但是我们根本不擅长在学校教人编程。涉及到计算机的课程,应该是数学系还是工程系的延伸,多数大学都决定不下来。结果他们最后弄出来的是诡异的融合,但其实两者都不是;或者他们在教编程,但是语言和技术已经落后现有规范好多年;又或者他们让学生死记算法列表及其复杂度,这会让学生误以为编程不过是死记硬背,然后成为一个能输出正确算法名字和伪代码的自动机。因为公司真正想找的是就是复读机,难道不是吗?直接开发一个数据结构的复读机,可能再加上一个排序算法的复读机,大概就能省下很多面试的时间。

我深信现有的教育方式及其缺陷,是造成我们听到的软件招聘恐怖故事的原因。拥有 CS 硕士学位,却似乎不能从一张白纸开始写代码的人,其实不差;更有可能是他们受到的教育轻视实际编程而注重理论。在邮件列表和论坛发布“请给我写好的代码”帖子的人,其实不差;更有可能他们受到的教育建基于背诵和应试。另外如果你从没读过著名物理学家费曼造访一所采用这个方法的大学的故事,我强烈推荐它。

那仍然是编程教学处在的阶段:我们知道自己需要程序员,而我们没有足够多的程序员来写代码,更别说教出更多的程序员,所以这种死记硬背的现象广泛存在,这是因为这已经是我们现在力所能及的范围。我们只是希望我们“教”出来的学生,会跑去看 Ruby on Rails 的教程,然后无意中看见 GitHub 的文档,然后从中神奇地学会真正的软件开发、架构和最佳规范。因为大家都明白,他们不可能在学校里学会这些。

与此同时另一方面,在我合作过的技术牛人当中,大多数根本没有软件工程和计算机科学的大学背景;很多人直到快上完学才第一次写代码( 不要脸的偏见:我直到快大学毕业才开始通常意义上的“编程”,我也是在毕业几年后才开始以此谋生)。很多真正厉害的人会被“计算机科学本科”这一条件过滤掉,这是招聘方不谨慎定下职位要求时会遇到的问题。即使招聘方费心加上“或拥有相当的经验”,他们甚至也还是被过滤掉,因为履历上的学位似乎就是招聘者和 HR 筛选推送给实际技术人员的求职者的第一条依据。

顺带一提,我有一个哲学学位。并不是炫耀,不过软件领域很多我认识并尊敬的非常厉害的人都有着相同的背景。

所以将学历作为筛选标准效果并不好;公司也很苦逼,因为拥有 CS 学位并不意味着一个人已经准备好坐下来写代码;准备好写代码的求职者也苦逼,因为没有 CS 学位仍然是个短板,而且为了学位回归学校四年并不轻松。而且每一飞秒都有五万个编程训练营/培训班被启动,从中出来的人拥有哲学系、文学系、神学系、历史系和现代 A 线诗歌符号学的学位,但是当他们经历了训练营后,他们大概至少能和计算机系的学生水平相当,因为 CS 的课程基本都很烂,而且主动加入编程训练营的人通常很聪明而且充满动力。而且如果他们能学会拆解 A 线诗歌,基本就能确认他们能用你的 JavaScript 框架写出一个 CRUD 应用程序,因为那个 JavaScript 框架上周才发布,所以根本没有多少人拥有超过一两天的 ReAngleBoneASS 实战经验。

编程面试很烂

由于学历不靠谱,另一个甄别会编程的人的方式是编程面试。求职者和公司内部的某人交谈(通常是电话或者视频聊天),并被要求写出解决问题的代码。如果你还保留着好奇心我就告诉你吧,我们不擅长用这个方式选出会编程的人。简单来说,此类面试并不靠谱,因为它们太短、太做作、太压迫。

详细一点来说:我认识多个顶级人才被他们绝对胜任的职位给拒了,就因为这种编程面试。我倾向于把它们看作“问个谜语”风潮的最新版,这个环节当年由于微软的实施而流行一时,因为每家公司都想像微软一样又大又成功。现在,人们听说谷歌会进行编程面试,并且看到 Jeff Atwood 的 FizzBuzz 测试,而每家公司都想像谷歌一样又大又成功,并且与 Jeff Atwood 的招聘恐怖故事产生共鸣,所以现在所有人都在进行编程面试。但是这种面试依旧很烂??赡苷馐且蛭雀杈菟涤玫氖前装?,而其他公司用的是电话。

想不想看一个非常称职却因为编程面试而被拒绝的一个例子?他被拒是因为面试官在电话那头笔录错了他念的 Bash 脚本,这当然让脚本出了问题。我绝对没有开玩笑或者夸张,而除了“神经病”我实在找不到其他形容。如果用的是白板,他就被录取了。

事实上,我十分确定我搞砸过一次编程面试(至少我到现在还没收到该公司的答复)。要记住我并不是刚毕业入行的人。我已经有超过十年的 Web 应用开发经验,处理过各种各样的规模系统;我是一个非常重要的 Web 框架的核心团队成员,并且可能是这方面的世界级专家;我真的写了关于使用该框架的书(最早的几本之一),有时会被聘请去教这个框架,以及被学术会议邀请去做关于这个框架的 keynote 演讲。我曾经有一阵子没怎么睡觉,全程死死盯着一个正在运行的程序,想要理清 Django 的旧式系统,发现我的精神动物是一只迟缓的懒猴,而过了一阵子当我的意识像甘道夫那样重新塞进身体时,我提交了仅仅两行代码进行反击,解决了五个“深藏 Django 腹中”不同的 bug。我挺擅长这些的,如果你还没注意到的话我希望你记住这点咯。

我希望你注意到,因为我基本确信我最近搞砸了一次编程面试。

我不会提那家公司的名字,因为这跟本文无关。我也不会公布他们问的题目,因为那也同样无关。那个题目并没有 FizzBuzz 那么简单,但还是很简单,是我下意识就能提出好几种解决方式的那种问题。面试官否决了我偏好的方法(大概因为这个方法直接调用标准库的函数而无法展示我能手动解决),于是我换了另一个方式。而我从记忆中重新构筑这个方法的时候恰巧犯了一个小错误,因为我过于自信了并且想跟面试官聊其他的,于是我想着我都知道怎么只靠记忆完成这个解决方案了,为啥不赶紧水过这个题目,然后谈谈我真正在乎的事呢。

顺便一提,我出了一个小笔误,就是我给错误的循环变量加了值。单字母的变量名很糟糕,即使是在你为了敷衍面试官而写的傻瓜程序里;再说白一点,代码能跑起来,但是结果是错误的。

而当程序跑完然后吐出错误的结果时,我全部的自信都荡然无存,内心OS:“我的个天!为啥不对!我应该知道的呀”,然后我一边疯狂调试,一边尝试向面试官解释我的做法并且回答他们的问题,一边读代码、看结果、加 debug 语句来查看中间值,然后整个气氛是:「哦!提醒一下,这会决定你是否能得到心仪的工作,所以别有任何负担哦」。所以虽然我修改好了,但是用了比正常更多的时间,这让我想到我是不是可能会变成 Atwood 风格的失败招聘故事的新事例?!懊淮?,有个拥有十年经验的人,所谓‘专家’,通过了前两轮电面,结果他居然连这个超级简单的函数都不会写,还花了九牛二虎之力来找到自己的错误。用这题当过滤器真是爽歪歪!”

如果你曾经在一轮技术面试之后感觉糟糕,如果你曾经感觉你彻底失败,是个废物,不该获得任何职位,只想住到远离计算机、技术和那些让你产生这种情绪的招聘流程的话:我真希望我能说一切正在好转。我能说的是,你并不是一个人。我自身的傲慢和想要赶紧完事然后往下继续的不耐烦,是我在那次面试失败的主因。

但是那并不会让最终的结果容易接受,也大概不会让这种面试变成公司有力的工具;这些面试似乎就是因为它们自身的属性而无法避免地会挤走合格的候选人。也就是说:缺乏经验的应聘者更有可能缺乏自信而大脑一片空白;或者花费太多力气来想出惊艳面试官的奇招,以至于最终垂死挣扎,看着无能;而有经验的应聘者很可能(我就是)把这种面试看成烦人的形式主义,只想越快搞定越好(约时间进行编程面试的时候,我甚至还跟招聘方开玩笑说我至少能用六种语言写 FizzBuzz,所以他们就直接告诉我想要哪种吧),面试结果只会符合古希腊人教育我们对于过分自信的期望。

而作为应聘者/候选人,这种面试更是烂。压力太大和缺乏容错空间,总是会让人感觉身体不适。编程面试对精神的虐待也同样糟糕。这真的是一个简单的“来证明你会写 for 循环吧”的题目吗?还是说这是一道藏着面试官想让你发现并阐述的深层问题的陷阱题?这真的只是在考察基本的编程技巧吗?会不会有一些知名的算法或技巧,而你没有的 CS 学位早就会让你滚瓜烂熟,甚至能作为软件共济会的接头暗号?你是不是应该展示你精通这个语言和工具,还是说他们想你开口说出心中所想,来展示你可以好好分析这个问题?如果你能在 A 线诗歌里面藏头打出“FizzBuzz”,面试官会不会对你印象更好?

这些念头会全程萦绕在你的脑海。他们会使你麻痹,抽空你的自信和思考能力,然后让你看上去完全不胜任。但是 $大公司 就是这么干的,他们又大又有钱又成功,所以其他人也会跟着做,留下一片大脑麻痹、毫无自信、犹豫再三再四再七十四的僵尸程序员,他们只会语气平平大声喊“超出递归最大深度”,而那些公司只会全程抱怨为什么就是找不到人才,然后麻烦谁能清理一下这些僵尸吗?

一切都很烂

我曾多次处在招聘双方的处境,我也经历过这个欣欣向荣的软件行业的各个阶段的面试(我似乎平均每五年就要找一轮工作,这让我对各个阶段都有一些有趣的印象)。而我从中学到的只是我们干得太糟糕了??蒲д苎Вㄎ以谘QЧ坏悖┯懈龊苡忻摹盎缥侍狻保喝绾吻终嬲目蒲?,和那些用 看起来是正经科学的字眼 包装起来的伪科学。这个问题,至今仍没有什么灵丹妙药。

软件开发也面临着划界问题,但我们的问题有点不同:我们需要知道的不仅仅是谁已经会写代码,还要知道写得多好,而在那些还不会写的有志之士当中,他们还差多少,还需要多少帮助才能做到(换言之,不仅仅是“我们可以聘用谁”,还有“高低职位分别可以聘用谁”,以及“我们可以招哪个实习生然后给他推荐好的培训日后再聘用他”)。这边也没有灵丹妙药;如果存在的话,我们早就找到了,因为很多天才都花了大量的时间在寻找它。

至今为止,我发现有用的做法总会在其他时候失灵。那包含了审查 GitHub 或其他类似的东西来评估能力;用人际关系和介绍信来找出已经证明自己的人;用对话形式、交换人生故事的面试(也就是面试官和应聘者聊一些看过做过的事,还有他们解决问题的方式);编程面试;“关键词”面试(我参加过一次面试,目标真的就只是看应聘者有没有“说出关键词”,来看他们是不是真的熟悉这个领域);高压面试;低压面试;短合同观察期;实习生返聘计划;团队融入面试;结对编程;黑客马拉松;一对一面试;多对一面试;你再随便想一个吧,肯定被使用过了而且成功率最高只有一半。

因此这对雇主很不利。我应该提到过对应聘者来说也很烂了吧?太多流程都严重有失公允,然后由于面试官和应聘者立场上的鸿沟,这些流程更加糟糕。有时候你甚至不知道有人在评估你(特别是当流程第一环节就是 GitHub 主页筛选的时候),而且被找来主管技术/编程面试的人,经常把这看作一件浪费时间的苦差事,他们不会花时间准备,甚至不会了解一下应聘者,甚至不知道他们来面试什么岗位(我遭遇过好几次这样的情况,我敢说一个连应聘者的简历都懒得看的面试官,是不会让应聘者想要加入他们的)。除此之外,就算是最好的技术面试,也有很强的对抗性因素,这也特别让人不舒服。

但是作为应聘者,不在面试前恶补公司的技术结构,可能加上一些技术面经,包含排序、搜搜算法和怎么计算费米对芝加哥钢琴调音师人数的估计算法的复杂度。应聘者事先不做准备,那就太离谱了。因为就算面试官可以完全不了解应聘者和那个职位,应聘者必须做足功夫,说不定面试官真的会问调音师那道题。

我知道理论上这种非人性化和脱节,是太多人申请技术岗位的副作用;让流程人性化和处理所有申请,这两者不可兼得。但这肯定会让求职者充满苦涩。我真希望,我能感觉我是作为一个将要成为同事的人在接受面试,而不是由可替换齿轮 #7365 作为可替换齿轮 #9540 岗位的面试官,然后由于更多的可替换齿轮在排队面试而时间有限。而且如果你是最早的五千个齿轮,你只能获得股权。

这完全没考虑到人与人的差别,有些人擅长应对形式化的面试,而有些人并不擅长。(这两点都看不出,这个人会在真正的工作环境做得如何;如果看得出的话,那某种程度上,这些面试技巧可以用来申请我并不想要的那种职位。)

那我们该怎么做?

老实说,我根本不知道。技术招聘对各方来说都很烂,而且没有简单的解决方式。甚至都没有能让我们撑到解决方式出炉的权宜之计。不过我还是会提一些东西,只因为洋洋洒洒写 3,000 字吐槽却不提出建议,看上去太糟糕了。

一旦一家公司大到分离出专门的招聘团队或部门时,HR 就会变成应聘者和现有员工双方的痛点。我的意思是应聘者面对的很多招聘者,他们自己都只是刚刚找到工作。这就降低了他们的反应能力以及说服其他人这家公司值得加入的能力,拖慢了整个招聘流程。如果你的招聘团队像旋转门一样很多人进进出出,你就该找出原因并解决问题,保证你放在那里的人真的了解公司,了解你在找的人才,别让任何一方(应聘者或需要信任的团队)空等。说的就是你,上次电话一个礼拜了都还没发送“招聘进度”邮件的某某公司。

当你依靠开发者进行面试时,请负责任地排好班。你已经在占用他们的时间,而且强迫他们切换注意力了;确保他们有足够的时间来不仅仅是打一个 30 分钟的电话,还要浏览应聘者的简历、GitHub 等,了解他们主管的职位的细节。跟一个能说出“我发现你做了/贡献了(项目)”并且能把这个项目跟公司和职位扯上关系的人交谈虽然只是一个小美好,但是小美好可以产生深远的影响?;褂幸繁C媸怨傧胍泵媸怨?;我能判断出对方很明显只想面试赶紧结束然后回到“宏图大计”,这很糟糕。

别搞编程面试,如果可以的话,看看应聘者写过的代码,或者向他们描述你最近遇到的一个小 bug,然后问他们会怎么解决。如果你能相处跟职位相关的问题那就更好了。让应聘者选择在电话上解释,或者写下来发邮件给你。我认识一些能写出神级代码却没办法开口好好解释的人,我也认识擅长开口解释却害怕写哪怕只是零散代码的人;除非你的职位要求特别的演说/写作能力,不然就别偏向任何一边。如果你必须进行编程面试,把用时和压力控制在合理的范围——你家的开发者都未必能在 30 分钟内在面对陌生人电话听写软件输出的情况下解决 bug,那就别强迫应聘者了?;褂?,你可以让讨厌面试的开发者改变心态:“这不是面试,是代码评估”。所有人都能把代码评估“电解”成 Agile? 和 Lean? 等等的关键词。代码评估有开发者渴望的元素!

在所有这些之上最重要的是,请人性化一些。我们不是机器;我们只是让机器做有趣的事情。有时候我们甚至可以让它们做正确而有趣的事情。但我们终究是人类,而现在的招聘流程存在鸿沟般严重的人性化缺失。对人类人性化一些吧,其他所有事情都会轻松很多。

还有,如果你正在寻找可以让机器做有趣事情的人,我还在等待合适的招聘者,所以可以来联系我。

一个技术大牛对程序员招聘的吐槽和建议,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113532/feed/ 0
新贝彩票注册 - 2018 年,程序员要具备哪些核心竞争力? http://www.cswhw.com.cn/113525/ http://www.cswhw.com.cn/113525/#comments Thu, 25 Jan 2018 07:13:32 +0000 http://www.cswhw.com.cn/?p=113525 近日国外开发者平台 HankerRank 发布了 2018 年开发者技能调查报告,本文摘录程序员求职时必备技能相关的调查结果。

2018 年,程序员要具备哪些核心竞争力?,首发于新贝彩票注册。

]]>
近日国外开发者平台 HankerRank 发布了 2018 年开发者技能调查报告,本文摘录程序员求职时必备技能相关的调查结果。

雇主招人时,看中哪些核心竞争力?

  1. 问题解决能力(不管企业大小,都排第1)
  2. 编程语言熟练程度(不管企业大小,排第2)
  3. 调试(不管企业大小,排第3)
  4. 系统设计(综合排第4)
  5. 性能优化(综合排第5)
  6. 剩下见下图

相比中大型公司,小公司更为看中开发者对框架的熟练程度。因为小公司追求快启动,框架有助于开发者更快速地的推送代码。

雇主招人时,看中哪些任职资质?(普通招聘人员角度)

  1. 经历/经验
  2. portfolio/作品集(GitHub是开发者展现个人项目最佳方式之一)
  3. 教育(学历/学位)
  4. 培训(技能认证/证书)
  5. 个人品牌

有一种流行的观点认为,招聘人员更中意有名牌大学?CS 学位的人选。但事实证明,他们实际上关心的是你所做的,而不是你上学的地方。绝大多数的招聘经理表示,他们寻找开发者的技能证明,比如以往工作,多年的经验和项目/ GitHub。无论公司规模大小如何,90% 的招聘人员表示更看中开发者的「以往工作经验」和「多年的经验」。

主管们最看中什么样的任职资质?

  1. portfolio/作品集(GitHub是开发者展现个人项目最佳方式之一)
  2. 以往工作经验
  3. 工作年限
  4. 教育(学历/学位)
  5. 培训(技能认证/证书)
  6. 个人品牌

现在很多公司在招 IT 技术人才时,会查看候选人的 GitHub 上的实际项目,以作为简历之外的技能评估补充。相比多年工作经验,创始人、CTO、VP 等主管人群更看重 GitHub 上的项目。

他们不像普通招聘人员(HR)那样看重「学历/学位」。这可能是因为候选人进入由高管面试轮时,上一轮的 HR 已经筛选过了。到了这一轮时,有更多时间来根据以往项目来评估候选人的技能。

相关文章

2018 开发者技能调查:这些编程语言受欢迎

2018 年,程序员要具备哪些核心竞争力?,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113525/feed/ 1
新贝彩票注册 - 2018 开发者技能调查:这些编程语言受欢迎 http://www.cswhw.com.cn/113526/ http://www.cswhw.com.cn/113526/#respond Thu, 25 Jan 2018 07:07:50 +0000 http://www.cswhw.com.cn/?p=113526 近日国外开发者平台 HankerRank 发布了 2018 年开发者技能调查报告,本文摘录部分和编程语言相关的调查结果。

2018 开发者技能调查:这些编程语言受欢迎,首发于新贝彩票注册。

]]>
近日国外开发者平台 HankerRank 发布了 2018 年开发者技能调查报告,本文摘录部分和编程语言相关的调查结果。

尽管经常有新编程语言出现,但程序员需要掌握核心、传统语言也是非常重要的。 总的来说,在「雇主青睐的编程语言」中,JavaScript、Java、Python、C++、C、C#?和 PHP 排在前位。

所有行业

JavaScript?第一,Java 稍微比 JS 少一点排第二,Python 第三、C++ 第四、C 第五;

汽车 & 运输行业

JS 第一、Java 第二、Python 第三、C++ 第四、C# 第五;

计算机硬件

C 语言和 C++ 的需求量,明显高于其他语言。Python 第三、Java 第四、JS 第五;

金融服务

Java 第一、JS 第二、Python 第三、C# 第四、C++ 第五;

政府

Java 第一、JS 第二、C# 第三

卫生保健

JS 第一、Java 第二、Python 第三、C# 第四

媒体/娱乐/游戏

JS 第一、Python 第二、Java 第三、PHP 第四

零售 & 电商

Java 第一、JS 第二、Python 第三

安全

Java 第一、Python 第二、JS 第三、C++ 第四、C 第五;

技术

Java 第一、JS 第二、Python 第三、C++ 第四、C 第五;

开发者计划学习的编程语言

  1. Go (得益于 Google)
  2. Python
  3. Scala
  4. Kotlin
  5. Ruby
  6. R
  7. Typescript
  8. Swift
  9. Rust
  10. Haskell

2018 开发者技能调查:这些编程语言受欢迎,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113526/feed/ 0
新贝彩票注册 - Linux 下各文件夹的结构说明及用途介绍 http://www.cswhw.com.cn/113519/ http://www.cswhw.com.cn/113519/#respond Tue, 23 Jan 2018 12:07:45 +0000 http://www.cswhw.com.cn/?p=113519 linux下各文件夹的结构说明及用途介绍。

Linux 下各文件夹的结构说明及用途介绍,首发于新贝彩票注册。

]]>
linux下各文件明及用途介

/bin二进制可执行命令。
/dev设备特殊文件。
/etc系统管理和配置文件。
/etc/rc.d启动的配 置文件和脚本。
/home用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示。
/lib标准程序设计库,又 叫动态链接共享库,作用类似windows里的.dll文件。
/sbin系统管理命令,这 里存放的是系统管理员使用的管理程序。
/tmp公用的临时文件存储 点。
/root系统管理员的主目 录。
/mnt系统提供这个目录是 让用户临时挂载其他的文件系统。
/lost+found这个 目录平时是空的,系统非正常关机而留下“无家可归”的文件就在这里。
/proc虚拟的目录,是系 统内存的映射??芍苯臃梦收飧瞿柯祭椿袢∠低承畔?。
/var某些大文件的溢出 区,比方说各种服务的日志文件。
/usr最庞大的目录,要用 到的应用程序和文件几乎都在这个目录。其中包含
/usr/x11r6存放x window的目录。
/usr/bin众多的应用程序。
/usr/sbin超级用户的一些管理程序。
/usr/doclinux文档。
/usr/includelinux下开发和编译应用程序所需要的头文件。
/usr/lib常用的动态链接库和软件包的配置文件。
/usr/man帮助文档。
/usr/src源代码,linux内核的源代码就放在/usr/src/linux 里。
/usr/local/bin本地增加的命令。
/usr/local/lib本地增加的库根文件系统。

通常情况下,根文件系统所占空间一般应该比较小,因为其中的绝大部分文件都不需要经常改动,而且包括严格的文件和一个小的 不经常改变的文件系统不容易损坏。除了可能的一个叫/vmlinuz标准的系统引导映像之外,根目录一般不含任何文 件。所有其他文件在根文件系统的子目录中。
1. /bin
/bin目录包含了引导启动所需的命令或普通用户可能用的命令(可能在引导启动后)。这些命 令都是二进制文件的可执行程序(bin是binary的简称),多是系统中重要的系统文件。
2. /sbin
/sbin目录类似/bin ,也用于存储二进制文件。因为其中的大部分文件多是系统管理员使用的基本的系统程序,所以虽然普通用户必要且允许时可以使用,但一般不给普通用户使 用。
3. /etc
/etc目录存放着各种系统配置文件,其中包括了用户信息文件/etc/passwd, 系统初始化文件/etc/rc等。linux正是靠这些文件才得以正常地运行。
4. /root
/root目录是超级用户的目录。
5. /lib
/lib目录是根文件系统上的程序所需的共享库,存放了根文件系统程序运行所需的共享文件。 这些文件包含了可被许多程序共享的代码,以避免每个程序都包含有相同的子程序的副本,故可以使得可执行文件变得更小,节省空间。
6. /lib/modules
/lib/modules目录包含系统核心可加载各种???,尤其是那些在恢复损坏的系统时重 新引导系统所需的???例如网络和文件系统驱动)。
7. /dev
/dev目录存放了设备文件,即设备驱动程序,用户通过这些文件访问外部设备。比如,用户可 以通过访问/dev/mouse来访问鼠标的输入,就像访问其他文件一样。
8. /tmp
/tmp目录存放程序在运行时产生的信息和数据。但在引导启动后,运行的程序最好使用/var/tmp来 代替/tmp,因为前者可能拥有一个更大的磁盘空间。
9. /boot
/boot目录存放引导加载器(bootstrap loader)使用的文件,如lilo,核心映像也经常放在这里,而不是放在根目录中。但是如果有许多核心映像,这个目录就可能变得很大,这时使用单独的 文件系统会更好一些?;褂幸坏阋⒁獾氖?,要确保核心映像必须在ide硬盘的前1024柱面内。
10. /mnt
/mnt目录是系统管理员临时安装(mount)文件系统的安装点。程序并不自动支持安装到/mnt 。/mnt下面可以分为许多子目录,例如/mnt/dosa可能是使用 msdos文件系统的软驱,而/mnt/exta可能是使用ext2文件系统的软驱,/mnt/cdrom光 驱等等。
11. /proc, /usr, /var, /home
其他文件系统的安装点。

目录树可以分为小的部分,每个部分可以在自己的磁盘或分区上。主要部分是根、/usr?、/var?和?/home?文件系统。每个部分有不同的目的。
每台机器都有根文件系统,它包含系统引导和使其他文件系统得以mount所必要的文件,根文件系统应该有单用户状态所必须的足够的内容?;褂Ω冒ㄐ薷此鸹?系统、恢复备份等的工具。
/usr?文件系统包含所有命令、库、man页和其他一般操作中所需的不改变的文件。?/usr?不应该有 一般使用中要修改的文件。这样允许此文件系统中的文件通过网络共享,这样可以更有效,因为这样节省了磁盘空间(/usr?很容易是数百兆),且易于管理 (当升级应用时,只有主/usr?需要改变,而无须改变每台机器)?即使此文件系统在本地盘上,也可以只读mount,以减少系统崩溃时文件系统的损 坏。
/var?文件系统包含会改变的文件,比如spool目录(mail、news、打印机等用的),?log文件、 formatted?manual?pages和暂存文件。传统上/var?的所有东西曾在?/usr?下的某个地方,但这样/usr?就不可能只读安装 了。
/home?文件系统包含用户家目录,即系统上的所有实际数据。一个大的/home?可能要分为若干文件系统,需要在 /home?下加一级名字,如/home/students?、/home/staff?等。

下面详细介绍:
/etc文件系
/etc目录包含各种系统配置文件,下面说明其中的一些。其他的你应该知道它们属于哪个程序, 并阅读该程序的man页。许多网络配置文件也在/etc中。
1. /etc/rc或/etc/rc.d或/etc/rc?.d:启动、或改变运行级时运 行的脚本或脚本的目录。
2. /etc/passwd用户数据库,其中的域给出了用户名、真实姓名、用户起始目 录、加密口令和用户的其他信息。
3. /etc/fdprm软盘参数表,用以说明不同的软盘格式??捎胹etfdprm进 行设置。更多的信息见setfdprm的帮助页。
4. /etc/fstab指定启动时需要自动安装的文件系统列表。也包括用swapon -a启用的swap区的信息。
5. /etc/group类似/etc/passwd ,但说明的不是用户信息而是组的信息。包括组的各种数据。
6. /etc/inittabinit 的配置文件。
7. /etc/issue包括用户在登录提示符前的输出信息。通常包括系统的一段短说明 或欢迎信息。具体内容由系统管理员确定。
8. /etc/magic“file”的配置文件。包含不同文件格式的说 明,“file”基于它猜测文件类型。
9. /etc/motdmotd是message of the day的缩写,用户成功登录后自动输出。内容由系统管理员确定。
常用于通告信息,如计划关机时间的警告等。
10. /etc/mtab当前安装的文件系统列表。由脚本(scritp)初始化,并由 mount命令自动更新。当需要一个当前安装的文件系统的列表时使用(例如df命令)。
11. /etc/shadow在安装了影子(shadow)口令软件的系统上的影子口令 文件。影子口令文件将/etc/passwd文件中的加密口令移动到/etc/shadow中,而后者只对超级用户(root)可读。这使破译口令更困 难,以此增加系统的安全性。
12. /etc/login.defslogin命令的配置文件。
13. /etc/printcap类似/etc/termcap ,但针对打印机。语法不同。
14. /etc/profile 、/etc/csh.login、/etc/csh.cshrc登 录或启动时bourne或cshells执行的文件。这允许系统管理员为所有用户建立全局缺省环境。
15. /etc/securetty确认安全终端,即哪个终端允许超级用户(root) 登录。一般只列出虚拟控制台,这样就不可能(至少很困难)通过调制解调器(modem)或网络闯入系统并得到超级用户特权。
16. /etc/shells列出可以使用的shell。chsh命令允许用户在本文件 指定范围内改变登录的shell。提供一
台机器ftp服务的服务进程ftpd检查用户shell是否列在/etc/shells文件 中,如果不是,将不允许该用户登录。
17. /etc/termcap终端性能数据库。说明不同的终端用什么“转义序列”控 制。写程序时不直接输出转义
序列(这样只能工作于特定品牌的终端),而是从/etc/termcap中查找要做的工作的 正确序列。这样,多数的程序可以在多数终端上运行。
/dev文件系
/dev
目录包括所有设备的设备文件。设备文件用特定的约定命名,这在设备列表中说明。设备文件在安装时由系 统产生,以后可以用/dev/makedev描述。/dev/makedev.local 是系统管理员为本地设备文件(或连接)写的描述文稿(即如一些非标准设备驱动不是标准makedev 的一部分)。下面简要介绍/dev下 一些常用文件。
1. /dev/console系统控制台,也就是直接和系统连接的监视器。
2. /dev/hdide硬盘驱动程序接口。如:/dev/hda指的是第一个硬 盘,had1则是指/dev/hda的第一个分区。如系统中有其他的硬盘,则依次为/dev /hdb、/dev/hdc、. . . . . .;如有多个分区则依次为hda1、hda2 . . . . . .
3. /dev/sdscsi磁盘驱动程序接口。如系统有scsi硬盘,就不会访问/dev/had, 而会访问/dev/sda。
4. /dev/fd软驱设备驱动程序。如:/dev/fd0指 系统的第一个软盘,也就是通常所说的a盘,/dev/fd1指第二个软盘,. . . . . .而/dev/fd1 h1440则表示访问驱动器1中的4.5高密盘。
5. /dev/stscsi磁带驱动器驱动程序。
6. /dev/tty提供虚拟控制台支持。如:/dev/tty1指 的是系统的第一个虚拟控制台,/dev/tty2则是系统
的第二个虚拟控制台。
7. /dev/pty提供远程登陆伪终端支持。在进行telnet登录时就要用到/dev/pty设 备。
8. /dev/ttys计算机串行接口,对于dos来说就是“com1”口。
9. /dev/cua计算机串行接口,与调制解调器一起使用的设备。
10. /dev/null“黑洞”,所有写入该设备的信息都将消失。例如:当想要将屏幕 上的输出信息隐藏起来
时,只要将输出信息输入到/dev/null中即可。
/usr文件系
/usr是个很重要的目录,通常这一文件系统很大,因为所有程序安装在这里。/usr里 的所有文件一般来自linux发行版;本地安装的程序和其他东西在/usr/local下,因为这样可以在升级新版系 统或新发行版时无须重新安装全部程序。/usr目录下的许多内容是可选的,但这些功能会使用户使用系统更加有效。/usr可容纳许多大型的软件包和它们的 配置文件。下面列出一些重要的目录(一些不太重要的目录被省略了)。
1. /usr/x11r6包含x window系统的所有可执行程序、配置文件和支持文件。为简化x的开发和安装,x的文件没有集成到系统中。x window系统是一个功能强大的图形环境,提供了大量的图形工具程序。用户如果对microsoft windows比较熟悉的话,就不会对x window系统感到束手无策了。
2. /usr/x386类似/usr/x11r6 ,但是是专门给x 11 release 5的。
3. /usr/bin集中了几乎所有用户命令,是系统的软件库。另有些命令在/bin/usr/local/bin中。
4. /usr/sbin包括了根文件系统不必要的系统管理命令,例如多数服务程序。
5. /usr/man、/usr/info、/usr/doc:这些目录包含所有手册页、 gnu信息文档和各种其他文档文件。每个联机手册的“节”都有两个子目录。例如:/usr/man/man1中包含联机手册第一节的源码(没有格式化的原 始文件),/usr/man/cat1包含第一节已格式化的内容。联机手册分为以下九节:内部命令、系统调用、库函数、设备、文件格式、游戏、宏软件包、 系统管理和核心程序。
6. /usr/include包含了c语言的头文件,这些文件多以.h结尾,用来描述c 语言程序中用到的数据结构、
子过程和常量。为了保持一致性,这实际上应该放在/usr/lib下,但习惯上一直沿用了这 个名字。
7. /usr/lib包含了程序或子系统的不变的数据文件,包括一些site – wide配置文件。名字lib来源于库(library); 编程的原始库也存在/usr/lib 里。当编译程序时,程序便会和其中的库进行连接。也有许多程序把配置文件存入其中。
8. /usr/local本地安装的软件和其他文件放在这里。这与/usr很相似。用户 可能会在这发现一些比较大
的软件包,如tex、emacs等。

/var文件系
/var包含系统一般运行时要改变的数据。通常这些数据所在的目录的大小是要经常变化或扩充 的。原来/var目录中有些内容是在/usr中的,但为了保持/usr目录的相对稳定,就把那些需要经常改变的目录放到/var中了。每个系统是特定的, 即不通过网络与其他计算机共享。下面列出一些重要的目录(一些不太重要的目录省略了)。
1. /var/catman包括了格式化过的帮助(man)页。帮助页的源文件一般存在 /usr/man/catman中;有些man页可能有预格式化的版本,存在/usr/man/cat中。而其他的man页在第一次看时都需要格式化,格 式化完的版本存在/var/man中,这样其他人再看相同的页时就无须等待格式化了。(/var/catman经常被 清除,就像清除临时目录一样。)
2. /var/lib存放系统正常运行时要改变的文件。
3. /var/local存放/usr/local中 安装的程序的可变数据(即系统管理员安装的程序)。注意,如果必要,
即使本地安装的程序也会使用其他/var目录,例如/var/lock 。
4. /var/lock锁定文件。许多程序遵循在/var/lock中 产生一个锁定文件的约定,以用来支持他们正在
使用某个特定的设备或文件。其他程序注意到这个锁定文件时,就不会再使用这个设备或文件。
5. /var/log各种程序的日志(log)文件,尤其是login (/var/log/wtmplog纪 录所有到系统的登录和注销) 和syslog (/var/log/messages 纪录存储所有核心和系统程序信息)。/var/log 里的文件经常不确定地增长,应该定期清除。
6. /var/run保存在下一次系统引导前有效的关于系统的信息文件。例如,/var/run/utmp包 含当前登录的用户的信息。
7. /var/spool放置“假脱机(spool)”程序的目录,如mail、 news、打印队列和其他队列工作的目录。每
个不同的spool在/var/spool下有自己的子目录,例如,用户的邮箱就存放在/var/spool/mail 中。
8. /var/tmp比/tmp允许更大的或需要存在较长时间的临时文件。注意系统管理 员可能不允许/var/tmp有很旧的文件。

/proc文件系
/proc文件系统是一个伪的文件系统,就是说它是一个实际上不存在的目录,因而这是一个非 常特殊的目录。它并不存在于某个磁盘上,而是由核心在内存中产生。这个目录用于提供关于系统的信息。下面说明一些最重要的文件和目录(/proc文件系统 在proc man页中有更详细的说明)。
1. /proc/x关于进程x的信息目录,这x是这一进程的标识号。每个进程在 /proc下有一个名为自己进程号的目录。
2. /proc/cpuinfo存放处理器(cpu)的信息,如cpu的类型、制造商、 型号和性能等。
3. /proc/devices当前运行的核心配置的设备驱动的列表。
4. /proc/dma显示当前使用的dma通道。
5. /proc/filesystems核心配置的文件系统信息。
6. /proc/interrupts显示被占用的中断信息和占用者的信息,以及被占用 的数量。
7. /proc/ioports当前使用的i/o端口。
8. /proc/kcore系统物理内存映像。与物理内存大小完全一样,然而实际上没有 占用这么多内存;它仅
仅是在程序访问它时才被创建。(注意:除非你把它拷贝到什么地方,否则/proc下没有任何东西占用任何磁盘空间。)
9. /proc/kmsg核心输出的消息。也会被送到syslog。
10. /proc/ksyms核心符号表。
11. /proc/loadavg系统“平均负载”;3个没有意义的指示器指出系统当前 的工作量。
12. /proc/meminfo各种存储器使用信息,包括物理内存和交换分区 (swap)。
13. /proc/modules存放当前加载了哪些核心??樾畔?。
14. /proc/net网络协议状态信息。
15. /proc/self存放到查看/proc的 程序的进程目录的符号连接。当2个进程查看/proc时,这将会是不同
的连接。这主要便于程序得到它自己的进程目录。
16. /proc/stat系统的不同状态,例如,系统启动后页面发生错误的次数。
17. /proc/uptime系统启动的时间长度。
18. /proc/version核心版本。

/usr/local下一般是你安装软件的目录,这个目录就相当于在windows下的programefiles这个目录?

/opt这个目录是一些大型软件的安装目录,或者是一些服务程序的安装目录

举个例子:刚才装的测试版firefox,就可以装到/opt/firefox_beta目录下,/opt/firefox_beta目录下面就包含了运 行firefox所需要的所有文件、库、数据等等。要删除firefox的时候,你只需删除/opt/firefox_beta目录即可,非常简单。

/usr/local

This is where most manually installed (ie. outside of your package manager) software goes. It has the same structure as /usr. It is a good idea to leave /usr to your package manager and put any custom scripts and things into /usr/local, since nothing important normally lives in /usr/local.

/usr/local

这里主要存放那些手动安装的软件,即 不是通过“新立得”或apt-get安装的软件 。 它和/usr目录具有相类似的目录结构 。让软件包管理器来管理/usr目录,而把自定义的脚本(scripts)放到/usr/local目录下面,我想这应该是个不错的主意。

Linux 下各文件夹的结构说明及用途介绍,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113519/feed/ 0
新贝彩票注册 - 可视化解释压缩算法的工作原理 http://www.cswhw.com.cn/113505/ http://www.cswhw.com.cn/113505/#comments Mon, 22 Jan 2018 13:26:00 +0000 http://www.cswhw.com.cn/?p=113505 压缩技术在生活中到处可见,硬盘上存储数据、发送电视信号、网页传输、流媒体……现代计算几乎没有一个重要领域不使用压缩技术。

可视化解释压缩算法的工作原理,首发于新贝彩票注册。

]]>
压缩技术在生活中无处不在,硬盘上存储数据、发送电视信号、网页传输、流媒体、电子游戏……现代计算几乎没有一个重要领域不使用压缩技术。

那么压缩技术到底是什么?

无论你使用过很多年的电脑压缩软件还是从没想过这个问题,本文将尝试解释,当你压缩一个文件或传输一段视频时,其中的数据到底发生了什么变化。我们将探寻这些重要问题的答案,在此过程中,也许会提出一些新的问题。

  • 对被压缩对象进行压缩,意味着什么?
  • 如何能将目标对象变得比原来更???
  • 如何具体实现压缩技术

让我们来一一解答吧!

via GIPHY

基础知识

在研究压缩技术和数字信息之前,这里有一段通俗易懂的压缩技术介绍。让我们来看看下方的英文字母:

看看我们用来表现这个单词(Tree)的字符,加起来一共是 4 个:

看起来还行。如果我们用汉字会发生什么?

天哪!只用了一个字符!我们有改变它要传达的意思和任何信息么?并没有。但是,我们降低了75%的网页空间,来表达“tree”的含义。那么我们到底做了什么?

没什么神奇的 —— 我们只是用另一种方式去表达了这个含义。我们选择了一种不同的、更加高效的信息表现方式。Spoiler:接下来是本文最重要的部分,请仔细阅读。

那么,如果是像素级的图片呢?

你肯定会觉得惊讶,如何将上面的例子应用于严谨的数字图像数据呢?让我们来看一下最近很流行的一类数据 —— 图片。现阶段,让我们先从简单的像素级图片入手,而不是一上来就尝试去压缩一张高分辨率的 Instagram 图片或其他类似的复杂图片。

不怎么好看对吗?因为这是我自己画的。上面是一个 10*10 的网格,每一种颜色都可以用‘B’、‘Y’和‘G’中的一个字符来表示。

我们怎么用数字化的方式表示上面的图像?以原始的方式存储这张图片的文件可能包含下面的内容:

我们所做的只是从左到右,从上到下,为每个像素写下了代表其颜色的字符。正如你预期的那样,总共会有 100 个字符。我们假设这 100 个字符会占用硬盘上的 100 个字节。这种存储方式,定义了一个合理的存储文件大小上限。任何其他存储方式,只要其文件大小大于上述方法,都是无意义的,或者尝试去存储除了图片数据之外的信息(比如元数据或其他数据)。我想你们应该能认同我的这种观点。

在你往下看之前,开动下你的大脑。如果我让你用少于 100 个字符来表示这张图片,你会怎么做呢?喝一杯茶,仔细想一想,我等着你。

想到什么方法了吗?很好,我也想到了一个。

我准备将我的方法命名为行程长度压缩算法(RLE)??嫘Φ睦?,这个方法不是我想出来的,也不是我命名的。至少从六十年代起,它已经成为了一种基本的压缩技术。我打赌,你们之中有些人刚刚才想出这种方法。

我们将行程长度压缩算法应用于上面的图片。在上方,我们写了很多一连串的相同颜色字符。让我们从那些‘B’字符下手。那么我们能够压缩这些重复的字符么?

当然可以!抛弃下面这种方式:

取而代之:

看起来有戏。通过缩写这一长串相同字符,我们将 17 个字符减少到了 3 个。顺便说下,我们将这些重复的字符串称之为 runs。所以行程长度压缩算法是通过记下 runs 的长度,而不是记下每一个字符,对数据进行压缩编码。这种压缩方式并没有信息丢失。能够解析前一个文件的程序,稍微修改下,就能解析我们的新文件格式。2 者解析出来的图片应该是一样的。

下面的实时 demo 展示了原始图像和它的 2 种存储编码方式:原始版本和行程长度压缩编码版。

通过点击任意像素点,你可以改变其颜色,下方的存储字符也会随之变化。

编注:英文原文此处有 Demo,本文无法再现,请在 http://www.cswhw.com.cn/compression-decompressed 查看。

随着你不断改变原始图像的像素颜色,你会发现我们能够压缩的比例和图片本身有关。如果整张图片只有一种颜色,或者颜色的连续区域很长,我们可以得到很小的输出。使用行程长度压缩算法能够得到的最小存储大小是 4 字节:

当然,这个算法在某些场景下也会表现的十分糟糕。实际上,用这个算法压缩出来的文件,可以比原始一个像素一个像素表示的方式都要大。你会发现,当需要表示‘1B’或’1G’时,它会使用 2 个字符。如果在你的像素图片中,每个颜色的连续长度只有 1 ,会发生什么?

惊讶吧。

是时候学习些术语了。

压缩率

如何衡量我们的压缩算法到底使数据缩小了多少?你可能已经猜到了 —— 计算数据压缩前后的大小比。

比如,我们使用算法将 100 字节的像素图片压缩至 42 字节,那么我们计算出的压缩率为 (100 / 42) ≈ 2.38。最好的情况是只有一种颜色的图片,这种算法的压缩率高达 (100 / 4) = 25!然而,当该算法作用于每个颜色的连续长度只有 1 的图片上时,压缩率只有 (100 / 200) = 0.5。Protip:压缩率小于 1 简直是糟糕透了。

我们可以看出,这种基础 RLE 算法的压缩率对于输入的数据结构十分敏感。对于这类简单的算法,这种现象很常见。该算法对于数据的结构做了若干假设,如果要使该算法能够输出理想结果,原始输入数据中必须存在重复相邻的相同字节。一个更智能的 RLE 算法实现可能会尝试使用重复的子串来对数据进行压缩编码。

甚至我直接用英语文字描述这张图片,压缩率都比 2 要大!运用这种方法,可以将数据压缩存储成一种友好、简洁的文件格式,相比第一次尝试我们又迈出了一小步。

数据到底能被压缩到多???

这是一个很大很宽泛的问题。当然,人们认为,对于任何输入数据,一个合理设计的压缩算法,应该至少能将数据压缩那么一点(这里的一点点,既指口语上的,也表示学术上的)。

不幸的是,事情并没有那么简单。假设我们有一个算法 A,对于任何的输入,能够使压缩率始终严格大于 1。对于某些输入,压缩率可以为 2.5;对于另一些输入,压缩率可能为 1.000000002。

如果这种算法存在,我们可以无限迭代调用它。对于某个输入,我们计算 A(A(A(data))),对每一次的输出不断调用 A()。我们每调用一次,数据的大小至少会被压缩一点点。不难看出,到最后,我们能将数据压缩至 1 字节,甚至 0 字节?

这看起来不太现实。事实也确实如此。我们甚至不需要使用递归法去证明该算法的可行性,试想下这种情况:有 9 个不同的文件,没有任何方法能够在不丢失数据的情况下,将这 9 个文件都压缩至 3 字节。

3 个字节一共只能表示 8 种不同的数据:000、001、010、100、011、101、110、111。即使我们有某个十分强大的压缩算法,能够将前 8 个文件分别压缩成前面这 8 种字节表示,第 9 个文件也只能压缩为其中之一。对于该算法,任意 8 个以上的未压缩数据片段,都无法找到更多不同的 3 个字节来表示。

这里有一条重要的原则:对常见数据的压缩,任何算法的压缩率都有严格的限制。你可以不断地使用某个算法对数据进行压缩,直到无法将数据压缩得更小,然后换种算法继续尝试。这种做法也许会将数据压缩得更?。ㄊ导噬?,很多线上的软件都是这么做的),但最终,你会遇到你永远无法再次压缩的数据。其实,你对不同的算法的重复调用,到头来又变成了另一种压缩算法。这条规则现在仍然适用。

柯氏复杂性

看到下面你也许会更加失望。对于压缩率的大小,不仅仅在算法上有着理论的限制 —— 数据本身的复杂度对其也会有很大的影响

让我们来看下下面的 2 个字符串:

和:

2 者是完全相同的长度,但是,你可以很轻易地看出来,后者明显要更加复杂。说的更具体点,使用 RLE 压缩算法,我们可以将第一个字符串压缩至最多 3 个字符(“24a”)。

柯氏复杂性(一位苏联数学家?Andrey Nikolaevich Kolmogorov?的伟大发明)将上述内容阐述地很好。当然,一个事物的度量方式有很多种,柯氏复杂性是一种比较不错的度量方式。数据的柯氏复杂性是指,通过计算机程序输出的,能够描述这个字符串的最短长度。

显然,对于柯氏复杂性,任何字符串‘S’的长度上界就是其本身。上述说法将算法进行了一定的简化,其实数据的柯氏复杂性还需加上整个程序的长度 —— 包括解释器或编译后的代码。但是就本文讨论的范围来说,没有必要。直接把它认为是你能生成的该数据的最短长度。

柯氏复杂性对于你选择什么编程语言并不是很敏感。程序语言的选择只会对复杂度的一个常数因子产生影响。下面这句话很重要:无论你选择什么语言来描述数据,所带来的长度变化是有限的。有些数据就是需要比一百万个绿色像素点更多的空间来表示,怎么也减少不了。

数据丢失

但是,别放弃希望。我们之前讨论的都是无损压缩。无损压缩是指,通过压缩之后的数据,能够完全还原压缩之前的原始数据。也就是说,如果 C 是我们的压缩算法,D 是相应的解压缩算法,D(C(x)) = x 对于任何输入数据 x 永远成立。

无损压缩是十分有用的!当压缩一些文献或博文、税收档案、低分辨率的像素图片等类似的文本数据时,你肯定想要做到无损压缩。对于这些数据,保证数据的精确和每个字符的顺序,是很重要的。

但是也有其他选择。有损压缩是指,不保证压缩的数据解压之后与压缩之前的数据完全一致。这种压缩算法十分常见。

有损压缩应用十分广泛。人类的感官对于一些微小错误或瑕疵是比较有容忍度的。数据丢失主要体现在压缩图片、音频(或视频)文件时。

需要例子吗?请看下面 2 张奥巴马的图片。

第一张图片是大小约为 335 千字节的 PNG 文件(PNG 是一种无损图片压缩格式)。这将作为我们的参照物。

第二张图片,是第一张图片保存为 JPEG 格式的结果,这是一种会丢失许多数据的有损压缩。第二张图片的大小约为 22 千字节,相比原始图片,压缩率约为 15,这么大的压缩率并不表示数据丢失会很严重。

你能看出这 2 张图片的区别么?也许能看出一点点。如果你尽可能靠近你的屏幕,眯起眼睛,转头环视下这张图片。接着你去看他的头发细节,一根一根地数头发,在没有头发的地方你会发现一些模糊。关键点不在于第二张图是不是一个完美的复制品,而在于它是不是足够好用。当你通过互联网传输数据时,十五倍的压缩率比起一张毫无损失的 PNG 图片更有价值。

但这并不是说在任何情况下,它都如此出色。为了达到这种压缩效果,JPEG 必须丢掉很多数据,尽管同时它尽力避免丢失太多数据,但是你可以尝试探索下它的极限。通过下面的实时 demo,你可以看出 JPEG 格式的图片质量下限能到多少。同时在图片清晰度变得无法容忍之前,注意看下图片质量是多少。像我之前说的那样,人类的视觉容忍度是很高的。

编注:英文原文此处有一个 Demo,本文无法再现,请在?http://www.cswhw.com.cn/compression-decompressed 查看

像 Netflix 和 YouTube 上的视频流服务,以及 Spotify 和 Soundcloud 上的音频流服务,都是使用的有损压缩?;撼寤蜓映偈且桓鲇没薹ㄈ淌艿?,所以在保证音视频质量的同时,这些服务尽可能地去压缩数据。你经?;峥吹绞莸亩顾?, 一开始视频会比较模糊,当检测到你的网络速度可以接受更小的压缩率时,视频的清晰度会随之提高。

看到下面这张来自 Giphy 网站上的动图了么?数据的动态压缩在这里同样适用??纯此鞘侨绾未硗俾那榭鱿碌亩技釉兀淮?,我在 Giphy 网站上将这个加载过程做成了一张动图,并将它嵌入了进来,看出什么问题了么?):

via GIPHY

看起来很奇怪对么?首先,他们加载了这张动图的第一帧低清晰度图片。接着,当更大的数据传输过来后,出现了动图。但是还不完全,只有仅仅几帧。然后,越来越多帧图片被传输了过来,直到最后完全加载整张动图。

这就是现代的流媒体压缩技术:混合的压缩策略几乎完全是为了,以尽可能少的字节(大小越小,时间也越短),提供给用户流畅的内容。针对文件的无损压缩技术,比如上面说到的 RLE,也有用武之地,而且它仍然是很多最好的桌面文件压缩工具的核心???。但是,多亏了有损压缩,你才能在电视上流畅地观看《权利的游戏》。

数据压缩无处不在

关于压缩技术本文我们就先介绍到这里,但这只是冰山一角。

我们学习了压缩技术的基本思想,从这些技术中得出了一条很重要的哲学道理:

图像,文字,视频,音乐 —— 任何数据都没有唯一正确的表现形式。区别只是在于有多少种表现数据的有效方式。

压缩技术就是不断寻找更加有效的方式来存储你的数据,最强大的压缩算法,对于任何数据,它都能找到一种高效的方法对其进行压缩。

感谢阅读,如果你认可我在文中制作的那些实时 demo,请随时与你的朋友分享。

可视化解释压缩算法的工作原理,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113505/feed/ 1
新贝彩票注册 - 汇编语言入门教程 http://www.cswhw.com.cn/113509/ http://www.cswhw.com.cn/113509/#respond Sun, 21 Jan 2018 13:19:24 +0000 http://www.cswhw.com.cn/?p=113509 汇编语言不容易学习,就连简明扼要的介绍都很难找到。下面我尝试写一篇最好懂的汇编语言教程,解释 CPU 如何执行代码。

汇编语言入门教程,首发于新贝彩票注册。

]]>
学习编程其实就是学高级语言,即那些为人类设计的计算机语言。

但是,计算机不理解高级语言,必须通过编译器转成二进制代码,才能运行。学会高级语言,并不等于理解计算机实际的运行步骤。

计算机真正能够理解的是低级语言,它专门用来控制硬件?;惚嘤镅跃褪堑图队镅?,直接描述/控制 CPU 的运行。如果你想了解 CPU 到底干了些什么,以及代码的运行步骤,就一定要学习汇编语言。

汇编语言不容易学习,就连简明扼要的介绍都很难找到。下面我尝试写一篇最好懂的汇编语言教程,解释 CPU 如何执行代码。

一、汇编语言是什么?

我们知道,CPU 只负责计算,本身不具备智能。你输入一条指令(instruction),它就运行一次,然后停下来,等待下一条指令。

这些指令都是二进制的,称为操作码(opcode),比如加法指令就是00000011。编译器的作用,就是将高级语言写好的程序,翻译成一条条操作码。

对于人类来说,二进制程序是不可读的,根本看不出来机器干了什么。为了解决可读性的问题,以及偶尔的编辑需求,就诞生了汇编语言。

汇编语言是二进制指令的文本形式,与指令是一一对应的关系。比如,加法指令00000011写成汇编语言就是 ADD。只要还原成二进制,汇编语言就可以被 CPU 直接执行,所以它是最底层的低级语言。

二、来历

最早的时候,编写程序就是手写二进制指令,然后通过各种开关输入计算机,比如要做加法了,就按一下加法开关。后来,发明了纸带打孔机,通过在纸带上打孔,将二进制指令自动输入计算机。

为了解决二进制指令的可读性问题,工程师将那些指令写成了八进制。二进制转八进制是轻而易举的,但是八进制的可读性也不行。很自然地,最后还是用文字表达,加法指令写成 ADD。内存地址也不再直接引用,而是用标签表示。

这样的话,就多出一个步骤,要把这些文字指令翻译成二进制,这个步骤就称为 assembling,完成这个步骤的程序就叫做 assembler。它处理的文本,自然就叫做 aseembly code。标准化以后,称为 assembly language,缩写为 asm,中文译为汇编语言。

每一种 CPU 的机器指令都是不一样的,因此对应的汇编语言也不一样。本文介绍的是目前最常见的 x86 汇编语言,即 Intel 公司的 CPU 使用的那一种。

三、寄存器

学习汇编语言,首先必须了解两个知识点:寄存器和内存模型。

先来看寄存器。CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存?;旧?,CPU 缓存可以看作是读写速度较快的内存。

但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的。有人比喻寄存器是 CPU 的零级缓存。

四、寄存器的种类

早期的 x86 CPU 只有8个寄存器,而且每个都有不同的用途。现在的寄存器已经有100多个了,都变成通用寄存器,不特别指定用途了,但是早期寄存器的名字都被保存了下来。

  • EAX
  • EBX
  • ECX
  • EDX
  • EDI
  • ESI
  • EBP
  • ESP

上面这8个寄存器之中,前面七个都是通用的。ESP 寄存器有特定用途,保存当前 Stack 的地址(详见下一节)。

我们常??吹?32位 CPU、64位 CPU 这样的名称,其实指的就是寄存器的大小。32 位 CPU 的寄存器大小就是4个字节。

五、内存模型:Heap

寄存器只能存放很少量的数据,大多数时候,CPU 要指挥寄存器,直接跟内存交换数据。所以,除了寄存器,还必须了解内存怎么储存数据。

程序运行的时候,操作系统会给它分配一段内存,用来储存程序和运行产生的数据。这段内存有起始地址和结束地址,比如从0x10000x8000,起始地址是较小的那个地址,结束地址是较大的那个地址。

程序运行过程中,对于动态的内存占用请求(比如新建对象,或者使用malloc命令),系统就会从预先分配好的那段内存之中,划出一部分给用户,具体规则是从起始地址开始划分(实际上,起始地址会有一段静态数据,这里忽略)。举例来说,用户要求得到10个字节内存,那么从起始地址0x1000开始给他分配,一直分配到地址0x100A,如果再要求得到22个字节,那么就分配到0x1020。

这种因为用户主动请求而划分出来的内存区域,叫做 Heap(堆)。它由起始地址开始,从低位(地址)向高位(地址)增长。Heap 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。

六、内存模型:Stack

除了 Heap 以外,其他的内存占用叫做 Stack(栈)。简单说,Stack 是由于函数运行而临时占用的内存区域。

请看下面的例子。

int main() {
   int a = 2;
   int b = 3;
}

上面代码中,系统开始执行main函数时,会为它在内存里面建立一个?。╢rame),所有main的内部变量(比如ab)都保存在这个帧里面。main函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。

如果函数内部调用了其他函数,会发生什么情况?

int main() {
   int a = 2;
   int b = 3;
   return add_a_and_b(a, b);
}

上面代码中,main函数内部调用了add_a_and_b函数。执行到这一行的时候,系统也会为add_a_and_b新建一个帧,用来储存它的内部变量。也就是说,此时同时存在两个?。?code>main和add_a_and_b。一般来说,调用栈有多少层,就有多少帧。

等到add_a_and_b运行结束,它的帧就会被回收,系统会回到函数main刚才中断执行的地方,继续往下执行。通过这种机制,就实现了函数的层层调用,并且每一层都能使用自己的本地变量。

所有的帧都存放在 Stack,由于帧是一层层叠加的,所以 Stack 叫做栈。生成新的帧,叫做”入栈”,英文是 push;栈的回收叫做”出栈”,英文是 pop。Stack 的特点就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束运行),这就叫做”后进先出”的数据结构。每一次函数执行结束,就自动释放一个帧,所有函数执行结束,整个 Stack 就都释放了。

Stack 是由内存区域的结束地址开始,从高位(地址)向低位(地址)分配。比如,内存区域的结束地址是0x8000,第一帧假定是16字节,那么下一次分配的地址就会从0x7FF0开始;第二帧假定需要64字节,那么地址就会移动到0x7FB0。

七、CPU 指令

7.1 一个实例

了解寄存器和内存模型以后,就可以来看汇编语言到底是什么了。下面是一个简单的程序example.c。

int add_a_and_b(int a, int b) {
   return a + b;
}

int main() {
   return add_a_and_b(2, 3);
}

gcc 将这个程序转成汇编语言。

$ gcc -S example.c

上面的命令执行以后,会生成一个文本文件example.s,里面就是汇编语言,包含了几十行指令。这么说吧,一个高级语言的简单操作,底层可能由几个,甚至几十个 CPU 指令构成。CPU 依次执行这些指令,完成这一步操作。

example.s经过简化以后,大概是下面的样子。

_add_a_and_b:
   push   %ebx
   mov    %eax, [%esp+8] 
   mov    %ebx, [%esp+12]
   add    %eax, %ebx 
   pop    %ebx 
   ret  

_main:
   push   3
   push   2
   call   _add_a_and_b 
   add    %esp, 8
   ret

可以看到,原程序的两个函数add_a_and_bmain,对应两个标签_add_a_and_b_main。每个标签里面是该函数所转成的 CPU 运行流程。

每一行就是 CPU 执行的一次操作。它又分成两部分,就以其中一行为例。

push   %ebx

这一行里面,push是 CPU 指令,%ebx是该指令要用到的运算子。一个 CPU 指令可以有零个到多个运算子。

下面我就一行一行讲解这个汇编程序,建议读者最好把这个程序,在另一个窗口拷贝一份,省得阅读的时候再把页面滚动上来。

7.2 push 指令

根据约定,程序从_main标签开始执行,这时会在 Stack 上为main建立一个帧,并将 Stack 所指向的地址,写入 ESP 寄存器。后面如果有数据要写入main这个帧,就会写在 ESP 寄存器所保存的地址。

然后,开始执行第一行代码。

push   3

push指令用于将运算子放入 Stack,这里就是将3写入main这个帧。

虽然看上去很简单,push指令其实有一个前置操作。它会先取出 ESP 寄存器里面的地址,将其减去4个字节,然后将新地址写入 ESP 寄存器。使用减法是因为 Stack 从高位向低位发展,4个字节则是因为3的类型是int,占用4个字节。得到新地址以后, 3 就会写入这个地址开始的四个字节。

push   2

第二行也是一样,push指令将2写入main这个帧,位置紧贴着前面写入的3。这时,ESP 寄存器会再减去 4个字节(累计减去8)。

7.3 call 指令

第三行的call指令用来调用函数。

call   _add_a_and_b

上面的代码表示调用add_a_and_b函数。这时,程序就会去找_add_a_and_b标签,并为该函数建立一个新的帧。

下面就开始执行_add_a_and_b的代码。

push   %ebx

这一行表示将 EBX 寄存器里面的值,写入_add_a_and_b这个帧。这是因为后面要用到这个寄存器,就先把里面的值取出来,用完后再写回去。

这时,push指令会再将 ESP 寄存器里面的地址减去4个字节(累计减去12)。

7.4 mov 指令

mov指令用于将一个值写入某个寄存器。

mov    %eax, [%esp+8]

这一行代码表示,先将 ESP 寄存器里面的地址加上8个字节,得到一个新的地址,然后按照这个地址在 Stack 取出数据。根据前面的步骤,可以推算出这里取出的是2,再将2写入 EAX 寄存器。

下一行代码也是干同样的事情。

mov    %ebx, [%esp+12]

上面的代码将 ESP 寄存器的值加12个字节,再按照这个地址在 Stack 取出数据,这次取出的是3,将其写入 EBX 寄存器。

7.5 add 指令

add指令用于将两个运算子相加,并将结果写入第一个运算子。

add    %eax, %ebx

上面的代码将 EAX 寄存器的值(即2)加上 EBX 寄存器的值(即3),得到结果5,再将这个结果写入第一个运算子 EAX 寄存器。

7.6 pop 指令

pop指令用于取出 Stack 最近一个写入的值(即最低位地址的值),并将这个值写入运算子指定的位置。

pop    %ebx

上面的代码表示,取出 Stack 最近写入的值(即 EBX 寄存器的原始值),再将这个值写回 EBX 寄存器(因为加法已经做完了,EBX 寄存器用不到了)。

注意,pop指令还会将 ESP 寄存器里面的地址加4,即回收4个字节。

7.7 ret 指令

ret指令用于终止当前函数的执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收。

ret

可以看到,该指令没有运算子。

随着add_a_and_b函数终止执行,系统就回到刚才main函数中断的地方,继续往下执行。

add    %esp, 8

上面的代码表示,将 ESP 寄存器里面的地址,手动加上8个字节,再写回 ESP 寄存器。这是因为 ESP 寄存器的是 Stack 的写入开始地址,前面的pop操作已经回收了4个字节,这里再回收8个字节,等于全部回收。

ret

最后,main函数运行结束,ret指令退出程序执行。

八、参考链接

汇编语言入门教程,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113509/feed/ 0
新贝彩票注册 - 当你在 Linux 上启动一个进程时会发生什么? http://www.cswhw.com.cn/113506/ http://www.cswhw.com.cn/113506/#comments Sat, 20 Jan 2018 12:26:45 +0000 http://www.cswhw.com.cn/?p=113506 本文是关于 fork 和 exec 是如何在 Unix 上工作的。你或许已经知道,也有人还不知道。几年前当我了解到这些时,我惊叹不已。

当你在 Linux 上启动一个进程时会发生什么?,首发于新贝彩票注册。

]]>
本文是关于 fork 和 exec 是如何在 Unix 上工作的。你或许已经知道,也有人还不知道。几年前当我了解到这些时,我惊叹不已。

我们要做的是启动一个进程。我们已经在博客上讨论了很多关于系统调用的问题,每当你启动一个进程或者打开一个文件,这都是一个系统调用。所以你可能会认为有这样的系统调用:

start_process(["ls", "-l", "my_cool_directory"])

这是一个合理的想法,显然这是它在 DOS 或 Windows 中的工作原理。我想说的是,这并不是 Linux 上的工作原理。但是,我查阅了文档,确实有一个 posix_spawn 的系统调用基本上是这样做的,不过这不在本文的讨论范围内。

fork 和 exec

Linux 上的 posix_spawn 是通过两个系统调用实现的,分别是 forkexec(实际上是 execve),这些都是人们常常使用的。尽管在 OS X 上,人们使用 posix_spawn,而 forkexec 是不提倡的,但我们将讨论的是 Linux。

Linux 中的每个进程都存在于“进程树”中。你可以通过运行 pstree 命令查看进程树。树的根是 init,进程号是 1。每个进程(init 除外)都有一个父进程,一个进程都可以有很多子进程。

所以,假设我要启动一个名为 ls 的进程来列出一个目录。我是不是只要发起一个进程 ls 就好了呢?不是的。

我要做的是,创建一个子进程,这个子进程是我(me)本身的一个克隆,然后这个子进程的“脑子”被吃掉了,变成 ls。

开始是这样的:

my parent
    |- me

然后运行 fork(),生成一个子进程,是我(me)自己的一份克?。?/p>

my parent
    |- me
       |-- clone of me

然后我让该子进程运行 exec("ls"),变成这样:

my parent
    |- me
       |-- ls

当 ls 命令结束后,我几乎又变回了我自己:

my parent
    |- me
       |-- ls (zombie)

在这时 ls 其实是一个僵尸进程。这意味着它已经死了,但它还在等我,以防我需要检查它的返回值(使用 wait 系统调用)。一旦我获得了它的返回值,我将再次恢复独自一人的状态。

my parent
    |- me

fork 和 exec 的代码实现

如果你要编写一个 shell,这是你必须做的一个练习(这是一个非常有趣和有启发性的项目。Kamal 在 Github 上有一个很棒的研讨会:http://www.cswhw.com.cn/kamalmarhubi/shell-workshop)。

事实证明,有了 C 或 Python 的技能,你可以在几个小时内编写一个非常简单的 shell,像 bash 一样。(至少如果你旁边能有个人多少懂一点,如果没有的话用时会久一点。)我已经完成啦,真的很棒。

这就是 forkexec 在程序中的实现。我写了一段 C 的伪代码。请记住,fork 也可能会失败哦。

int pid = fork();
// 我要分身啦
// “我”是谁呢?可能是子进程也可能是父进程
if (pid == 0) {
    // 我现在是子进程
    // “ls” 吃掉了我脑子,然后变成一个完全不一样的进程
    exec(["ls"])
} else if (pid == -1) {
    // 天啊,fork 失败了,简直是灾难!
} else {
    // 我是父进程耶
    // 继续做一个酷酷的美男子吧
    // 需要的话,我可以等待子进程结束
}

上文提到的“脑子被吃掉”是什么意思呢?

进程有很多属性:

  • 打开的文件(包括打开的网络连接)
  • 环境变量
  • 信号处理程序(在程序上运行 Ctrl + C 时会发生什么?)
  • 内存(你的“地址空间”)
  • 寄存器
  • 可执行文件(/proc/$pid/exe
  • cgroups 和命名空间(与 Linux 容器相关)
  • 当前的工作目录
  • 运行程序的用户
  • 其他我还没想到的

当你运行 execve 并让另一个程序吃掉你的脑子的时候,实际上几乎所有东西都是相同的! 你们有相同的环境变量、信号处理程序和打开的文件等等。

唯一改变的是,内存、寄存器以及正在运行的程序,这可是件大事。

为何 fork 并非那么耗费资源(写入时复制)

你可能会问:“如果我有一个使用了 2GB 内存的进程,这是否意味着每次我启动一个子进程,所有 2 GB 的内存都要被复制一次?这听起来要耗费很多资源!”

事实上,Linux 为 fork() 调用实现了写时复制copy on write,对于新进程的 2GB 内存来说,就像是“看看旧的进程就好了,是一样的!”。然后,当如果任一进程试图写入内存,此时系统才真正地复制一个内存的副本给该进程。如果两个进程的内存是相同的,就不需要复制了。

为什么你需要知道这么多

你可能会说,好吧,这些细节听起来很厉害,但为什么这么重要?关于信号处理程序或环境变量的细节会被继承吗?这对我的日常编程有什么实际影响呢?

有可能哦!比如说,在 Kamal 的博客上有一个很有意思的 bug。它讨论了 Python 如何使信号处理程序忽略了 SIGPIPE。也就是说,如果你从 Python 里运行一个程序,默认情况下它会忽略 SIGPIPE!这意味着,程序从 Python 脚本和从 shell 启动的表现会有所不同。在这种情况下,它会造成一个奇怪的问题。

所以,你的程序的环境(环境变量、信号处理程序等)可能很重要,都是从父进程继承来的。知道这些,在调试时是很有用的。

当你在 Linux 上启动一个进程时会发生什么?,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113506/feed/ 2
新贝彩票注册 - 10 个用于 AI 开发的框架和库 http://www.cswhw.com.cn/113499/ http://www.cswhw.com.cn/113499/#comments Fri, 19 Jan 2018 08:14:55 +0000 http://www.cswhw.com.cn/?p=113499 本文将介绍那些用于 AI 开发的高质量库,并谈谈它们的优缺点,以及特性。

10 个用于 AI 开发的框架和库,首发于新贝彩票注册。

]]>
尽管人工智能(AI )已经存在很长时间了,但因为这一领域取得的巨大进步,它最近成为了一个流行词。

AI 曾被认为是狂热爱好者和天才的专属领域,但由于各种库和框架的蓬勃发展,它慢慢成为了一个不那么排外的 IT 领域,并吸引了大量的人才投入其中。

在本文中,我们将介绍那些用于 AI 开发的高质量库,并谈谈它们的优缺点,以及特性。

现在,让我们进入并探索 AI 库的世界吧。


TensorFlow

“使用数据流程图对可拓展的机器学习进行计算”

How does a deep learning network work?

语言:C++

84 725 ★

初接触 AI 时,你听说的首批框架应该包含了谷歌的 TensorFlow。

TensorFlow 是一个使用数据流程图进行数值计算的开源软件。这个不错的框架因其架构而闻名,它允许在任何 CPU 或 GPU 上进行计算,不管是桌面、服务器,还是移动设备。它可在 Python 编程语言中使用。

TensorFlow 主要是通过数据层进行排序,而我们可以调用节点,并根据所得到的信息进行决策。点击查看!

Deep learning concept of Tensorflow

优点:

  • 使用简单易学的语言,如 Python。
  • 使用计算图进行抽象。
  • 可以使用 TensorBoard 获得可视化。

缺点:

  • 运行速度慢,因为 Python 不是最快的语言。
  • 缺乏许多预训练的模型。
  • 不完全开源。

Microsoft CNTK

“开源的深度学习工具包”

Microsoft Cognitive Toolkit

语言:C++

13 516 ★

我们是否可以将它看作是微软对谷歌 TensorFlow 的回应?

微软的?CNTK(计算网络工具包)是一个用来增强??榛捅3旨扑阃绶掷氲目?,提供学习算法和模型描述。

在需要大量服务器进行计算的情况下,CNTK 可以同时利用多台服务器。

据说 CNTK 在功能上接近谷歌的 TensorFlow,但速度比对方要快一些。了解更多。

Microsoft CNTK architecture

优点:

  • 高度灵活。
  • 允许分布式训练。
  • 支持 C++、C#、Java 和 Python。

缺点:

  • 它由一种新的语言——NDL(网络描述语言)实现。
  • 缺乏可视化。

Theano

“数值计算库”
Theano framework

语言:Python

7 550 ★

作为 TensorFlow 的强有力竞争对手,Theano 是一个强大的 Python 库,它允许使用高效多维数组进行数值计算。

它不使用 CPU,而是透明地使用 GPU,用于数据密集型计算,所以效率很高。

因此,在大约 10 年内,Theano 一直被用于大规模的数据密集型计算。

然而,在 2017 年 9 月 28 日当日,开发团队宣称,将在 2017 年 11 月 15 日发布 1.0 版后,停止对它的主要开发。

但这并没有削弱它的强大实力,你仍可以使用它,随时进行深入学习的研究。了解更多。

d3viz: Interactive visualization of Theano compute graphs

优点:

  • 对 CPU 和 GPU 进行了适当优化。
  • 高效的数值计算任务。

缺点:

  • 与其他库相比,原始的 Theano 有点儿低级。
  • 需要与其他库一起使用,以获得较高级的抽象。
  • 在 AWS 上使用有点小 Bug。

Caffe

“应对深入学习的快速开放架构”
Caffe machine learning framework

语言:C++

22 111 ★

Caffe 是一个强大的深度学习框架。

和这个列表中的其他框架一样,它对于深入学习的研究而言,是非??焖俸陀行У?。

使用 Caffe,你可以轻易地构建一个用于图像分类的 CNN(卷积神经网络)。它在 GPU 上运行良好,使得运行速度非???。查看主页。
Caffe main classes

上图是 Caffe 的主类。

优点:

  • 可以与 Python 和 MATLAB 绑定使用。
  • 高性能。
  • 无需编写代码,即可训练模型。

缺点:

  • 对递归网络支持不好。
  • 对新架构来说不是很好。

Keras

“针对人类的深度学习”
Keras frameowork

语言:Python

23 711 ★

Keras 是一个用 Python 编写的开源神经网络库。

不似?TensorFlow、CNTK、Theano、Keras 这种端到端(End-to-End)的机器学习框架,

相反,它是一个接口,提供了高层次的抽象,使得神经网络的配置变得更加简单,而不必考虑所在的框架。

谷歌的 TensorFlow 目前支持 Keras 作为后端,而微软的 CNTK 也将在短时间内获得支持。了解更多。

Keras Cheat Sheet: Neural Networks in Python

优点:

  • 它对用户友好,易于上手。
  • 高度拓展。
  • 可以在 CPU 或 GPU 上无缝运行。
  • 完美兼容 Theano 和 TensorFlow。

缺点:

  • 不能有效地作为一个独立的框架来使用。

Torch

“开源机器学习库”
Torch framework

语言:C

7 584 ★

Torch 是一个用于科学计算和数值计算的开源机器学习库。

它是一个基于? Lua 编程语言(终于不再是 Python)的库。

通过提供大量算法,使得深入学习的研究更加容易,并提高了效率和速度。它有一个强大的 N 维数组,帮助进行类似切片和索引这样的计算,并提供线性代数程序和神经网络模型。了解更多。

Torch - convolutional network, for natural images

优点:

  • 高度灵活。
  • 速度快,效率高。
  • 大量的预训练模型可用。

缺点:

  • 说明文档不够清晰。
  • 缺乏立即使用的即插即用代码。
  • 它基于一个不怎么流行的编程语言 Lua。

Accord.NET

“针对 .NET 的机器学习、计算机视觉、统计学和通用科学计算”
Accord.net machine learning framework

语言:C#

2 424 ★

这是为 C# 程序员准备的。

Accord.NET 框架是一个 .NET 机器学习框架,使得音频和图像的处理变得更加简单。

该框架可以有效地解决数值优化、人工神经网络,甚至给出了可视化的特征。此外,Accord.NET 对计算机视觉和信号处理具有强大的功能,并且易于算法实现。查看主页。

Machine learning samples

优点:

  • 它拥有一个庞大且活跃的开发团队。
  • 说明文档非常不错。
  • 高质量的可视化。

缺点:

  • 这不是一个非常流行的框架。
  • 与 TensorFlow 相比,速度慢。

Spark MLlib

“可扩展的机器学习库”
Spark MLlib runs everywhere

语言:Scala

15 708 ★

Apache 的 Spark MLlib 是一个具有高度拓展性的机器学习库。

它在 Java、Scala、Python 甚至 R 语言中都非常有用,因为它使用 Python 和 R 中类似 Numpy 这样的库,能够进行高效的交互。

MLlib 可以很容易地插入 Hadoop 工作流程中。它提供了机器学习算法,如分类、回归、聚类等。

这个强大的库在处理大规模的数据时,速度非???。在网站上了解更多。

MLlib pipeline example

优点:

  • 对于大规模数据处理来说,非???。
  • 可用于多种语言。

缺点:

  • 陡峭的学习曲线。
  • 仅 Hadoop 支持即插即用。

Sci-Kit Learn

“Python 中的机器学习”

Choosing the right estimator

语言:Python

24 369 ★

Sci-kit learn 是一个针对机器学习的强大 Python 库,主要用于构建模型。

使用诸如 Numpy、SciPy 和 Matplotlib 等其他库构建,对于统计建模技术(如分类、回归、集群等)非常有效。

Sci-Kit learn的特性包括监督式学习算法、非监督式学习算法和交叉验证。点击查看。

Varying regularization in Multi-layer Perceptron

优点:

  • 可以使用许多 shell 算法。
  • 高效的数据挖掘。

缺点:

  • 不是最好的模型构建库。
  • GPU 使用不高效。

MLPack

“可扩展的 C++ 机器学习库”
MLPack framework

语言:C++

1 856 ★

MLPack 是一个使用 C++ 实现的可扩展的机器学习库。在 C++ 中,你可以猜到,它的内存管理非常出色。

拥有高质量的机器学习算法与库,MLPack 的运行速度非???。它对新手十分友好,因为它提供了一个可供使用的简单 API。点击查看。

Inheritance diagram for HMM <Distribution>

优点:

  • 高度拓展。
  • 可以与 Python 和 C++ 绑定。

缺点:

  • 说明文档不够清晰。

总结

本文所讨论的库都非常高效,并经过了时间的考验,质量上乘。五大巨头 Facebook、谷歌、雅虎、苹果、微软都在使用这些库进行深度学习和机器学习项目。

你有什么理由不用哪?

你能想到其他经常使用,但不在列表上的库吗?请在评论部分与我们分享。

10 个用于 AI 开发的框架和库,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113499/feed/ 1
新贝彩票注册 - AI 玩跳一跳的正确姿势,跳一跳 Auto-Jump 算法详解 http://www.cswhw.com.cn/113493/ http://www.cswhw.com.cn/113493/#comments Tue, 16 Jan 2018 07:19:59 +0000 http://www.cswhw.com.cn/?p=113493 最近,微信小游戏跳一跳可以说是火遍了全国,从小孩子到大孩子仿佛每一个人都在刷跳一跳,作为无(zhi)所(hui)不(ban)能(zhuan)的AI程序员,我们在想,能不能用人工智能(AI)和计算机视觉(CV)的方法来玩一玩这个游戏?

AI 玩跳一跳的正确姿势,跳一跳 Auto-Jump 算法详解,首发于新贝彩票注册。

]]>

最近,微信小游戏跳一跳可以说是火遍了全国,从小孩子到大孩子仿佛每一个人都在刷跳一跳,作为无(zhi)所(hui)不(ban)能(zhuan)的AI程序员,我们在想,能不能用人工智能(AI)和计算机视觉(CV)的方法来玩一玩这个游戏?于是,我们开发了微信跳一跳Auto-Jump算法,重新定义了玩跳一跳的正确姿势,我们的算法不仅远远超越了人类的水平,在速度和准确度上也远远超越了目前已知的所有算法,可以说是跳一跳界的state-of-the-art,下面我们详细介绍我们的算法。

算法的第一步是获取手机屏幕的截图并可以控制手机的触控操作,我们的github仓库里详细介绍了针对Android和IOS手机的配置方法。

你只需要按照将手机连接电脑,按照教程执行就可以完成配置。在获取到屏幕截图之后,就是个简单的视觉问题。我们需要找的就是小人的位置和下一次需要跳的台面的中心。

如图所示,绿色的点代表小人当前的位置,红点代表目标位置。

多尺度搜索(Multiscale Search)

这个问题可以有非常多的方法去解,为了糙快猛地刷上榜,我一开始用的方式是多尺度搜索。我随便找了一张图,把小人抠出来,就像下面这样。

另外,我注意到小人在屏幕的不同位置,大小略有不同,所以我设计了多尺度的搜索,用不同大小的进行匹配,最后选取置信度(confidence score)最高的。

多尺度搜索的代码长这样

def multi_scale_search(pivot, screen, range=0.3, num=10):
    H, W = screen.shape[:2]
    h, w = pivot.shape[:2]

    found = None
    for scale in np.linspace(1-range, 1+range, num)[::-1]:
        resized = cv2.resize(screen, (int(W * scale), int(H * scale)))
        r = W / float(resized.shape[1])
        if resized.shape[0] < h or resized.shape[1] < w:
            break
        res = cv2.matchTemplate(resized, pivot, cv2.TM_CCOEFF_NORMED)

        loc = np.where(res >= res.max())
        pos_h, pos_w = list(zip(*loc))[0]

        if found is None or res.max() > found[-1]:
            found = (pos_h, pos_w, r, res.max())

    if found is None: return (0,0,0,0,0)
    pos_h, pos_w, r, score = found
    start_h, start_w = int(pos_h * r), int(pos_w * r)
    end_h, end_w = int((pos_h + h) * r), int((pos_w + w) * r)
    return [start_h, start_w, end_h, end_w, score]

我们来试一试,效果还不错,应该说是又快又好,我所有的实验中找小人从来没有失误。

不过这里的位置框的底部中心并不是小人的位置,真实的位置是在那之上一些。

同理,目标台面也可以用这种办法搜索,但是我们需要收集一些不同的台面,有圆形的,方形的,便利店,井盖,棱柱等等。由于数量一多,加上多尺度的原因,速度上会慢下来。这时候,我们就需要想办法加速了。首先可以注意到目标位置始终在小人的位置的上面,所以可以操作的一点就是在找到小人位置之后把小人位置以下的部分都舍弃掉,这样可以减少搜索空间。但是这还是不够,我们需要进一步去挖掘游戏里的故事。小人和目标台面基本上是关于屏幕中心对称的位置的。这提供了一个非常好的思路去缩小搜索空间。假设屏幕分辨率是(1280,720)的,小人底部的位置是(h1, w1),那么关于中心对称点的位置就是(1280 – h1, 720 – w1),以这个点为中心的一个边长300的正方形内,我们再去多尺度搜索目标位置,就会又快有准了。效果见下图,蓝色框是(300,300)的搜索区域,红色框是搜到的台面,矩形中心就是目标点的坐标了。

加速的奇技淫巧(Fast-Search)

玩游戏需要细心观察。我们可以发现,小人上一次如果跳到台面中心,那么下一次目标台面的中心会有一个白点,就像刚才所展示的图里的。更加细心的人会发现,白点的RGB值是(245,245,245),这就让我找到了一个非常简单并且高效的方式,就是直接去搜索这个白点,注意到白点是一个连通区域,像素值为(245,245,245)的像素个数稳定在280-310之间,所以我们可以利用这个去直接找到目标的位置。这种方式只在前一次跳到中心的时候可以用,不过没有关系,我们每次都可以试一试这个不花时间的方法,不行再考虑多尺度搜索。

讲到这里,我们的方法已经可以运行的非常出色了,基本上是一个永动机。下面是用我的手机玩了一个半小时左右,跳了859次的状态,我们的方法正确的计算出来了小人的位置和目标位置,不过我选择狗带了,因为手机卡的已经不行了。

这里有一个示例视频,欢迎观看!

点击查看视频

到这里就结束了吗?那我们和业余玩家有什么区别?下面进入正经的学术时间,非战斗人员请迅速撤离!

CNN Coarse-to-Fine 模型

考虑到IOS设备由于屏幕抓取方案的限制(WebDriverAgent获得的截图经过了压缩,图像像素受损,不再是原来的像素值,原因不详,欢迎了解详情的小伙伴提出改进意见~)无法使用fast-search,同时为了兼容多分辨率设备,我们使用卷积神经网络构建了一个更快更鲁棒的目标检测模型,下面分数据采集与预处理,coarse模型,fine模型,cascade四部分介绍我们的算法。

数据采集与预处理

基于我们非常准确的multiscale-search、fast-search模型,我们采集了7次实验数据,共计大约3000张屏幕截图,每一张截图均带有目标位置标注,对于每一张图,我们进行了两种不同的预处理方式,并分别用于训练coarse模型和fine模型,下面分别介绍两种不同的预处理方式。

Coarse 模型数据预处理

由于每一张图像中真正对于当前判断有意义的区域只在屏幕中央位置,即人和目标物体所在的位置,因此,每一张截图的上下两部分都是没有意义的,因此,我们将采集到的大小为1280*720的图像沿x方向上下各截去320*720大小,只保留中心640*720的图像作为训练数据。

我们观察到,游戏中,每一次当小人落在目标物中心位置时,下一个目标物的中心会出现一个白色的圆点,

考虑到训练数据中fast-search会产生大量有白点的数据,为了杜绝白色圆点对网络训练的干扰,我们对每一张图进行了去白点操作,具体做法是,用白点周围的纯色像素填充白点区域。

Fine 模型数据预处理

为了进一步提升模型的精度,我们为fine模型建立了数据集,对训练集中的每一张图,在目标点附近截取320*320大小的一块作为训练数据,

为了防止网络学到trivial的结果,我们对每一张图增加了50像素的随机偏移。fine模型数据同样进行了去白点操作。

Coarse 模型

我们把这一问题看成了回归问题,coarse模型使用一个卷积神经网络回归目标的位置,

def forward(self, img, is_training, keep_prob, name='coarse'):
    with tf.name_scope(name):
        with tf.variable_scope(name):
            out = self.conv2d('conv1', img, [3, 3, self.input_channle, 16], 2)
            # out = tf.layers.batch_normalization(out, name='bn1', training=is_training)
            out = tf.nn.relu(out, name='relu1')

            out = self.make_conv_bn_relu('conv2', out, [3, 3, 16, 32], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv3', out, [5, 5, 32, 64], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv4', out, [7, 7, 64, 128], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv5', out, [9, 9, 128, 256], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = tf.reshape(out, [-1, 256 * 20 * 23])
            out = self.make_fc('fc1', out, [256 * 20 * 23, 256], keep_prob)
            out = self.make_fc('fc2', out, [256, 2], keep_prob)

    return out

经过十小时的训练,coarse模型在测试集上达到了6像素的精度,实际测试精度大约为10像素,在测试机器(MacBook Pro Retina, 15-inch, Mid 2015, 2.2 GHz Intel Core i7)上inference时间0.4秒。这一模型可以很轻松的拿到超过1k的分数,这已经远远超过了人类水平和绝大多数自动算法的水平,日常娱乐完全够用,不过,你认为我们就此为止那就大错特错了~

Fine 模型

fine模型结构与coarse模型类似,参数量稍大,fine模型作为对coarse模型的refine操作,

def forward(self, img, is_training, keep_prob, name='fine'):
    with tf.name_scope(name):
        with tf.variable_scope(name):
            out = self.conv2d('conv1', img, [3, 3, self.input_channle, 16], 2)
            # out = tf.layers.batch_normalization(out, name='bn1', training=is_training)
            out = tf.nn.relu(out, name='relu1')

            out = self.make_conv_bn_relu('conv2', out, [3, 3, 16, 64], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv3', out, [5, 5, 64, 128], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv4', out, [7, 7, 128, 256], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = self.make_conv_bn_relu('conv5', out, [9, 9, 256, 512], 1, is_training)
            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

            out = tf.reshape(out, [-1, 512 * 10 * 10])
            out = self.make_fc('fc1', out, [512 * 10 * 10, 512], keep_prob)
            out = self.make_fc('fc2', out, [512, 2], keep_prob)

    return out

经过十小时训练,fine模型测试集精度达到了0.5像素,实际测试精度大约为1像素,在测试机器上的inference时间0.2秒。

Cascade

总体精度1像素左右,时间0.6秒。

总结

针对这一问题,我们利用AI和CV技术,提出了合适适用于IOS和Android设备的完整解决方案,稍有技术背景的用户都可以实现成功配置、运行,我们提出了Multiscale-Search,Fast-Search,CNN Coarse-to-Fine三种解决这一问题的算法,三种算法相互配合,可以实现快速准确的搜索、跳跃,用户针对自己的设备稍加调整跳跃参数即可接近实现“永动机”。讲到这里,似乎可以宣布,我们的工作terminate了这个问题,微信小游戏跳一跳game over!

友情提示:适度游戏益脑,沉迷游戏伤身,技术手段的乐趣在于技术本身而不在游戏排名,希望大家理性对待游戏排名和本文提出的技术,用游戏娱乐自己的生活

声明:本文提出的算法及开源代码符合MIT开源协议,以商业目的使用该算法造成的一切后果须由使用者本人承担

Git仓库地址:

http://www.cswhw.com.cn/Prinsphield/Wechat_AutoJump

http://www.cswhw.com.cn/Richard-An/Wechat_AutoJump

AI 玩跳一跳的正确姿势,跳一跳 Auto-Jump 算法详解,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113493/feed/ 11
新贝彩票注册 - 为小白准备的重要 Docker 命令说明 http://www.cswhw.com.cn/113490/ http://www.cswhw.com.cn/113490/#comments Tue, 16 Jan 2018 03:12:45 +0000 http://www.cswhw.com.cn/?p=113490 在本教程中,我们会学习管理 docker 容器的其他命令。

为小白准备的重要 Docker 命令说明,首发于新贝彩票注册。

]]>
在早先的教程中,我们学过了在 RHEL CentOS 7 上安装 Docker 并创建 docker 容器。 在本教程中,我们会学习管理 docker 容器的其他命令。

Docker 命令语法

$ docker [option] [command] [arguments]

要列出 docker 支持的所有命令,运行

$ docker

我们会看到如下结果,

attach Attach to a running container
build  Build an image from a Dockerfile
commit  Create a new image from a container's changes
cp  Copy files/folders between a container and the local filesystem
create  Create a new container
diff  Inspect changes on a container's filesystem
events  Get real time events from the server
exec  Run a command in a running container
export  Export a container's filesystem as a tar archive
history  Show the history of an image
images  List images
import  Import the contents from a tarball to create a filesystem image
info  Display system-wide information
inspect  Return low-level information on a container or image
kill  Kill a running container
load  Load an image from a tar archive or STDIN
login  Log in to a Docker registry
logout  Log out from a Docker registry
logs  Fetch the logs of a container
network  Manage Docker networks
pause  Pause all processes within a container
port  List port mappings or a specific mapping for the CONTAINER
ps  List containers
pull  Pull an image or a repository from a registry
push  Push an image or a repository to a registry
rename  Rename a container
restart  Restart a container
rm  Remove one or more containers
rmi  Remove one or more images
run  Run a command in a new container
save  Save one or more images to a tar archive
search  Search the Docker Hub for images
start  Start one or more stopped containers
stats  Display a live stream of container(s) resource usage statistics
stop  Stop a running container
tag  Tag an image into a repository
top  Display the running processes of a container
unpause  Unpause all processes within a container
update  Update configuration of one or more containers
version  Show the Docker version information
volume  Manage Docker volumes
wait  Block until a container stops, then print its exit code

要进一步查看某个命令支持的选项,运行:

$ docker docker-subcommand info

就会列出 docker 子命令所支持的选项了。

测试与 Docker Hub 的连接

默认,所有镜像都是从 Docker Hub 中拉取下来的。我们可以从 Docker Hub 上传或下载操作系统镜像。为了检查我们是否能够正常地通过 Docker Hub 上传/下载镜像,运行

$ docker run hello-world

结果应该是:

Hello from Docker.
This message shows that your installation appears to be working correctly.
…

输出结果表示你可以访问 Docker Hub 而且也能从 Docker Hub 下载 docker 镜像。

搜索镜像

搜索容器的镜像,运行

$ docker search Ubuntu

我们应该会得到可用的 Ubuntu 镜像的列表。记住,如果你想要的是官方的镜像,请检查 official 这一列上是否为 [OK]。

下载镜像

一旦搜索并找到了我们想要的镜像,我们可以运行下面语句来下载它:

$ docker pull Ubuntu

要查看所有已下载的镜像,运行:

$ docker images

运行容器

使用已下载镜像来运行容器,使用下面命令:

$ docker run -it Ubuntu

这里,使用 -it 会打开一个 shell 与容器交互。容器启动并运行后,我们就可以像普通机器那样来使用它了,我们可以在容器中执行任何命令。

显示所有的 docker 容器

要列出所有 docker 容器,运行:

$ docker ps

会输出一个容器列表,每个容器都有一个容器 id 标识。

停止 docker 容器

要停止 docker 容器,运行:

$ docker stop container-id

从容器中退出

要从容器中退出,执行:

$ exit

保存容器状态

容器运行并更改后(比如安装了 apache 服务器),我们可以保存容器状态。这会在本地系统上保存新创建镜像。

运行下面语句来提交并保存容器状态:

$ docker commit 85475ef774 repository/image_name

这里,commit 命令会保存容器状态,85475ef774,是容器的容器 id,repository,通常为 docker hub 上的用户名 (或者新加的仓库名称)image_name,是新镜像的名称。

我们还可以使用 -m-a 来添加更多信息。通过 -m,我们可以留个信息说 apache 服务器已经安装好了,而 -a 可以添加作者名称。

像这样:

docker commit -m "apache server installed"-a "Dan Daniels" 85475ef774 daniels_dan/Cent_container

我们的教程至此就结束了,本教程讲解了一下 Docker 中的那些重要的命令,如有疑问,欢迎留言。

为小白准备的重要 Docker 命令说明,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113490/feed/ 1
新贝彩票注册 - 回顾 2017 年发布的 10 个新数据库系统 http://www.cswhw.com.cn/113486/ http://www.cswhw.com.cn/113486/#respond Mon, 15 Jan 2018 13:30:01 +0000 http://www.cswhw.com.cn/?p=113486 数据库世界并不是每周都有让人不可思议的新闻,但在一年的时间里,我还是惊讶地发现,我们看到了很多新事物,以及该领域坚持不懈地发展。

回顾 2017 年发布的 10 个新数据库系统,首发于新贝彩票注册。

]]>

作为?Database Weekly?的编辑(Database Weekly?是一份关于数据库和数据存储世界新内容的每周时事资讯),我喜欢在新的数据库系统中闲逛,看看在未来的几十年里,哪些想法可能会影响到日常的开发人员。

数据库世界并不是每周都有让人不可思议的新闻,但在一年的时间里,我还是惊讶地发现,我们看到了很多新事物,以及该领域坚持不懈地发展。2017 年也不例外,所以我想回顾一下一些有趣的新发行版,包括一个事务性图表数据库,一个可复制的地理多模型数据库,以及一个新的高性能键/值存储数据库。

TimescaleDB? — 一款基于 Postgres 的能自动分区的时间序列数据库

其中一个令人兴奋的新扩展源于?PostgreSQL,Timescale?基于?Apache 2.0 的许可,它是由一个名为?PhD-packed?的机构支持启动的。

Timescale 通过自动分区为 Postgres 添加时间序列存储功能,但是却包含在寻常的 Postgres 界面和工具中。 查询是使用常规的 SQL 对“提供与时间序列数据的接口” 的 “hypertable” 进行的。

Microsoft Azure Cosmos DB ?— 微软的多模式数据库

Cosmos DB?本质上是 Azure 的旧的?DocumentDB?的品牌重塑和重新构建,但是它很容易实现将全球分布式数据跟 Azure 的多样数据中心交叉。全球分布是 Cosmos DB 的杀手锏,并且它可以将数据库请求路由到包含数据的最近区域,而不需要更改配置。

“多模式”的部分也很重要。虽然一切都在无模式的 JSON 的引擎盖下,但依然有一个 SQL 查询 API ,以及 MongoDB API、Cassandra API,甚至一个图形数据库 API(基于?Gremlin?)。

学习更多关于 Cosmos 的较好的方式之一是这个微软的第9频道的?15 分钟视频介绍。

Cloud Spanner ?—? Google 全球分布式关系数据库

Google 的?Cloud Spanner?已经工作了很长一段时间了,起初是在 2012 年一篇非常有趣的学术论文中公开阐释的(虽然开发始于 2007 年)。最初的开发是因为 Google 需要一个全球化分布式的高可用性存储系统,但其现在也向公众开放。

谷歌认识到,使 Cloud Spanner 适合其自身用途的功能对企业也很有吸引力,因此它承诺 99.999% 的可用性、无计划?;奔浜汀捌笠导丁卑踩?。

Cloud Spanner 支持 ANSI 2011 SQL ,为已熟悉关系数据库概念的开发人员提供了经过战斗级测试的高可用性水平扩展的关系数据库。

Neptune ?—? Amazon 的全面管理图形数据库服务

Microsoft 和 Google 我们都已经讲到了, 所以怎么能漏了 Amazon 呢? 这是另外一个受限于特定云服务的数据库, ?Amazon 在最近召开的?re:Invent 大会上展示了?Neptune?的预览。

Neptune 承诺会是一个快速且可靠的图形数据库服务,其目的是能迅速地为开发者提供图形数据库服务,并且不会让他们感到麻烦,当然这些是要付费的。

Neptune 支持用两种标准来对你的图形库进行查询, 一个是得到越来越多的支持的?Gremlin?的“黄金”标准,还有就是?SPARQL (你的图形会被当作是一个 RDF )。

YugaByte ?—? 一个开源的云原生数据库

YugaByte 今年因其“隐形模式”脱颖而出,它提供了一个支持 SQL 和 NoSQL 操作模式的数据库。目的是在云中直接使用,充当对容器的有状态补充。

YugaByte 使用 C ++ 构建并开源,支持 Cassandra 查询语言(CQL)以及 Redis 协议。 对 PostgreSQL 协议的支持正在进行中,Spark 应用可在上面运行。

YugaByte 是另一个启动后才受到支持的项目(由扩展了 Apache HBase 平台的一位 Facebook 工程师创建),其业务模式初定是会有一个“企业版”,在开源社区版的基础上增加多云集群协调 ,监视和警报,分层存储和支持等特性。

Peloton ?—? 一个自驱动的 SQL DBMS

Peloton 探索了一些有趣的想法,特别是在使用 AI 来自动优化数据库的领域。它还支持字节寻址 NVM 存储技术,并且是使用 Apache 许可开源的。

“自驱动”数据库背后的想法是,DBMS 可以自主操作和调整自身。它可以预测工作负载的趋势,并据此做好准备,而无需 DBA 或操作员掌控。

也许毫不奇怪的是,Peloton 源于一个学术项目(特别是来自卡内基梅隆大学),其创建者之一写了一篇关于为什么它被创建的系列文章。它已经开发好几年了,但在 2017 年变得更加开放。

JanusGraph? —? 一个基于 Java 的分布式图形数据库

JanusGraph?是一个实用的、随时可用的数据库,其中包含大量的集成,并且建立在?TitanDB?的坚实基础之上。它针对可扩展性、存储及查询巨大图形数据库做了优化,同时支持事务和大量并发用户。

它可以使用 Cassandra、HBase、Google Cloud Bigtable 和 BerkeleyDB 作为存储后端,并且可以与 Spark、Giraph 和 Hadoop 直接整合。它甚至支持与 ElasticSearch、Solr 或 Lucene 集成的全文和地理位置检索。

Aurora Serverless? — AWS 上即时可伸缩,“即付即用”的关系型数据库

另一个来自 Amazo re:Invent 会议的公告是他们成功的 Aurora 数据库服务的无服务器版本,Aurora Serverless。

随着整合到“无服务器”平台的最新趋势,这个平台将永远消除你在扩展和操作上的难题,Aurora Serverless背后的理念是许多数据库用例不需要一致的性能或使用水平,相反,你可以“随时付费”(逐秒付费),以便按需调整数据库的大小。

它目前仅是预览版,但承诺在 2018 年会有重大进展。

TileDB ?— 用于存储大密度及稀疏矩阵数组

TileDB?是起源自麻省理工学院和英特尔的数据库,用于存储多维阵列数据,这是类似基因科学、医学成像和金融时间序列等领域常见的要求。

它支持许多压缩机制(如 gzip、lz4、Blosc 和 RLE )和存储后端(如 GFS、S3 和 HDFS )。

Memgraph ?—? 一个高性能、可内存驻留的图形数据库

Memgraph?背后的驱动力是为快速分析和使用来自人造和机器智能的数据以及设备和物联网不断增长的互联性提供工具。因此,优先事项是“速度、可伸缩和简单性”。

在 Memgraph 的生命周期中,它还处于早期阶段,它不是开源的,但可以通过 request?下载。它支持 openCypher 图形查询语言,支持内存中的 ACID 事务,并具有基于磁盘的持久化机制。

回顾 2017 年发布的 10 个新数据库系统,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113486/feed/ 0
新贝彩票注册 - Pick:一款 Linux 上的命令行模糊搜索工具 http://www.cswhw.com.cn/113480/ http://www.cswhw.com.cn/113480/#respond Mon, 15 Jan 2018 11:37:56 +0000 http://www.cswhw.com.cn/?p=113480 它允许用户通过 ncurses(3X) 界面来从一系列选项中进行选择,而且还支持模糊搜索的功能。当你想要选择某个名字中包含非英文字符的目录或文件时,这款工具就很有用了。

Pick:一款 Linux 上的命令行模糊搜索工具,首发于新贝彩票注册。

]]>
今天,我们要讲的是一款有趣的命令行工具,名叫 Pick。它允许用户通过 ncurses(3X) 界面来从一系列选项中进行选择,而且还支持模糊搜索的功能。当你想要选择某个名字中包含非英文字符的目录或文件时,这款工具就很有用了。你根本都无需学习如何输入非英文字符。借助 Pick,你可以很方便地进行搜索、选择,然后浏览该文件或进入该目录。你甚至无需输入任何字符来过滤文件/目录。这很适合那些有大量目录和文件的人来用。

安装 Pick

对 Arch Linux 及其衍生品来说,Pick 放在 AUR 中。因此 Arch 用户可以使用类似 Pacaur,Packer,以及 Yaourt 等 AUR 辅助工具来安装它。

pacaur -S pick

或者,

packer -S pick

或者,

yaourt -S pick

Debian,Ubuntu,Linux Mint 用户则可以通过运行下面命令来安装 Pick。

sudo apt-get install pick

其他的发行版则可以从这里下载最新的安装包,然后按照下面的步骤来安装。在写本指南时,其最新版为 1.9.0。

wget http://www.cswhw.com.cn/calleerlandsson/pick/releases/download/v1.9.0/pick-1.9.0.tar.gz
tar -zxvf pick-1.9.0.tar.gz
cd pick-1.9.0/

使用下面命令进行配置:

./configure

最后,构建并安装 Pick:

make
sudo make install

用法

通过将它与其他命令集成能够大幅简化你的工作。我这里会给出一些例子,让你理解它是怎么工作的。

让们先创建一堆目录。

mkdir -p abcd/efgh/ijkl/mnop/qrst/uvwx/yz/

现在,你想进入目录 /ijkl/。你有两种选择??梢允褂?cd 命令:

cd abcd/efgh/ijkl/

或者,创建一个快捷方式 或者说别名指向这个目录,这样你可以迅速进入该目录。

但,使用 pick 命令则问题变得简单的多??聪旅嬲飧隼?。

cd $(find . -type d | pick)

这个命令会列出当前工作目录下的所有目录及其子目录,你可以用上下箭头选择你想进入的目录,然后按下回车就行了。

像这样:

而且,它还会根据你输入的内容过滤目录和文件。比如,当我输入 “or” 时会显示如下结果。

这只是一个例子。你也可以将 pick 命令跟其他命令一起混用。

这是另一个例子。

find -type f | pick | xargs less

该命令让你选择当前目录中的某个文件并用 less 来查看它。

还想看其他例子?还有呢。下面命令让你选择当前目录下的文件或目录,并将之迁移到其他地方去,比如这里我们迁移到 /home/sk/ostechnix。

mv "$(find . -maxdepth 1 |pick)" /home/sk/ostechnix/

通过上下按钮选择要迁移的文件,然后按下回车就会把它迁移到 /home/sk/ostechnix/ 目录中的。

从上面的结果中可以看到,我把一个名叫 abcd 的目录移动到 ostechnix 目录中了。

使用方式是无限的。甚至 Vim 编辑器上还有一个叫做 pick.vim 的插件让你在 Vim 中选择更加方便。

要查看详细信息,请参阅它的 man 页。

man pick

我们的讲解至此就结束了。希望这款工具能给你们带来帮助。如果你觉得我们的指南有用的话,请将它分享到您的社交网络上,并向大家推荐我们。

Pick:一款 Linux 上的命令行模糊搜索工具,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113480/feed/ 0
新贝彩票注册 - Linux 的 fmt 命令用法与案例 http://www.cswhw.com.cn/113479/ http://www.cswhw.com.cn/113479/#respond Mon, 15 Jan 2018 11:36:25 +0000 http://www.cswhw.com.cn/?p=113479 有时你会发现需要格式化某个文本文件中的内容。比如,该文本文件每行一个单词,而任务是把所有的单词都放在同一行。当然,你可以手工来做,但没人喜欢手工做这么耗时的工作。而且,这只是一个例子-事实上的任务可能千奇百怪。

Linux 的 fmt 命令用法与案例,首发于新贝彩票注册。

]]>
有时你会发现需要格式化某个文本文件中的内容。比如,该文本文件每行一个单词,而任务是把所有的单词都放在同一行。当然,你可以手工来做,但没人喜欢手工做这么耗时的工作。而且,这只是一个例子 – 事实上的任务可能千奇百怪。

好在,有一个命令可以满足至少一部分的文本格式化的需求。这个工具就是 fmt。本教程将会讨论 fmt 的基本用法以及它提供的一些主要功能。文中所有的命令和指令都在 Ubuntu 16.04LTS 下经过了测试。

Linux fmt 命令

fmt 命令是一个简单的文本格式化工具,任何人都能在命令行下运行它。它的基本语法为:

fmt [-WIDTH] [OPTION]... [FILE]...

它的 man 页是这么说的:

重新格式化文件中的每一个段落,将结果写到标准输出。选项 -WIDTH--width=DIGITS 形式的缩写。

下面这些问答方式的例子应该能让你对 fmt 的用法有很好的了解。

Q1、如何使用 fmt 来将文本内容格式成同一行?

使用 fmt 命令的基本形式(省略任何选项)就能做到这一点。你只需要将文件名作为参数传递给它。

fmt [file-name]

下面截屏是命令的执行结果:

format contents of file in single line

你可以看到文件中多行内容都被格式化成同一行了。请注意,这并不会修改原文件(file1)。

Q2、如何修改最大行宽?

默认情况下,fmt 命令产生的输出中的最大行宽为 75。然而,如果你想的话,可以用 -w 选项进行修改,它接受一个表示新行宽的数字作为参数值。

fmt -w [n] [file-name]

下面这个例子把行宽削减到了 20:

change maximum line width

Q3、如何让 fmt 突出显示第一行?

这是通过让第一行的缩进与众不同来实现的,你可以使用 -t 选项来实现。

fmt -t [file-name]

make fmt highlight the first line

Q4、如何使用 fmt 拆分长行?

fmt 命令也能用来对长行进行拆分,你可以使用 -s 选项来应用该功能。

fmt -s [file-name]

下面是一个例子:

make fmt split long lines

Q5、如何在单词与单词之间,句子之间用空格分开?

fmt 命令提供了一个 -u 选项,这会在单词与单词之间用单个空格分开,句子之间用两个空格分开。你可以这样用:

fmt -u [file-name]

注意,在我们的案例中,这个功能是默认开启的。

总结

没错,fmt 提供的功能不多,但不代表它的应用就不广泛。因为你永远不知道什么时候会用到它。在本教程中,我们已经讲解了 fmt 提供的主要选项。若想了解更多细节,请查看该工具的 man 页。

Linux 的 fmt 命令用法与案例,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113479/feed/ 0
新贝彩票注册 - 请停止结对编程 http://www.cswhw.com.cn/113474/ http://www.cswhw.com.cn/113474/#comments Sat, 13 Jan 2018 08:37:09 +0000 http://www.cswhw.com.cn/?p=113474 这是一个风和日丽的星期五下午,Ben 和 Martin 本应该在 咖啡馆喝一杯下午茶,一起聊聊周末的计划,然而 PM 的一个微信通知打乱了这一切。原来产品出现了一个bug需要紧急修复,下班之前必须要搞定。

请停止结对编程,首发于新贝彩票注册。

]]>

(根据真实事件改编,情节有所夸张,请勿对号入座。)

这是一个风和日丽的星期五下午,Ben 和 Martin 本应该在 Costa 咖啡馆喝一杯下午茶,一起聊聊周末的计划,然而 PM 的一个微信通知打乱了这一切。原来产品出现了一个bug需要紧急修复,下班之前必须要搞定。两人收到消息疾步走回到岗位,也没了心情去喝刚泡好的咖啡,连忙打开邮箱查看问题报告。

开始

Ben:看来这不是一个很大的问题,就是处理一个来自于远端服务的异常。现在的情况是BFF(backend for frontends)在内部的远端服务有异常,会将异常直接返回到客户端,这样只要一个保单出了问题,前端所有的保单也都没法用了。

Martin:那怎么解决?

Ben:感觉可以在异常的地方加一个异常处理。这个涉及到RxJava和Java8的stream特性,我不是太熟悉,要不我们一起Pair吧

Martin:好。

两人喝了一口炙热的咖啡,摆好键盘鼠标,打开了IntelliJ工程。几分钟后,这个故障重现了。

Martin:可以重现的故障通常比较好解决。我们在这里先弄个try…catch试试。 两人似乎很有信心,然而重启项目后,故障并没有按照预期停下来。

Ben:hmm,这里为什么停不下来呢?

Martin:可能是RxJava的延迟处理,没有正确的捕捉到。这样,你在这里再写一个逻辑,然后在这里设个断点……

焦急

在这个过程中,Martin只是对着屏幕指指点点,时不时看看手机、在微信上聊聊天。Ben对RxJava并不是很熟悉,他想紧紧跟随Martin的思路,然而增加多个逻辑以后,依然都不能解决问题。15分钟已经过去,Ben这时候心生怀疑,是不是哪些地方没弄对?

Ben:我们理一下思路看看?

Martin:恩,来吧,一起看一下代码。

Martin领着Ben一起看了一下代码,并且一直在旁边指点Ben进行单步调试。由于RxJava的延迟特性,使得断点很难设置。而抛出异常的调用栈会出现在某些莫名其妙的地方,这让他们根本不知道把try…catch放在哪里才能奏效。

Ben:可能是要这样,在这里加一个OnError看能不能解决。

看似问题能够解决,其实是又一次的失败。在两人的激烈讨论中,时间过得很快,一晃眼已经是1个小时以后,咖啡早已经凉了,然而两个人完全没有心情,甚至都忘了咖啡的存在。

Ben对Martin的解决方案越来越没有信心,两人开始重新讨论起解决方案。然而方案是越讨论越复杂,看起来想在下班前解决这个问题是不可能了,通宵是必然了。

简化

Zen是组里的Tech Lead,今天在忙另外一个事情。这个周五真是不得安宁,恨不得想到美国去过过昨天。

Zen听到两个人的讨论,虽然并不了解这个问题的细节,但直觉上认为是跑偏了。马上提醒Ben和Martin:

这不是一个很难的问题,我感觉你们想复杂了?是不是走偏了?能给我说一下你们怎么想的么?

被Zen打断的Martin说了一下之前的解决方案,也说试过了其他的方案了,都不行。由于Zen对这个事情也不是很了解,所以只是提了一个醒:

“Keep it simple,别把事情整复杂了?!?/p>

两个人的讨论依然在继续,Ben有点无法跟上Martin的思路,艰难地写着代码,但每次都不对。Pair的气氛犹如冬日里冰冷的咖啡一样凝结,不知道孰是孰非。Ben已经有些不高兴,Martin则依然在一旁指指点点但并不动手。

Zen一看表已经3点钟了,又插了一句嘴:

Martin,既然你对这个更熟悉,你来操刀吧。你来写代码吧。

可能由于之前的讨论过于激烈,Martin反驳Zen:

我们在Pair啊,他对RxJava不熟悉,我应该指导他。我看着他写就可以了。

Zen说,

你们的解决方案是什么,给我看看。

解释了一通以后,Zen也没有更多的想法,就让他们继续吧。但Zen建议道:

在这个紧要的关头,我们应该改变一下Pair的方式。现在不是教授知识,而是要高效的解决问题。在这种压力的情境下,你可以直接实现自己的思路,带着别人飞就好了。

分歧

Martin稍微冷静了下,拿过键盘,继续开始修复问题。Ben这时候在一旁观察,也适当的休息一下,之前手忙脚乱的按F8、F9的神经也得以缓和。

Ben:看来还是不行。我们再理一下代码吧。

Martin:你说的这些我之前都试过,都不行,要这样才行。

Ben:我说的是这样做的,既然我们还没讨论清楚,我们再来看一下代码吧。

两人拿出了纸和笔,对着屏幕一边画一边讨论,然而Ben并不认可Martin的方案,说要采用另外个方案。Martin则坚持认为这是一个可行的方案,得试试。Ben拿过键盘,准备按照Martin的方案写代码,但心里面颇为不爽,一直在想说服Martin采用他的方案试试。

怒气

到此时,时间都已经不知不觉过去两个小时了,然而问题似乎离真相总是忽远忽近。两个人已经疲劳不堪,再加上解决方案的不一致,两人的言语中开始显露出一些怒气。

Zen在运行测试的空档,打断了两人的对话,建议道:

既然大家已经产生了分歧,要不然两个人分开,各自实现一个,看谁能够先实现,然后再来讨论。

Martin对于Zen并不认同,认为Zen指责他和Ben没有Pair好。

Zen解释道:

其实我听出了两人意见的不统一,言语中已经有一些怒火,这样下去Pair的效率很低。首先,大家带着不爽来干活,互相质疑。更关键的是,解决问题已经用去了两个多小时,大家都比较疲惫,可以适当休息。我让你们分开的目的是让大家冷静一下,在不受打扰的情况下工作一段时间,可能会不一样。

冷静

Martin回到了电脑面前,按照他的思路一步一步做下去。Ben去上了个厕所,倒掉了那杯冷冰冰的咖啡,泡了杯热茶?;氐降缒郧白ㄗ⒌闹匦掳凑账乃悸芬徊揭徊阶呦氯?。

其实两个人已经接近了真相,只是这之间不停的对话把注意力消耗殆尽。两人企图达到一个统一,然而口头的对话并不能解决问题,反而暂缓了这个过程。

10分钟后,Ben兴高采烈的说已经搞出来了一套可以运行的方案,叫Martin一同过来看看。Ben的临时解决方案比较简单好理解,但并不完美。熟悉RxJava的Martin指出了一些可以改进的地方。

然后两人又开始了新一轮的Pair,重新将这个方案完善。有了这个基础的解决方案,两人都很高兴,是朝着一个正确的方向大步向前。

尾声

下午6点半,虽然比正常下班晚了半个多小时,但还好整个解决方案都正常了,交付的任务也顺利完成。

Ben和Martin都总结道,我们应该停止结对,当:

  • 两人的思路不统一但无法说服对方时:我们可以考虑分开一阵,安静一下,各自用可运行的代码来证明思路的可行。这里只需要相对粗糙的代码即可。
  • 时间已经超过番茄时间而感到疲惫时:人的专注力是有限的,在Pair时非常累,特别是在能力方面存在较大差距的时候。在这时候我们可以试试番茄工作法,让大脑得到休息。
  • 注意力不集中或者有其他事务要处理时:在Pair的时候,彼此要尊重对方,不要玩手机、看其他无关的网页,除非事先取得别人的同意,否则就要等到停止结对、处理完事务后再继续。

请停止结对编程,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113474/feed/ 2
新贝彩票注册 - 在 Linux 的终端上伪造一个好莱坞黑客的屏幕 http://www.cswhw.com.cn/113471/ http://www.cswhw.com.cn/113471/#respond Fri, 12 Jan 2018 08:54:55 +0000 http://www.cswhw.com.cn/?p=113471 这是一个简单的小工具,可以把你的 Linux 终端变为好莱坞风格的黑客入侵的实时画面。

在 Linux 的终端上伪造一个好莱坞黑客的屏幕,首发于新贝彩票注册。

]]>

摘要:这是一个简单的小工具,可以把你的 Linux 终端变为好莱坞风格的黑客入侵的实时画面。

我攻进去了!

你可能会几乎在所有的好莱坞电影里面会听说过这句话,此时的荧幕正在显示着一个入侵的画面。那可能是一个黑色的终端伴随着 ASCII 码、图标和连续不断变化的十六进制编码以及一个黑客正在击打着键盘,仿佛他/她正在打一段愤怒的论坛回复。

但是那是好莱坞大片!黑客们想要在几分钟之内破解进入一个网络系统除非他花费了几个月的时间来研究它。不过现在我先把对好莱坞黑客的评论放在一边。

因为我们将会做相同的事情,我们将会伪装成为一个好莱坞风格的黑客。

这个小工具运行一个脚本在你的 Linux 终端上,就可以把它变为好莱坞风格的实时入侵终端:

看到了吗?就像这样,它甚至在后台播放了一个 Mission Impossible 主题的音乐。此外每次运行这个工具,你都可以获得一个全新且随机的入侵的终端。

让我们看看如何在 30 秒之内成为一个好莱坞黑客。

如何安装 Hollywood 入侵终端在 Linux 之上

这个工具非常适合叫做 Hollywood 。从根本上说,它运行在 Byobu ——一个基于文本的窗口管理器,而且它会创建随机数量、随机尺寸的分屏,并在每个里面运行一个混乱的文字应用。

Byobu 是一个在 Ubuntu 上由 Dustin Kirkland 开发的有趣工具。在其他文章之中还有更多关于它的有趣之处,让我们先专注于安装这个工具。

Ubuntu 用户可以使用简单的命令安装 Hollywood:

sudo apt install hollywood

如果上面的命令不能在你的 Ubuntu 或其他例如 Linux Mint、elementary OS、Zorin OS、Linux Lite 等等基于 Ubuntu 的 Linux 发行版上运行,你可以使用下面的 PPA 来安装:

sudo apt-add-repository ppa:hollywood/ppa
sudo apt-get update
sudo apt-get install byobu hollywood

你也可以在它的 GitHub 仓库之中获得其源代码: Hollywood 在 GitHub 。

一旦安装好,你可以使用下面的命令运行它,不需要使用 sudo :

hollywood

因为它会先运行 Byosu ,你将不得不使用 Ctrl+C 两次并再使用 exit 命令来停止显示入侵终端的脚本。

这里面有一个伪装好莱坞入侵的视频。

这是一个让你朋友、家人和同事感到吃惊的有趣小工具,甚至你可以在酒吧里给女孩们留下深刻的印象,尽管我不认为这对你在那方面有任何的帮助,

并且如果你喜欢 Hollywood 入侵终端,或许你也会喜欢另一个可以让 Linux 终端产生 Sneaker 电影效果的工具。

如果你知道更多有趣的工具,可以在下面的评论栏里分享给我们。

在 Linux 的终端上伪造一个好莱坞黑客的屏幕,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113471/feed/ 0
新贝彩票注册 - 区块链初学者指南 http://www.cswhw.com.cn/113467/ http://www.cswhw.com.cn/113467/#comments Fri, 12 Jan 2018 02:33:39 +0000 http://www.cswhw.com.cn/?p=113467 区块链到底是什么呢?其实是两个东西:一个是区块一个是链。说玄虚一点,就是一链子的区块。

区块链初学者指南,首发于新贝彩票注册。

]]>

我并不明白为什么人们会觉得要理解区块链会有点难,而我也想知道为什么自己并没有。那是在 2013 年,我第一次听说有比特币这个东西(是的,知道的太晚啦)。我穷得连一个都买不起,看到这儿你也许已经对此文无爱了。后来,我想要去了解一下它所依赖的底层技术,也就区块链。 不过因为太忙了,所以迟迟没有开始(那就并不存在什么 开始不开始了)。

那么这个 “区块链”到底是什么呢?

其实是两个东西:一个是区块一个是链。说玄虚一点,就是一链子的区块。因为它是存在于计算机中的东西,所以我们可以厘定它的一个物理形态是啥样子的,就是数字信息被分成一个一个区块然后把这些区块链接起来。举个例子,下图中的方块,每一个都表示一个国家,而且每一个都包含了对应国家的城市名称。

等等,其实还有更多东西来着。这里的每一个方块都一个叫做哈希的东西。一个哈希就是一串字符 (比如?“1hi515AHA5H” )。哈希是根据方块里面所包含的信息来得到的。 U.S.A 的方块拥有 New York, Los Angeles, 还有 Chicago 这几个城市,所以它的哈希就是像 “NYLAC” 的东西了?(技术上其实远非如此,但你理会精要就行了)。

每一个接续的方块都会包含前一个方块的哈希,所以这个就是(强制性的)将它们绑到一起的纽带。如果有人擅自篡改了第一个方块,加入了城市?Boston,那么新的哈希就会是 “NYLACB”,然而后面接续的 India 这个方块已经存着的哈?;故?“NYLAC”,这种不匹配就会把链条打断。所以哈希的目的就是确保没有人可以篡改区块。

那如果有人修改了一个方块的内容,然后把后面的接续方块的哈希也一并更新会如何呢??这也是有可能的,不过有一件事情我还没有告诉你。区块链的数据并不只是存在于仅仅一台计算机里面。一台计算机里面的区块链数据并不能骗到人,因为它会被复制到网络中每一个用户的计算机里面去。如果你加入了一个区块链网络,那么你的计算机就会去下载这些区块数据,如果有人篡改了他拥有的版本,整个网络也会考虑占多数的人的计算机上所拥有的版本才是正确的。

还有一件事,在一个区块链网络中,不仅是数据,就连整个系统的程序都被复制到了所有的电脑中。大多数互联网应用都是集中话的,比如 Facebook,她的数据和程序都被放在了她的服务器上,你的计算机会从 Facebook 的服务器上获取到你一个人需要知道的信息。但在区块链的世界理,就没有存在于中心的东西,它依赖的是用户的计算机来容纳自己的程序。是的,这就意味着,如果整个区块链网络中的每一台电脑都关机了,那么这个区块链系统就死翘翘了。

公共区块链

这是不是就意味着区块链系统其实就是由一群心怀善意自愿让他们的计算机保持运行的人来组成的呢? 还有这些防篡改的区块是用来干嘛的呢?

区块链网络的功效不胜枚举。比特币是一种数据货币和一个支付系统。它所有的防篡改区块中所保存的就是全部交易的分类账。那些贡献了他们自己的计算机的人被称为矿工。系统会给他们提供比特币作为奖励。

Ethereum 有意向附加功能。它可以承载你的代码,从头开始发展出一个区块链系统,而要构建一个属于你自己的系统也许会非常地困难(记住这得看有人为你牺牲他们的计算机运行能力才行哦)。Ethereum 就维护着这些耗损巨大的运算能力,而你则需要为这些计算消耗买单。

区块链应用并不非得是支付系统或者加密货币。它可以任何东西,像是一个社交网络,一个像?LiveEdu?这样的学习平台,等等。

私有区块链

Bitcoin, Ethereum 等等这些都是公共区块链的例子,任何人都可以成为其中的一分子。那如果我们想要有一个私有的区块链网络该如何呢?有些人想要一个私有的区块链是想干嘛呢?那就来瞧瞧下面的故事吧。

Mark 和 Sara

Mark 已经五个月没交房租了,当 Sara 找他要的时候,他就说晚点会给她。她付不起律师费,而法院强制执行诉讼就需要8个月甚至一年,所以唯一的选择就是去说服?Mark。

Joe 的生意

Joe 是一个商人,他经常要跟不同的公司做生意。几个月之前他和一家零售商签了一份合同,尽管合同条款都已经履约了,可零售商确拒绝付款。这帮人利用法律制度中的漏洞来游说 Joe,想以此达到少付钱的目的。Joe 在这以前就是有这方面经验的,在某些情况下,他会找法院求助,但这样做所耗费的时间和金钱却要损失他自己的利润。

我们该如何帮助 Sara 和 Joe 呢?

我们是不是能在其它地方解决这个问题呢? 在 Sara 遇到的这种情况中,我们需要让 Mark ?按月支付房租,这其实就是一个基于时间的触发机制。你的日历程序使用这样的触发器来给你提供预设事件的通知。

在 Joe 遇到的场景中,一旦合约中的条款都满足了,当事人就得付款,这其实就是一个基于条件的触发机制。你想想上次从 Amazon 买电子书的时候,是不是得先确认付款了,Amazon 才会把电子书发给你?

重点是,计算机程序会始终如一的执行诸如此类的指令。当你点击着这篇文章,向下滚动,诸如这类的操作,它也会照着执行不误。为了能帮助到 Sara ,我们需要将合同的条款转变成代码。

Sara 和 Mark 之间所订立的智能合同的伪代码

If?today’s?date?is?30th?and?rent?is?not?paid?then
Transfer?$500?from?Mark’s?account?to?Sara’s?account

可是我们在哪儿部署这些代码呢? 它就应该被部署到所有参与者的计算机上。Sara 的还有?Mark 的银行都会是这一个私有区块链网络的一部分。Joe 和 Sara 会签署一份编码的协议(也就是智能合同),然后这份协议会被分发到网络中去,Mark 的和 Sara 的银行都会有一份拷贝。在每个月的 30 号,当时钟跳动到 12 点整,协议好的金额就会从 Mark 的账户转移到 Sara 的账户上去。Joe 也开始使用智能合同来强制让他的客户支付协议好的货款。

Sara 高兴了,因为她再也不用去烦心 Mark 会不会如约付房租了。Joe 也高兴,因为他也不用找法院要说法了,省下这些精力,他可以继续发展自己的生意了。

私有区块链只限于业务中涉及到的相关各方,因此 Joe 不会是 Sara 和 Mark 所属区块链网络的一部分。

前行之路

现在你对此已经有点概念了,也许应该尝试一下?edX 上的课程(免费的哦),它会教你怎么在区块链上构建应用。

区块链初学者指南,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113467/feed/ 1
新贝彩票注册 - 加密货币的本质 http://www.cswhw.com.cn/113463/ http://www.cswhw.com.cn/113463/#respond Thu, 11 Jan 2018 02:37:40 +0000 http://www.cswhw.com.cn/?p=113463 2017 年比特币暴涨,其他币也像雨后春笋一样冒出来,已经有1000多种了。 很多人都在问,加密货币(cryptocurrency)的时代,真的来临了吗?将来会不会人类不再使用美元、人民币,改用加密货币?

加密货币的本质,首发于新贝彩票注册。

]]>
去年,比特币暴涨,其他币也像雨后春笋一样冒出来,已经有1000多种了。

很多人都在问,加密货币(cryptocurrency)的时代,真的来临了吗?将来会不会人类不再使用美元、人民币,改用加密货币?那么多品种,我应该使用哪一种币?要不要现在就去投资一些?

这些问题的答案,我也想知道,就花了很多时间查阅资料、研究协议。前两周发表的《区块链入门教程》和《比特币入门教程》,是我的学习心得。但是,那两篇教程主要介绍基本概念、探讨协议的可行性,没回答一个根本的问题:加密货币到底是什么?

下面就是我对这个问题的思考。阅读之前,如果你已经了解区块链和比特币,那很好;如果不了解,也没关系,本文不涉及技术,只讨论最基本的原理。

一、钱是什么?

我们都知道,人民币是钱,美元是钱,金银财宝是钱。我问一个问题,它们为什么能成为钱?

你可能回答,因为它们有价值,或者是价值的代表。但是,有价值的东西多了,为什么只有这些品种成为了钱?

答案很容易想到,因为人们普遍相信(认同)它们的价值,其他东西的价值难以得到普通认同,无法成为钱。比如,邮票的价值就没有普遍的认同,除了集邮爱好者,其他地方都不能当钱用。一般来说,认同的人越多,这种钱的通用性就越高。

我曾经去俄罗斯旅行,当地货币是卢布??墒?,一旦离开俄国,没人相信它的购买力,所以卢布离开俄国就没用了。相反,全世界人民都相信美元的价值,所以全世界都能用。我用美元付账的时候,我发现那些俄国人都很满意。

所以,钱的本质,或者说货币的本质,就是它的可信性。它必须使人们相信,它是有价值的,然后才能成为钱,才能被收藏和支付。

二、可信性

为什么钱必须是可信的?因为对方必须相信它的价值,否则你没法支付出去。那么,接下来的问题就是,可信的东西是否就是钱?

我的回答是 Yes。一样东西能否成为钱,只取决于人们是否相信它的价值,至于它是不是真的有价值,根本不重要。

如果马云在一张纸条上写”这张纸条价值10000元”,下面签了他的名,并且附上防伪标记。你说这纸条是钱吗?我跟你保证,这就是钱,你用来支付,人们都会接受,马云等同于发行了一种新的纸币。

比特币也是如此,它是什么,其实不太重要。重要的是,它必须保证自己是可信的,这样才能让足够的人相信它的价值,然后才能成为钱。

三、比特币的可信性

比特币要解决的核心问题,就是创造一种可信的数字凭证。由于这种凭证可信,所以能够当做货币。

比特币的技术基础是加密学,因为只有加密学才能保证它的可信性。一旦加密被破解,它就没法当作货币了。这也是这一类数字凭证被称为”加密货币”的原因。

技术人员对比特币感兴趣,还有一个重要原因。任何需要可靠的数字凭证的场合,也许都可以用到这种技术。

四、比特币的特点

比特币有三个特点,就是因为做到了这三点,所以它可信,能够当作钱。

首先,它不会被(轻易)偷走。或者反过来说,它使得你无法去偷别人,你只能花你自己的钱。因为必须要有别人的私钥,才能取出他的钱。正常情况下,你拿不到别人的私钥。

其次,它无法伪造。每一个比特币都能追溯来源,而所有比特币都来源于矿工获得的奖励??蠊ぶ挥行陆ㄇ?,才能获得奖励,这是很难的事情,所以无法伪造比特币。

最后,它无法大批生成。原因跟上一条一样,比特币的发行速度是稳定的,现在每10分钟新增12.5个,然后每四年减半,最终停止增长。因此不会像纸币那样,政府滥发导致通货膨胀。

五、比特币有实体吗?

由于后面要提到的原因,比特币不可能拥有实体,没法做到”从口袋里掏出一个币”这种场景,交易都必须通过互联网完成。

你可能会说,钱都有实体,怎么可能存在无形的钱呢?答案正好相反,钱就应该是无形的,那些实体的钱其实是对物质材料的浪费,由于技术不够发达,不得不做成实体。

我小时候买东西,都必须用现金,否则没法证明,自己拥有购买力。只有通过实体的钱,才能保证对方确实收到了钱。如果银行业发达,就不用现金了,可以使用信用卡。支付的时候,对方抄一下信用卡号码,查询银行”这个账户有钱吗”。银行回答有钱,OK,成交。

但是,互联网使得实体的信用卡也不需要了。如果存在一个开放的中央记账系统,任何人都可以查询,你把钱划到老板的账户,老板查询一下,发现收到了,交易自动成交,整个过程都是无形的,还需要什么信用卡呢?

这个中央记账系统已经实现了,就叫做区块链。

六、区块链的作用

区块链就是一个数据库,记载了所有的交易,用作中央记账系统。

每笔交易的核心,就是一句话,比如”张三向李四转移了1个比特币”。为了证明这句话可信,张三为它加上了数字签名。任何人都可以用张三的公钥,证明这确实是张三本人的行为。另一方面,其他人无法伪造张三的数字签名,所以不可能伪造这笔交易。

矿工们收到这句话,首先验证数字签名的可信性,然后验证张三确实拥有这些比特币(每一笔交易都有上一笔交易的编号,用来查询比特币的来源)。验证通过以后,就着手把这句话写入区块链了。一旦写入区块链,所有人就都可以查询到,因此这笔比特币就被认为,从张三转移到了李四。

区块链的作用就是把这句话永久保存下来了,让任何人都可以查看,并且任何人(包括张三本人在内)都无法再修改了。

货币是什么?其实就是这句话。这一句话就完成了一次支付。我们平时用人民币支付,其实只是用纸币表达这条信息。如果每个人都可以实时写入/读取中央记账系统(区块链),那么完全可以不携带货币。

七、双重支出

前面说过,交易不可能被伪造。但是,由于每一笔交易都是一串二进制信号,因此可能被复制。举例来说,”张三向李四转移了1个比特币”这句话,可能被其他人复制,也可能被张三自己复制,提交到区块链。

如果这句话被两次写入区块链,就意味着张三可以把同一笔钱花掉两次。但是,第二次写入的时候,查询区块链可以发现张三已经把这笔钱花掉了,从而认定这是不合法的交易,不能写入区块链。因此,复制交易是不可能的。

比较麻烦的是另一种情况,就是张三把同一笔钱付给两个人。他先向区块链提交一个交易”张三向李四转移了1个比特币”,然后又提交了另一个交易”张三向王五转移了1个比特币”。这两个交易都可能被认为是真实的交易,从而进入区块链。因此,必须有办法防止出现这种情况。

情况一:同一个矿工收到了这两个交易。那么他会察觉到,它们不可能同时成立,因此选择其中的一笔写入区块链。

情况二:矿工 A 收到了第一笔交易,矿工 B 收到了第二笔交易,他们各自都会认定这是合法的交易,分别把这两笔交易写入了两个区块,这时区块链就出现了分叉。

比特币协议规定,分叉点之后最先达到6个区块的那个分支,被认定为正式的区块链,其他分支都将被放弃。由于区块的生成速度由计算能力决定,所以到底哪一笔交易最后会被写入区块链,完全由它所在的分支能吸引多少计算能力决定。隐藏的逻辑是,如果大多数人(计算能力)选择相信某一笔交易,那么它就应该是真的。

综上所述,双重支出不可能发生。因为中央记账系统总有办法发现,你把同一笔钱花了两遍。但是,这也说明了比特币的一个代价,就是交易不能实时确认,必须等待至少一个小时。

八、参考链接

(完)

加密货币的本质,首发于新贝彩票注册。

]]>
http://www.cswhw.com.cn/113463/feed/ 0