# 一步步搭建物联网系统(教你设计物联网系统)

# 1 GNU/Linux 强大且Free

GNU/Linux

## 1.1 什么是Linux

Linux是一种自由和开放源码的类UNIX操作系统内核。目前存在着许多不同的Linux发行版，可安装在各种各样的电脑硬件设备，从手机、平板电脑、路由器和影音游戏控制台，到桌上型电脑，大型电脑和超级电脑。 Linux是一个领先的操作系统内核，世界上运算最快的10台超级电脑运行的都是基于Linux内核的操作系统。

Linux操作系统也是自由软件和开放源代码发展中最著名的例子。只要遵循GNU通用公共许可证,任何人和机构都可以自由地使用Linux的所有底层源代码，也可以自由地修改和再发布。严格来讲，Linux这个词本身只表示Linux内核，但在实际上人们已经习惯了用Linux来形容整个基于Linux内核，并且使用GNU工程各种工具和数据库的操作系统（也被称为GNU/Linux）。通常情况下，Linux被打包成供桌上型电脑和服务器使用的Linux发行版本。一些流行的主流Linux发行版本，包括Debian（及其衍生版本Ubuntu），Fedora和openSUSE等。Linux得名于电脑业余爱好者Linus Torvalds。

而不是如百度百科所讲的Linux操作系统是UNIX操作系统的一种克隆系统。它诞生于1991年的 Linux桌面[1]10 月5日（这是第一次正式向外公布的时间）。以后借助于Internet网络，并通过全世界各地计算机爱好者的共同努力，已成为今天世界上使用最多的一种UNIX类操作系统，并且使用人数还在迅猛增长。

Linux只是个内核，而不是操作系统，所以在这我们再理解一下操作系统是由什么组成的。

## 1.2 操作系统

操作系统（英语：Operating System，简称OS）是管理计算机硬件与软件资源的计算机程序，同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。 操作系统的型态非常多样，不同机器安装的操作系统可从简单到复杂，可从手机的嵌入式系统到超级计算机的大型操作系统。许多操作系统制造者对它涵盖范畴的定义也不尽一致，例如有些操作系统集成了图形用户界面(GUI)，而有些仅使用命令行界面(CLI)，而将GUI视为一种非必要的应用程序。

操作系统位于底层硬件与用户之间，是两者沟通的桥梁。用户可以通过操作系统的用户界面，输入命令。操作系统则对命令进行解释，驱动硬件设备，实现用户要求。以现代标准而言，一个标准PC的操作系统应该提供以下的功能：

- 进程管理（Processing management）
- 内存管理（Memory management）
- 文件系统（File system）
- 网络通信（Networking）
- 安全机制（Security）
- 用户界面（User interface）
- 驱动程序（Device drivers）

而让我们来看一下两者之间的不同之处，这是一张linux的架构图我们可以发现内核只是位于底层。

### 1.2.1 Linux架构图

Linux Kernel

#### 1.2.1.1 用户模式

应用程序（sh、vi、OpenOffice.org等）

复杂库（KDE、glib等） 简单库（opendbm、sin等）

C库（open、fopen、socket、exec、calloc等）

#### 1.2.1.2 内核模式

- 系统中断、调用、错误等软硬件消息
- 内核（驱动程序、进程、网络、内存管理等）
- 硬件（处理器、内存、各种设备）

我们可以发现，由linux内核+shell可以构成一个操作系统，而linux本身只是个内核，也就是图中的内核模式，负责控制系统的这些部分。也就是我们可以发现，Linux内核构成了一个操作系统除用户界面以外的部分，而shell就是这最后的用户界面。

而linux内核以外的部分就是由GNU计划构成的。

### 1.2.2 Shell

Shell

Shell是系统的用户界面，提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。

实际上Shell是一个命令解释器，它解释由用户输入的命令并且把它们送到内核。不仅如此，Shell有自己的编程语言用于对命令的编辑，它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点，比如它也有循环结构和分支控制结构等，用这种编程语言编写的Shell程序与其他应用程序具有同样的效果

bash 是一个为GNU计划编写的Unix shell。它的名字是一系列缩写：Bourne-Again SHell — 这是关于Bourne shell（sh）的一个双关语（Bourne again / born again）。Bourne shell是一个早期的重要shell，由史蒂夫·伯恩在1978年前后编写，并同Version 7 Unix一起发布。bash则在1987年由布莱恩·福克斯创造。在1990年，Chet Ramey成为了主要的维护者。

shell将会是我们在GNU/linux中经常用到的经常有到的工具之一，用来操作计算机用的。在迁移到linux之前我们可以试用cygwin来进行模拟：

Cygwin是许多自由软件的集合，最初由Cygnus Solutions开发，用于各种版本的Microsoft Windows上，运行`UNIX类`系统。

### 1.2.3 GCC

GCC（GNU Compiler Collection，GNU编译器套装），是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发行的自由软件，也是GNU计划的关键部分，亦是自由的类Unix及苹果电脑Mac OS X 操作系统的标准编译器。GCC（特别是其中的C语言编译器）也常被认为是跨平台编译器的事实标准。

GCC原名为GNU C语言编译器（GNU C Compiler），因为它原本只能处理C语言。GCC很快地扩展，变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada，以及Go与其他语言。

    #include <stdio.h>
    main()
    {
      printf("Hello world\n");
    }

    ~/temp/free> gcc hello.c -o hello
    hello.c:2:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
    main()
    ^~~~
    1 warning generated.
    ~/temp/free> ./hello
    Hello world

同shell一样，对于GNU/linux系统而言,GCC的作用也是无可取代的。当然如果只是一般用途的话，GCC对于一般用户可能没用，但是在些GNU/Linux系统上，我们可能就需要自己编译源码成二进制文件，而没有软件包，因而其重要性是不言而喻的。自然的如果我们自己动手编译GNU/Linux操作系统的话，我们会理解其的重要意义。有兴趣的同学可以试一下：Linux From Scratch (LFS)。

### 1.2.4 启动引导程序

最后，当我们构成以上的那些之后，我们就需要一个引导程序，以便使系统启动，引导进内核。

启动程序（bootloader）于电脑或其他计算机应用上，是指引导操作系统启动的程序。启动程序启动方式与程序视应用机型种类。例如在普通PC上，引导程序通常分为两部分：第一阶段引导程序位于主引导记录，用于引导位于某个分区上的第二阶段引导程序，如NTLDR、GNU GRUB等。

BIOS 开机完成后，bootloader就接手初始化硬件设备、创建存储器空间的映射，以便为操作系统内核准备好

正确的软硬件环境。

简单的bootloader的虚拟汇编码，如其后的八个指令:

- 0: 将P暂存器的值设为8
- 1: 检查纸带({paper tape)读取器，是否已经可以进行读取
- 2: 如果还不能进行读取, 跳至1
- 3: 从纸带读取器，读取一byte至累加器
- 4: 如为带子结尾，跳至8
- 5: 将暂存器的值，存储至P暂存器中的数值所指定的地址
- 6: 增加P暂存器的值
- 7: 跳至1

但是随着计算机操作系统越来越复杂，位于MBR的空间已经放不下引导操作系统的代码，于是就有了第二阶段的引导程序，而MBR中代码的功能也从直接引导操作系统变成了引导第二阶段的引导程序。

通常在一个GNU/Linux系统中选用GNUGRUB做为引导程序，例如Ubuntu就是用GRUB2。

GNU GRUB（简称“GRUB”）是一个来自GNU项目的启动引导程序。GRUB是多启动规范的实现，它允许用户可以在计算机内同时拥有多个操作系统，并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核，也可用于向这些内核传递启动参数。

GNU GRUB的前身为Grand Unified Bootloader。它主要用于类Unix系统；同大多Linux发行版一样，GNU系统也采用GNU GRUB作为它的启动器。Solaris从10 1/06版开始在x86系统上也采用GNU GRUB作为启动器。

以上也就构成了一个简单的操作系统。

## 1.3 从编译开始

我们以一次编译开始我们的Linux学习之旅。

### 1.3.1 开始之前

- 如果你没有用过GNU/Linux，我想你需要在虚拟机上安装一个。
- 一个主流的GNU/Linux发行版，如Ubuntu,CentOS,Debian,Mint,OpenSUSE,Fedora等等。
- 学会如何打开shell(ps:bash,zsh,sh等等)。

或者你也可以在Windows上安装Cygwin。

### 1.3.2 编译Nginx

1.下载这个软件的源码包

    wget http://nginx.org/download/nginx-1.7.4.tar.gz

wget是一个用于下载的软件，当然你也可以用软件，只是用wget似乎会比图形界面快哦。

2.解压软件包

    tar -vf nginx-1.7.4.tar.gz

-vf的意思是Extract，也就是解压，而tar则是这个解压软件的名字。看上去似乎比WinRAR来得复制得多，但是你可以计时一下，从下载到解压完，和你用鼠标比哪个比较快。

3.到nginx目录下

这里需要分两部进行

1).列出所有文件

    ls -al

    drwxr-xr-x   15 fdhuang  staff   510B Sep  2 13:44 nginx-1.7.4
    -rw-r--r--    1 fdhuang  staff   798K Aug  5 21:55 nginx-1.7.4.tar.gz

2).到nginx-1.7.4目录

    cd nginx-1.7.4

4.配置nginx

一次简单的配置如下

    ./configure

当你熟练以后，你可能和我一样用下面的配置(`注意`:用下面的代码会出错。)

    ./configure --user=www --group=www --add-module=../ngx_pagespeed-1.8.3.4-beta --add-module=../ngx_cache_purge --prefix=/usr/local/nginx --with-pcre --with-http_spdy_module --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-ipv6

过程中可能会提示你其中出了多少错误，而这时你便可以很愉快地去用搜索引擎搜索他们。

5.make

这里就会用到GCC等等。

    make

6.运行

如果运行顺利的话，应该可以直接

    ./objs/nginx

### 1.3.3 其他

1.如果没有wget,make,gcc等命令的时候可以用类似于下面的方法安装，

    sudo apt-get install gcc,make,wget

2.正常情况下一个开源项目都会有一个README，会告诉你应该如何去做。

## 1.4 包管理

GNU/Linux最方便的东西莫过于包管理了。

引自OpenSUSE官网的说明及图片1

package management

1. Linux 发行版无非就是一堆软件包 (package) 形式的应用程序加上整体地管理这些应用程序的工具。通常这些 Linux 发行版，包括 openSUSE，都是由成千上万不同的软件包构成的。

2. 软件包: 软件包不止是一个文件，内含构成软件的所有文件，包括程序本身、共享库、开发包以及使用说明等。

3. 元数据 (metadata) 包含于软件包之中，包含软件正常运行所需要的一些信息。软件包安装之后，其元数据就存储于本地的软件包数据库之中，以用于软件包检索。

4. 依赖关系 (dependencies) 是软件包管理的一个重要方面。实际上每个软件包都会涉及到其他的软件包，软件包里程序的运行需要有一个可执行的环境（要求有其他的程序、库等），软件包依赖关系正是用来描述这种关系的。

Linux 下的软件包通常是以下三种格式：

- tgz - tar gzip 文件。这类文件是基本的压缩软件包，可以容纳软件包维护者认为有用的所有的东西。此格式除本身的压缩格式外，并没有有关软件包内容的标准。
- deb - 此格式的软件包常用于 Debian 系统，是标准的 Debian 软件包格式。
- rpm - 此格式由 Red Hat Linux 所创建，并经由 LSB 标准化，现已为众多 Linux 发行版所采用，是一个优秀的软件包格式。openSUSE 即是用此格式。更多信息可以参阅此处。

> 所以这就需要能自动解决依赖关系的软件包管理器。软件包管理系统就是一个工具集，为系统提供一个统一的安装、升级、删除软件的方式。

## 1.5 Ubuntu LNMP

在余下的章节中，我们需要去部署，需要去使用Ubuntu。如果在Windows下可以使用LAMP，但是在这里我们只说Ubuntu。开始之前你需要安装好Ubuntu，无论是在虚拟机，还是在真机安装，或者是Docker。

### 1.5.1 Update软件包列表

`apt-get`是debian，ubuntu发行版的包管理工具。`apt-get update`可以确保我们的软件包列表是最新的，下面是一个简单的更新过程。

打开Terminal或者Konsole等等之类的终端控制台。

    root@70cdc7a176a5:/# sudo apt-get update
    Ign http://archive.ubuntu.com trusty InRelease
    Ign http://archive.ubuntu.com trusty-updates InRelease
    Ign http://archive.ubuntu.com trusty-security InRelease
    Ign http://archive.ubuntu.com trusty-proposed InRelease
    Get:1 http://archive.ubuntu.com trusty Release.gpg [933 B]
    Get:2 http://archive.ubuntu.com trusty-updates Release.gpg [933 B]
    Get:3 http://archive.ubuntu.com trusty-security Release.gpg [933 B]
    Get:4 http://archive.ubuntu.com trusty-proposed Release.gpg [933 B]
    Get:5 http://archive.ubuntu.com trusty Release [58.5 kB]
    Get:6 http://archive.ubuntu.com trusty-updates Release [62.0 kB]
    Get:7 http://archive.ubuntu.com trusty-security Release [62.0 kB]
    Get:8 http://archive.ubuntu.com trusty-proposed Release [209 kB]
    Get:9 http://archive.ubuntu.com trusty/main Sources [1335 kB]
    Get:10 http://archive.ubuntu.com trusty/restricted Sources [5335 B]
    Get:11 http://archive.ubuntu.com trusty/universe Sources [7926 kB]
    Get:12 http://archive.ubuntu.com trusty/main amd64 Packages [1743 kB]
    Get:13 http://archive.ubuntu.com trusty/restricted amd64 Packages [16.0 kB]
    Get:14 http://archive.ubuntu.com trusty/universe amd64 Packages [7589 kB]
    64% [14 Packages 664 kB/7589 kB 9%]                          58.3 kB/s 1min 58s

更新完应该会显示:

    Fetched 20.5 MB in 5min 22s (63.6 kB/s)
    Reading package lists... Done

### 1.5.2 安装MySQL

安装命令

    sudo apt-get install mysql-server php5-mysql

过程:

    root@70cdc7a176a5:/# sudo apt-get install mysql-server php5-mysql
    Reading package lists... 0%
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following extra packages will be installed:
      libaio1 libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18
      libterm-readkey-perl libwrap0 lsof mysql-client-5.5 mysql-client-core-5.5
      mysql-common mysql-server-5.5 mysql-server-core-5.5 php5-common php5-json
      psmisc tcpd
    Suggested packages:
      libclone-perl libmldbm-perl libnet-daemon-perl libplrpc-perl
      libsql-statement-perl libipc-sharedcache-perl tinyca mailx php5-user-cache
    The following NEW packages will be installed:
      libaio1 libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18
      libterm-readkey-perl libwrap0 lsof mysql-client-5.5 mysql-client-core-5.5
      mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 php5-common
      php5-json php5-mysql psmisc tcpd
    0 upgraded, 19 newly installed, 0 to remove and 12 not upgraded.
    Need to get 9982 kB of archives.
    After this operation, 99.1 MB of additional disk space will be used.
    Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main libaio1 amd64 0.3.109-4 [6364 B]
    Get:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/main mysql-common all 5.5.40-0ubuntu0.14.04.1 [14.1 kB]
    Get:3 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libmysqlclient18 amd64 5.5.40-0ubuntu0.14.04.1 [598 kB]
    Get:4 http://archive.ubuntu.com/ubuntu/ trusty/main libwrap0 amd64 7.6.q-25 [46.2 kB]
    Get:5 http://archive.ubuntu.com/ubuntu/ trusty/main libdbi-perl amd64 1.630-1 [879 kB]
    Get:6 http://archive.ubuntu.com/ubuntu/ trusty/main libdbd-mysql-perl amd64 4.025-1 [99.3 kB]
    Get:7 http://archive.ubuntu.com/ubuntu/ trusty/main libterm-readkey-perl amd64 2.31-1 [27.4 kB]
    Get:8 http://archive.ubuntu.com/ubuntu/ trusty-updates/main mysql-client-core-5.5 amd64 5.5.40-0ubuntu0.14.04.1 [703 kB]
    Get:9 http://archive.ubuntu.com/ubuntu/ trusty-updates/main mysql-client-5.5 amd64 5.5.40-0ubuntu0.14.04.1 [1466 kB]
    Get:10 http://archive.ubuntu.com/ubuntu/ trusty-updates/main mysql-server-core-5.5 amd64 5.5.40-0ubuntu0.14.04.1 [3215 kB]
    47% [10 mysql-server-core-5.5 850 kB/3215 kB 26%]             79.9 kB/s 1min 6s

在安装的过程中会要求你输入数据库密码。(默认为空)

### 1.5.3 安装Nginx

    echo "deb http://ppa.launchpad.net/nginx/stable/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/nginx-stable.list
    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
    sudo apt-get update
    sudo apt-get install nginx

启动Nginx Server

    sudo service nginx start

### 1.5.4 安装PHP

sudo apt-get install php5-fpm

安装过程

    root@70cdc7a176a5:/# sudo apt-get install php5-fpm
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following extra packages will be installed:
      libsystemd-daemon0
    Suggested packages:
      php-pear
    The following NEW packages will be installed:
      libsystemd-daemon0 php5-fpm
    0 upgraded, 2 newly installed, 0 to remove and 12 not upgraded.
    Need to get 2201 kB of archives.
    After this operation, 9326 kB of additional disk space will be used.
    Do you want to continue? [Y/n] y
    Get:1 http://archive.ubuntu.com/ubuntu/ trusty-proposed/main libsystemd-daemon0 amd64 204-5ubuntu20.8 [9608 B]
    Get:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/universe php5-fpm amd64 5.5.9+dfsg-1ubuntu4.5 [2191 kB]
    Fetched 2201 kB in 1min 5s (33.6 kB/s)
    Selecting previously unselected package libsystemd-daemon0:amd64.
    (Reading database ... 13105 files and directories currently installed.)
    Preparing to unpack .../libsystemd-daemon0_204-5ubuntu20.8_amd64.deb ...
    Unpacking libsystemd-daemon0:amd64 (204-5ubuntu20.8) ...
    Selecting previously unselected package php5-fpm.
    Preparing to unpack .../php5-fpm_5.5.9+dfsg-1ubuntu4.5_amd64.deb ...
    Unpacking php5-fpm (5.5.9+dfsg-1ubuntu4.5) ...
    Processing triggers for ureadahead (0.100.0-16) ...
    Setting up libsystemd-daemon0:amd64 (204-5ubuntu20.8) ...
    Setting up php5-fpm (5.5.9+dfsg-1ubuntu4.5) ...

    Creating config file /etc/php5/fpm/php.ini with new version
    php5_invoke: Enable module pdo for fpm SAPI
    php5_invoke: Enable module pdo_mysql for fpm SAPI
    php5_invoke: Enable module opcache for fpm SAPI
    php5_invoke: Enable module json for fpm SAPI
    php5_invoke: Enable module mysql for fpm SAPI
    php5_invoke: Enable module mysqli for fpm SAPI
    invoke-rc.d: policy-rc.d denied execution of start.
    Processing triggers for libc-bin (2.19-0ubuntu6.3) ...
    Processing triggers for ureadahead (0.100.0-16) ...

1. https://zh.opensuse.org/index.php?title=%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%AE%A1%E7%90%86&variant=zh↩