Wetts's blog

Stay Hungry, Stay Foolish.

0%

Bias、Error、Variance

  • 准:bias 描述的是根据样本拟合出的模型的输出预测结果的期望与样本真实结果的差距,简单讲,就是在样本上拟合的好不好。要想在 bias 上表现好,low bias,就得复杂化模型,增加模型的参数,但这样容易过拟合(overfitting),过拟合对应上图是 high variance,点很分散。low bias 对应就是点都打在靶心附近,所以瞄的是准的,但手不一定稳。
  • 确:varience 描述的是样本上训练出来的模型在测试集上的表现,要想在 variance 上表现好,low varience,就要简化模型,减少模型的参数,但这样容易欠拟合(unfitting),欠拟合对应上图是 high bias,点偏离中心。low variance 对应就是点都打的很集中,但不一定是靶心附近,手很稳,但是瞄的不准。

Error = Bias + Variance

Bias、Error、Variance2

在航空中,pitch、yaw、roll 下图所示。

  • pitch 是围绕 X 轴旋转,也叫做俯仰角。
  • yaw 是围绕 Y 轴旋转,也叫偏航角。
  • roll 是围绕 Z 轴旋转,也叫翻滚角。

pitch、yaw、roll1

在 3D 系统中,假设视点为原点,则视点坐标系如下图所示,通常 z 轴的负方向是视点方向(OpenGL)。
pitch、yaw、roll2

在多元分类的问题中,我们默认采用 softmax 函数,具体表现为将多个神经元的输出,映射到 0~1 的区间中,按概率高低进行分类,各概率之和为 1。

某分类的概率数学表达式为:$y_{i}=e^{i} / \Sigma_{j=1} e^{j}$

具体来说,假设有四个输出单元,分别为:

  • $y_{1}=e^{x 1} /\left(e^{x 1}+e^{x 2}+e^{x 3}+e^{x 4}\right)$,假设其概率为 0.4。
  • $y_{2}=e^{x 2} /\left(e^{x 1}+e^{x 2}+e^{x 3}+e^{x 4}\right)$,假设其概率为 0.15。
  • $y_{3}=e^{x 3} /\left(e^{x 1}+e^{x 2}+e^{x 3}+e^{x 4}\right)$,假设其概率为 0.15。
  • $y_{4}=e^{x 4} /\left(e^{x 1}+e^{x 2}+e^{x 3}+e^{x 4}\right)$,假设其概率为 0.3。

转自:https://zhuanlan.zhihu.com/p/48982978

在深度学习里,Tensor 实际上就是一个多维数组(multidimensional array)。

而 Tensor 的目的是能够创造更高维度的矩阵、向量。

张量1

现在将三维的张量用一个正方体来表示:
张量2

这样子可以进一步生成更高维的张量:
张量3

这有啥用呢?在用 TensorFlow 处理更高维数据结构的时候,最好可以能够在脑子里相出数据的形状。

举个简单的例子,彩色图像文件(RGB)一般都会处理成 3-d tensor,每个 2d array 中的 element 表示一个像素,R 代表 Red,G 代表 Green,B 代表 Blue:
张量4

而用 Python 举例子的话,来看看下面这个表格:
张量5

再来看看 Tensor 对象的 3 个属性:

  1. rank: number of dimensions
  2. shape: number of rows and columns
  3. type: data type of tensor’s elements

根据上面的张量说明图,是不是可以将属性和对象对应起来呢?

最后总结一下:在深度学习中,Tensor 实际上就是一个多维数组(multidimensional array),其目的是能够创造更高维度的矩阵、向量。我们通过图示和 Python 的实例能够想象 Tensor 的空间构造以及如何用 Tensor 的属性来构造 Tensor。

batch

深度学习的优化算法,说白了就是梯度下降。按照损失函数的计算规模和每次的参数更新分类有三种方式。

批梯度下降(BGD——Batch gradient descent)

损失函数计算:遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。

特点:每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习。

随机梯度下降(SGD——stochastic gradient descent)

损失函数计算:每看一个数据就算一下损失函数,然后求梯度更新参数。

特点:速度比较快,但是收敛性能不太好,可能在最优点附近晃来晃去,hit 不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。

小批梯度下降(mini-batch gradient decent)

为了克服两种方法的缺点,现在一般采用的是一种折中手段。

损失函数计算:把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,计算量也不是很大。

iterations

iterations(迭代):每一次迭代都是一次权重更新,每一次权重更新需要 batch_size 个数据进行 Forward 运算得到损失函数,再 BP 算法更新参数。1 个 iteration 等于使用 batchsize 个样本训练一次。

epochs

epochs 被定义为向前和向后传播中所有批次的单次训练迭代。这意味着 1 个周期是整个输入数据的单次向前和向后传递。简单说,epochs 指的就是训练过程中数据将被“轮”多少次。

三者之间的关系

训练集有 1000 个样本,batch_size = 10,那么训练完整个样本集需要: 100 次 iteration,1 次 epoch。

具体的计算公式为:
one epoch = numbers of iterations = N = 训练样本的数量 / batch_size

转自:https://blog.csdn.net/sch0120/article/details/70256318

bash 的 startup 文件

Linux shell 是用户与 Linux 系统进行交互的媒介,而 bash 作为目前 Linux 系统中最常用的 shell,它支持的 startup 文件也并不单一,甚至容易让人感到费解。本文以 CentOS7 系统为例,对 bash 的 startup 文件进行一些必要的梳理和总结。

根据bash手册上的描述:

  • /etc/profile: The systemwide initialization file, executed for login shells
  • /etc/bash.bash_logout: The systemwide login shell cleanup file, executed when a login shell exits
  • ~/.bash_profile: The personal initialization file, executed for login shells
  • ~/.bashrc: The individual per-interactive-shell startup file
  • ~/.bash_logout: The individual login shell cleanup file, executed when a login shell exits

此外,bash 还支持 ~/.bash_login~/.profile 文件,作为对其他 shell 的兼容,它们与 ~/.bash_profile 文件的作用是相同的。

备注:Debian系统会使用 ~/.profile 文件取代 ~/.bash_profile文件,因此在相关细节上,会与 CentOS 略有不同。

“profile”与“rc”系列

通过名字的不同,我们可以直观地将 startup 文件分为“profile”与“rc”两个系列,其实他们的功能都很类似,但是使用的场景不同,这也是大家最容易忽略的地方。

所谓的不同场景,其实就是 shell 的运行模式。我们知道运行中的 bash 有“交互”和“登陆”两种属性,而执行“profile”系列还是“rc”系列,就与shell的这两个属性有关。

原理上讲,“登陆 shell”启动时会加载“profile”系列的 startup 文件,而“交互式非登陆 shell”启动时会加载“rc”系列的 startup 文件。

“profile”系列的执行场景

根据 bash 手册上的描述:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

When a login shell exits, bash reads and executes commands from the files ~/.bash_logout and /etc/bash.bash_logout, if the files exists.

“profile”系列的代表文件为 ~/.bash_profile,它用于“登录 shell”的环境加载,这个“登录 shell”既可以是“交互式”的,也可以是“非交互式”的。

通过 --noprofile 选项可以阻止系统加载“profile”系列的 startup 文件。

交互式登陆 shell

对于交互式的登陆 shell 而言,CentOS 规定了 startup 文件的加载顺序如下:

登陆过程:

  1. 读取并执行 /etc/profile 文件;
  2. 读取并执行 ~/.bash_profile 文件;
    • 若文件不存在,则读取并执行 ~/.bash_login 文件;
    • 若文件不存在,则读取并执行 ~/.profile 文件;

登出过程:

  1. 读取并执行 ~/.bash_logout 文件;
  2. 读取并执行 /etc/bash.bash_logout 文件;

为了完成实验,我新建了一些系统默认没有提供的 startup 文件,例如 /etc/bash.bash_logout。然后在每个文件中打印了文件名,并将它们之间的显式调用语句注释掉,例如 ~/.bash_profile 对 ~/.bashrc 的显式调用。

“交互式登陆shell”的实验结果如下:

1
2
3
4
5
6
7
8
9
[root@localhost ~]# su - chen
Last login: Tue Apr 18 17:15:08 CST 2017 from 192.168.161.1 on pts/2
execute /etc/profile
execute ~/.bash_profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[root@localhost ~]#

我们看到,因为执行了 ~/.bash_profile 文件,所以优先级更低的 ~/.bash_login~/.profile 文件并没有被执行。

我们可以删除 ~/.bash_profile~/.bash_login 文件,这样系统就会找到并执行 ~/.profile 文件:

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# mv /home/chen/.bash_profile /home/chen/.bash_profile.bak
[root@localhost ~]# mv /home/chen/.bash_login /home/chen/.bash_login.bak
[root@localhost ~]# su - chen
Last login: Tue Apr 18 17:27:21 CST 2017 on pts/1
execute /etc/profile
execute ~/.profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[root@localhost ~]#

非交互式登陆 shell

对于非交互式的登陆 shell 而言,CentOS 规定了 startup 文件的加载顺序如下:

登陆过程:

  1. 读取并执行 /etc/profile 文件;
  2. 读取并执行 ~/.bash_profile 文件;
    • 若文件不存在,则读取并执行 ~/.bash_login 文件;
    • 若文件不存在,则读取并执行 ~/.profile 文件;

我们注意到,与“交互式登陆 shell”相比,“非交互式登陆 shell”并没有登出的过程,实验也证实了这一点:

1
2
3
4
5
-bash-4.2$ bash --login -c "uname -r"
execute /etc/profile
execute ~/.bash_profile
3.10.0-514.el7.x86_64
-bash-4.2$ # 此时非交互式shell已退出

“rc”系列的执行场景

根据 bash 手册上的描述:

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the –norc option. The –rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

“rc”系列的代表文件为 ~/.bashrc,它用于“交互式非登录 shell”的环境加载。

通过 --norc 选项可以阻止系统加载“rc”系列的 startup 文件;通过 --rcfile 选项可以使用指定的文件替代系统默认的 ~/.bashrc 文件。

交互式非登陆 shell

对于交互式的非登陆 shell 而言,CentOS 规定了 startup 文件的加载顺序如下:

  1. 读取并执行 ~/.bashrc--rcfile 选项指定的文件

这里需要说明,其实“rc”系列 startup 文件还包括 /etc/bashrc。但是系统并不直接调用这个文件,而是通过 ~/.bashrc 文件显式地调用它。

为了完成实验,我在每个 startup 文件中打印了文件名,并将它们之间的显式调用语句注释掉,例如 ~/.bashrc/etc/bashrc 的显式调用。

“交互式非登陆 shell”的实验结果如下:

1
2
3
4
5
[root@localhost ~]# su chen
execute ~/.bashrc
bash-4.2$ exit
exit
[root@localhost ~]#

startup 文件的默认调用关系

细心的用户会发现,startup 文件的加载并不像上面所述的那样简单。这是因为在 CentOS 中,startup 文件之间还存在着默认的显式调用关系,它们是:

  1. ~/.bash_profile 显式调用 ~/.bashrc 文件;
  2. ~/.bashrc 显式调用 /etc/bashrc 文件;

再看 startup 文件

分别打开 /etc/profile/etc/bashrc 两个文件,我们可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost ~]# head /etc/profile
# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

[root@localhost ~]# head /etc/bashrc
# /etc/bashrc

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

由此可见,“profile”系列文件的主要目的在于为“登录 shell”设置环境变量和启动程序;而“rc”系列文件的主要目的在于设置功能和别名。

顺便提一句,Linux 中“rc”是英文“run command”的缩写,表示文件中存放需要执行的命令。其实这也非常符合逻辑,设置功能就要执行 shopt 命令,而设置别名要执行 alias 命令。与“rc”系列互补,“profile”系列用来设置环境变量,它不会去调用这两个命令,但却经常需要使用 export 语句。不信你可以看一看这两个文件。

另外值得一提的是,这两个文件同时提到了一个位置:/etc/profile.d 目录。这个目录用于存放个性化配置脚本,你可以把自己需要的全局配置放入以 .sh 结尾的文件中,系统在执行 /etc/profile/etc/bashrc 文件时,都会择机调用它们。这样做最大的好处是便于维护,而且相对更加安全。

这些文件的编写方法,可以参考目录下已有的文件:

1
2
3
[root@localhost ~]# ls /etc/profile.d/*.sh
/etc/profile.d/256term.sh /etc/profile.d/colorls.sh /etc/profile.d/less.sh
/etc/profile.d/colorgrep.sh /etc/profile.d/lang.sh /etc/profile.d/which2.sh

总结

  • 对于“登录 shell”而言
    • “交互式”执行“登陆”和“登出”相关的“profile”系列 startup 文件
    • “非交互式”只执行“登陆”相关的“profile”系列 startup 文件
  • 对于“非登陆 shell”而言
    • “交互式”执行“rc”系列的 startup 文件
    • 而“非交互式”执行的配置文件由环境变量 BASH_ENV 指定。

Linux 中 startup 文件区分全局和个人:全局 startup 文件放在 /etc 目录下,用于设置所有用户共同的配置,除非你清楚地知道你在做的事情,否则不要轻易改动它们;个人 startup 文件放在 ~ 目录下,用于设置某个用户的个性化配置。

~/.bash_profile 会显式调用 ~/.bashrc 文件,而 ~/.bashrc 又会显式调用 /etc/bashrc 文件,这是为了让所有交互式界面看起来一样。无论你是从远程登录(登陆 shell),还是从图形界面打开终端(非登陆 shell),你都拥有相同的提示符,因为环境变量 PS1 在 /etc/bashrc 文件中被统一设置过。

下面我来对startup文件进行一个完整的总结:

startup 文件 交互登陆 非交互登陆 交互非登陆 非交互非登陆
/etc/profile 直接执行1 直接执行1 - -
~/.bash_profile 直接执行2 直接执行2 - -
~/.bash_login 条件执行2 条件执行2 - -
~/.profile 条件执行2 条件执行2 - -
~/.bash_logout 直接执行3 不执行 - -
/etc/bash.bash_logout 直接执行4 不执行 - -
~/.bashrc 引用执行2.1 引用执行2.1 直接执行1 -
/etc/bashrc 引用执行2.2 引用执行2.2 引用执行1.1 -

备注:

  1. “直接执行”表示此文件被系统直接调用,它的执行是无条件的;
  2. “条件执行”表示此文件被系统调用是有先决条件的(没有优先级更高的文件可用);
  3. “引用执行”表示此文件不是被系统直接调用的,而是被其他文件显式调用的;
  4. 后面的数字表示文件被调用的顺序,数字越大调用越靠后;
  5. “非交互非登陆” shell 的配置文件可以由 BASH_ENV 环境变量指定;

最后我想说的是,知道 startup 文件何时被执行并不是关键,关键是要理解自己的情况应该去修改哪个 startup 文件。

如果你想对 bash 的功能进行设置或者是定义一些别名,推荐你修改 ~/.bashrc 文件,这样无论你以何种方式打开 shell,你的配置都会生效。而如果你要更改一些环境变量,推荐你修改 ~/.bash_profile 文件,因为考虑到 shell 的继承特性,这些更改确实只应该被执行一次(而不是多次)。针对所有用户进行全局设置,推荐你在 /etc/profile.d 目录下添加以 .sh 结尾的文件,而不是去修改全局 startup 文件。

转自:https://blog.csdn.net/sch0120/article/details/70226903

Linux shell 是用户与 Linux 系统进行交互的媒介,而 bash 作为目前 Linux 系统中最常用的 shell,它在运行时具有两种属性,即“交互”与“登陆”。

  • 按照 bash 是否与用户进行交互,可以将其分为“交互式”与“非交互式”;
  • 而按照 bash 是否被用户登陆,又可将其分为“登陆 shell”与“非登陆 shell”。

“交互式”与“非交互式”

含义说明

  • 交互式,是 shell 的一种运行模式,交互式 shell 等待你输入命令,并且立即执行,然后将结果反馈给你。这是每个 CLI 用户都非常熟悉的流程:登录、执行一些命令、登出。当你登出后,这个 shell 就终止了。
  • 非交互式,是 shell 的另一种运行模式,它专门被用来执行预先设定的命令。在这种模式下,shell 不与用户进行交互,而是读取存放在脚本文件中的命令并执行它们。当它读到文件的结尾,这个 shell 就终止了。

启动方法

根据bash手册上的描述:

An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.

从上面的描述看,只要执行 bash 命令的时候,不带有“选项以外的参数”或者 -c 选项,就会启动一个交互式 shell。要理解这句话,就要弄懂“选项以外的参数”是什么意思,其实它指的就是 shell 的脚本文件;而 -c 选项将指定字符串作为命令读入 bash,也就相当于执行指定的命令,它和前者有些类似,只是不从脚本文件中读取罢了。请看例子:

1
2
3
4
5
6
7
8
9
[chen@localhost Temp]$ echo "uname -r; date" > script.sh
[chen@localhost Temp]$ bash ./script.sh
3.10.0-514.el7.x86_64
Tue Apr 18 14:43:50 CST 2017
[chen@localhost Temp]$
[chen@localhost Temp]$ bash -c "uname -r; date"
3.10.0-514.el7.x86_64
Tue Apr 18 14:44:49 CST 2017
[chen@localhost Temp]$

通常来说,用于执行脚本的 shell 都是“非交互式”的,但我们也有办法把它启动为“交互式” shell,方法就是在执行 bash 命令时,添加 -i 选项:

1
2
3
4
[chen@localhost Temp]$ bash -c "echo \$-"
hBc
[chen@localhost Temp]$ bash -i -c "echo \$-"
himBHc

我们看到,添加了 -i 选项的 bash -c 命令为我们启动了一个“交互式” shell。

判别方法

根据 bash 手册上的描述:

PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.

用于在 shell 脚本和 startup 文件中判断当前 shell“交互”属性的方法,就是判断变量 PS1 是否有值,或者判断变量 $- 是否包含 i,请看例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
[chen@localhost Temp]$ cat ./test1.sh 
echo "\$0 : $0"
echo "\$- : $-"
echo "\$PS1 : $PS1"
[chen@localhost Temp]$ bash ./test1.sh # 非交互式shell
$0 : ./test1.sh
$- : hB
$PS1 :
[chen@localhost Temp]$ bash -i ./test1.sh # 交互式shell
$0 : ./test1.sh
$- : himB
$PS1 : [\u@\h \W]\$
[chen@localhost Temp]$

“登陆 shell”与“非登陆 shell”

含义说明

“登陆 shell”通常指的是:

  1. 用户通过输入用户名/密码(或证书认证)后启动的 shell;
  2. 通过带有 -l|--login 参数的 bash 命令启动的 shell。

例如,系统启动、远程登录、使用 su - 切换用户、通过 bash --login 命令启动 bash 等。

而其他情况启动的 shell 基本上就都是“非登陆 shell”了。

例如,从图形界面启动终端、使用 su 切换用户、通过 bash 命令启动 bash 等。

判别方法

根据 bash 手册上的描述:

A login shell is one whose first character of argument zero is a -, or one started with the --login option.

我们可以通过在 shell 中 echo $0 查看,显示 -bash 的一定是“登陆 shell”,反之显示 bash 的则不好说。

1
2
3
4
[chen@localhost ~]$ bash --login
[chen@localhost ~]$ echo $0
bash
[chen@localhost ~]$

可以看出,使用 bash --login 启动的“登陆 shell”,其 $0 也并非以 - 开头,这也就是为什么手册上的描述里使用“or”的原因。

另外,当我们执行 exit 命令退出 shell 时,也可以观察到它们的不同之处:

1
2
3
4
5
6
7
[chen@localhost ~]$ bash --login
[chen@localhost ~]$ exit # 退出登陆shell
logout
[chen@localhost ~]$ bash
[chen@localhost ~]$ exit # 退出非登陆shell
exit
[chen@localhost ~]$

原则上讲,我们使用 logout 退出“登陆 shell”,使用 exit 退出“非登录 shell”。但其实 exit 命令会判断当前 shell 的“登陆”属性,并分别调用 logout 或 exit 指令,因此使用起来相对方便。

主要区别

对于用户而言,“登录 shell”和“非登陆 shell”的主要区别在于启动 shell 时所执行的 startup 文件不同。

简单来说,“登录 shell”执行的 startup 文件为 ~/.bash_profile,而“非登陆 shell”执行的 startup 文件为 ~/.bashrc

/boot

引导程序,内核等存放的目录。

这个目录,包括了在引导过程中所必需的文件,引导程序的相关文件(例如 grub、lilo 以及相应的配置文件以及 Linux 操作系统内核相关文件(例如 vmlinuz 等一般都存放在这里。在最开始的启动阶段,通过引导程序将内核加载到内存,完成内核的启动(这个时候,虚拟文件系统还不存在,加载的内核虽然是从硬盘读取的,但是没经过 Linux 的虚拟文件系统,这是比较底层的东西来实现的。然后内核自己创建好虚拟文件系统,并且从虚拟文件系统的其他子目录中(例如 /sbin 和 /etc 加载需要在开机启动的其他程序或者服务或者特定的动作(部分可以由用户自己在相应的目录中修改相应的文件来配制。如果我们的机器中包含多个操作系统,那么可以通过修改这个目录中的某个配置文件(例如 grub.conf 来调整启动的默认操作系统,系统启动的择菜单,以及启动延迟等参数)。

/sbin

超级用户可以使用的命令的存放目录。

存放大多涉及系统管理的命令(例如引导系统的 init 程序,是超级权限用户 root 的可执行命令存放地,普通用户无权限执行这个目录下的命令(但是时普通用户也可能会用到。这个目录和 /usr/sbin; /usr/X11R6/sbin 或 /usr/local/sbin 等目录是相似的,我们要记住,凡是目录 sbin 中包含的都是 root 权限才能执行的,这样就行了。后面会具体区分)。

/bin

普通用户可以使用的命令的存放目录。

系统所需要的那些命令位于此目录,比如 ls、cp、mkdir 等命令;类似的目录还 /usr/bin,/usr/local/bin 等等。这个目录中的文件都是可执行的、普通用户都可以使用的命令。作为基础系统所需要的最基础的命令就是放在这里。

/lib

根目录下的所程序的共享库目录。

此目录下包含系统引导和在根用户执行命令时候所必需用到的共享库。做个不太好但是比较形象的比喻,点类似于 Windows 上面的 system32 目录。理说,这里存放的文件应该是 /bin 目录下程序所需要的库文件的存放地,也不排除一些例外的情况。类似的目录还 /usr/lib,/usr/local/lib 等等。

/dev

设备文件目录。

在 Linux 中设备都是以文件形式出现,这里的设备可以是硬盘,键盘,鼠标,网卡,终端,等设备,通过访问这些文件可以访问到相应的设备。设备文件可以使用 mknod 命令来创建,具体参见相应的命令;而为了将对这些设备文件的访问转化为对设备的访问,需要向相应的设备提供设备驱动模块(一般将设备驱动编译之后,生成的结果是一个 *.ko 类型的二进制文件),在内核启动之后,再通过 insmod 等命令加载相应的设备驱动之后,我们就可以通过设备文件来访问设备了。一般来说,想要 Linux 系统支持某个设备,只要个东西:相应的硬件设备,支持硬件的驱动模块,以及相应的设备文件。

/home

普通用户的家目录($HOME 目录)。

在 Linux 机器上,用户主目录通常直接或间接地置在此目录下。其结构通常由本地机的管理员来决定。通常而言,系统的每个用户都自己的家目录,目录以用户名作为名字存放在 /home 下面(例如 quietheart 用户,其家目录的名字为 /home/quietheart。该目录中保存了绝大多数的用户文件(用户自己的配置文件,定制文件,文档,数据等),root 用户除外(参见后面的 /root 目录。由于这个目录包含了用户实际的数据,通常系统管理员为这个目录单独挂载一个独立的磁盘分区,这样这个目录的文件系统格式就可能和其他目录不一样了(尽管表面上看,这个目录还是属于根目录的一棵子树上),有利于数据的维护。

/root

用户 root 的 $HOME 目录。

系统管理员(就是 root 用户或超级用户)的主目录比较特殊,不存放在 /home 中,而是直接放在 /root 目录下了。

/etc

全局的配置文件存放目录。

系统和程序一般都可以通过修改相应的配置文件,来进行配置。例如,要配置系统开机的时候启动那些程序,配置某个程序启动的时候显示什么样的风格等等。通常这些配置文件都集中存放在 /etc 目录中,所以想要配置什么东西的话,可以在 /etc 下面寻找我们可能需要修改的文件。一些大型套件,如 X11,在 /etc 下它们自己的子目录。系统配置文件可以放在这里或在 /usr/etc。 不过所程序总是在 /etc 目录下查找所需的配置文件,你也可以将这些文件链接到目录 /usr/etc。另外,还一个需要注意的常见现象就是,当某个程序在某个用户下运行的时候,可能会在该用户的家目录中生成一个配置文件(一般这个文件最开始就是 /etc 下相应配置文件的拷贝),存放相应于“当前用户”的配置,这样当前用户可以通过配置这个家目录的配置文件,来改变程序的行为,并且这个行为只是该用户特定的。原因就是:一般来说一个程序启动,如果需要读取一些配置文件的话,它会首先读取当前用户家目录的配置文件,如果存在就使用;如果不存在它就到 /etc 下读取全局的配置文件进而启动程序。就是这个配置文件不自动生成,我们手动在自己的家目录中创建一个文件的话,也有许多程序会首先读取到这个家目录的文件并且以它的配置作为启动的选项(例如我们可以在家目录中创建 vim 程序的配置文件 .vimrc,来配置自己的 vim 程序)。

/usr

这个目录中包含了命令库文件和在通常操作中不会修改的文件。

这个目录对于系统来说也是一个非常重要的目录,其地位类似 Windows 上面的”Program Files”目录。安装程序的时候,默认就是安装在此文件内部某个子文件夹内。输入命令后系统默认执行 /usr/bin 下的程序(当然,前提是这个目录的路径已经被添加到了系统的环境变量中)。此目录通常也会挂载一个独立的磁盘分区,它应保存共享只读类文件,这样它可以被运行 Linux 的不同主机挂载。

/usr/lib

目标库文件,包括动态连接库加上一些通常不是直接调用的可执行文件的存放位置。

这个目录功能类似 /lib 目录,按理说,这里存放的文件应该是 /bin 目录下程序所需要的库文件的存放地,也不排除一些例外的情况。

/usr/bin

一般使用者使用并且不是系统自检等所必需可执行文件的目录。

此目录相当于根文件系统下的对应目录(/bin),非启动系统,非修复系统以及非本地安装的程序一般都放在此目录下。

/usr/sbin

管理员使用的非系统必须的可执行文件存放目录。

此目录相当于根文件系统下的对应目录(/sbin),保存系统管理程序的二进制文件,并且这些文件不是系统启动或文件系统挂载 /usr 目录或修复系统所必需的。

/usr/share

存放共享文件的目录。

在此目录下不同的子目录中保存了同一个操作系统在不同构架下工作时特定应用程序的共享数据(例如程序文档信息)。使用者可以找到通常放在 /usr/doc 或 /usr/lib 或 /usr/man 目录下的这些类似数据。

/usr/include

C 程序语言编译使用的头文件。

linux 下开发和编译应用程序所需要的头文件一般都存放在这里,通过头文件来使用某些库函数。默认来说这个路径被添加到了环境变量中,这样编译开发程序的时候编译器会自动搜索这个路径,从中找到你的程序中可能包含的头文件。

/usr/local

安装本地程序的一般默认路径。

当我们下载一个程序源代码,编译并且安装的时候,如果不特别指定安装的程序路径,那么默认会将程序相关的文件安装到这个目录的对应目录下。例如,安装的程序可执行文件被安装(安装实质就是复制到了 /usr/local/bin 下面,此程序可执行文件所需要依赖的库文件被安装到了/usr/local/lib目录下),被安装的软件如果是某个开发库(例如 Qt,Gtk 等)那么相应的头文件可能就被安装到了 /usr/local/include 中等等。也就是说,这个目录存放的内容,一般都是我们后来自己安装的软件的默认路径,如果择了这个默认路径作为软件的安装路径,被安装的软件的所文件都限制在这个目录中,其中的子目录就相应于根目录的子目录。

/proc

特殊文件目录。

这个目录采用一种特殊的文件系统格式(proc 格式,内核支持这种格式。其中包含了全部虚拟文件。它们并不保存在磁盘中,也不占据磁盘空间(尽管命令 ls -c 会显示它们的大小)。当您查看它们时,您实际上看到的是内存里的信息,这些文件助于我们了解系统内部信息。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
├1/ 关于进程1的信息目录。每个进程在/proc 下一个名为其进程号的目录。
├cpuinfo 处理器信息,如类型、制造商、型号和性能。
├devices 当前运行的核心配置的设备驱动的列表。
├dma 显示当前使用的DMA通道。
├filesystems 核心配置的文件系统。
├interrupts 显示使用的中断,and how many of each there have been.
├ioports 当前使用的I/O端口。
├kcore 系统物理内存映象。与物理内存大小一样,但实际不占这么多内存;
├kmsg 核心输出的消息。也被送到syslog 。
├ksyms 核心符号表。
├loadavg 系统”平均负载”;3个没意义的指示器指出系统当前的工作量。
├meminfo 存储器使用信息,包括物理内存和swap。
├modules 当前加载了哪些核心模块。
├net 网络协议状态信息。
├self 到查看/proc 的程序的进程目录的符号连接。
├stat 系统的不同状态
├uptime 系统启动的时间长度。
└version 核心版本。

/opt

可择的文件目录。

这个目录表示的是可择的意思,些自定义软件包或者第方工具,就可以安装在这里。比如在 Fedora Core 5.0 中,OpenOffice 就是安装在这里。些我们自己编译的软件包,就可以安装在这个目录中;通过源码包安装的软件,可以把它们的安装路径设置成 /opt 这样来安装。这个目录的作用一点类似 /usr/local。

/mnt

临时挂载目录。

这个目录一般是用于存放挂载储存设备的挂载目录的,比如磁盘,光驱,网络文件系统等,当我们需要挂载某个磁盘设备的时候,可以把磁盘设备挂载到这个目录上去,这样我们可以直接通过访问这个目录来访问那个磁盘了。一般来说,我们最好在 /mnt 目录下面多建立几个子目录,挂载的时候挂载到这些子目录上面,因为通常我们可能不仅仅是挂载一个设备吧。

/media

挂载的媒体设备目录。

挂载的媒体设备目录,一般外部设备挂载到这里,例如 cdrom 等。比如我们插入一个 U 盘,我们一般会发现,Linux 自动在这个目录下建立一个 disk 目录,然后把U盘挂载到这个 disk 目录上,通过访问这个 disk 来访问 U 盘。

/var

内容经常变化的目录。

此目录下文件的大小可能会改变,如缓冲文件,日志文件,缓存文件,等一般都存放在这里。

/tmp

临时文件目录。

该目录存放系统中的一些临时文件,文件可能会被系统自动清空。系统直接把 tmpfs 类型的文件系统挂载到这个目录上,tmpfs 文件系统由 Linux 内核支持,在这个文件系统中的数据,实际上是内存中的,由于内存的数据断电易失,当系统重新启动的时候我们就会发现这个目录被清空了。

/lost+found

恢复文件存放的位置。

当系统崩溃的时候,在系统修复过程中需要恢复的文件,可能就会在这里被找到了,这个目录一般为空。

另外,有些目录初学者容易混淆,这里简单区分一下:

/bin,/sbin 与 /usr/bin,/usr/sbin:

  • /bin:一般存放对于用户和系统来说“必须”的程序(二进制文件)。
  • /sbin:一般存放用于系统管理的“必需”的程序(二进制文件),一般普通用户不会使用,根用户使用。
  • /usr/bin:一般存放的只是对用户和系统来说“不是必需的”程序(二进制文件)。
  • /usr/sbin:一般存放用于系统管理的系统管理的不是必需的程序(二进制文件)。

/lib 与 /usr/lib(/lib 和 /usr/lib 的区别类似 /bin,/sbin 与 /usr/bin,/usr/sbin):

  • /lib:一般存放对于用户和系统来说“必须”的库(二进制文件)。
  • /usr/lib:一般存放的只是对用户和系统来说“不是必需的”库(二进制文件)。

虚拟机有三种网络模式,分别是 Bridged(桥接模式)、NAT(网络地址转换模式)、Host-only(主机模式)。

NAT(网络地址转换模式)

使用 NAT 模式,就是让虚拟系统借助 NAT 的功能,通过宿主机所在的网络来访问公网。在这种模式下宿主机成为双网卡主机,同时参与现有的宿主局域网和新建的虚拟局域网,但由于加设了一个虚拟的 NAT 服务器,使得虚拟局域网内的虚拟机在对外访问时,使用的则是宿主机的IP地址,这样从外部网络来看,只能看到宿主机,完全看不到新建的虚拟局域网。

这种情况下虚拟机可以上网可以 ping 通主机,但是主机 ping 不通虚拟机。

优点:利用 Virtualbox 安装一个新的虚拟系统,在虚拟系统中不用进行任何手工配置就能直接访问互联网,只要宿主机器能访问互联网即可。

Bridged(桥接模式)

在这种模式下,Virtualbox 虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器,需要手工为虚拟系统配置 IP 地址、网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信,虚拟系统和宿主机器的关系,就像连接在同一个 Hub 上的两台电脑。从网络技术上理解相当于在宿主机前端加设了一个虚拟交换机,然后宿主机和所有虚拟机共享这个交换机。

这种情况下主机和虚拟机可以互相通信,虚拟机也可以上外网。

优点:利用 Virtualbox 在局域网内新建一个虚拟服务器,为局域网用户提供网络服务。

Host-only(主机模式)

在某些特殊的网络调试环境中,要求将真实环境和虚拟环境隔离开,这时就可采用 host-only 模式,在这种模式下宿主机上的所有虚拟机是可以相互通信的,但虚拟机和真实的网络是被隔离开的。

在这种模式下新建了一个由所有虚拟机与宿主机所构成的局域网,但该局域网与宿主机本身所处的现有局域网是相互独立的,如果不做额外路由设置,这两个局域网之间不会连通,因此新建的局域网可以认为是一个单独从属于当前宿主机的私有网络,其成员为当前宿主机和相关的所有虚拟机。

从网络技术上讲相当于为宿主机增添了一个虚拟网卡,让宿主机变成一台双网卡主机(宿主网卡+虚拟网卡)。同时在宿主机后端加设一个虚拟交换机,让宿主机和所有虚拟机构成另一个虚拟的局域网。由于具备双网卡,宿主机可同时参与两个局域网(现有的宿主局域网+新建的虚拟局域网),只不过缺省情况下两个局域网不连通。

优点:利用 Virtualbox 创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作。

vagrant 中一共提供了三种网络配置。

端口映射(Forwarded port)

这种方式,就是把本机和虚拟机的端口进行映射。比如:我配置本机计算机的8080端口为虚拟机的 80 端口,这样我访问该机器的 8080 端口,vagrant 会把请求转发到虚拟机的 80 端口是那个去处理。

1
config.vm.forwarded_port 80, 8080

通过这种方式,我们可以有针对性的把虚拟机的某些端口公布到外网让其他人去访问。

端口转发隐含着一个 provider 的 NAT 网络将被首先创建。所以,如果你单独定义一条端口转发的配置语句的话,VM 将会自动建立 NAT 网络环境。

私有网络(Private network)

这种方式是只允许主机访问虚拟机。如果多个虚拟机设定在同一个网段,那么几个虚拟机之间也可以互相访问。这种方式,就好像是搭建了一个私有的 linux 集群。而且只有一个出口,那就是该主机。

1
config.vm.network "private_network", ip: "192.168.21.4"

使用这种方式,非常安全,因为只有一个出口,但是你的虚拟机只允许你自己进行操作。团队成员不能操作,那你的电脑就成服务器主机了。

值得注意的是,ip 地址“192.168.21.4”不是随便指定的。首先你可以不指定,这表示虚机启动时会 DHCP 到一个可用的 IP 地址(例如:192.168.33.101),这是 vagrant 通过 virtualbox 私有网络的 DHCP 机制获得的。如果你要自行指定明确的 IP 地址,要保证该地址是在恰当的网段中,例如 192.168.33.71。

多台虚拟机在私有网络模式下也可以互相访问,只要设置为相同的网段就可以。本质上说,这是使用 provider 的 HostOnly 模式。

公有网络(Public network)

虚拟机享受实体机器一样的待遇,一样的网络配置,vagrant1.3 版本之后也可以设定静态 IP。设定语法如下:

1
config.vm.network "public_network", ip: "192.168.1.120"

这种网络配置方式,方便团队开发,别人也可以访问你的虚拟机。当然,你和你的虚拟机必须在同一个网段中。

可以不指定ip,也可以指定 LAN 网段中的一个可用的地址,但需要注意不要和 LAN 中已有的主机或者保留的 IP 地址相冲突。

本质上说,这是使用 provider 的桥接网络模式。