2015年9月

介绍

我不会告诉你怎么在自己的电脑上去构建、安装一个定制化的 Linux 内核,这样的资料太多了,它们会对你有帮助。本文会告诉你当你在内核源码路径里敲下make 时会发生什么。

当我刚刚开始学习内核代码时,Makefile 是我打开的第一个文件,这个文件看起来真令人害怕 :)。那时候这个 Makefile 还只包含了1591 行代码,当我开始写本文时,内核已经是4.2.0的第三个候选版本 了。

这个 makefile 是 Linux 内核代码的根 makefile ,内核构建就始于此处。是的,它的内容很多,但是如果你已经读过内核源代码,你就会发现每个包含代码的目录都有一个自己的 makefile。当然了,我们不会去描述每个代码文件是怎么编译链接的,所以我们将只会挑选一些通用的例子来说明问题。而你不会在这里找到构建内核的文档、如何整洁内核代码、tags 的生成和交叉编译 相关的说明,等等。我们将从make 开始,使用标准的内核配置文件,到生成了内核镜像 bzImage 结束。

如果你已经很了解 make 工具那是最好,但是我也会描述本文出现的相关代码。

让我们开始吧!

(题图来自:adafruit.com)

编译内核前的准备

在开始编译前要进行很多准备工作。最主要的就是找到并配置好配置文件,make 命令要使用到的参数都需要从这些配置文件获取。现在就让我们深入内核的根 makefile

内核的根 Makefile 负责构建两个主要的文件:vmlinux (内核镜像可执行文件)和模块文件。内核的 Makefile 从定义如下变量开始:

VERSION = 4
PATCHLEVEL = 2
SUBLEVEL = 0
EXTRAVERSION = -rc3
NAME = Hurr durr I'ma sheep

这些变量决定了当前内核的版本,并且被使用在很多不同的地方,比如同一个 Makefile 中的 KERNELVERSION

KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)

接下来我们会看到很多ifeq 条件判断语句,它们负责检查传递给 make 的参数。内核的 Makefile 提供了一个特殊的编译选项 make help ,这个选项可以生成所有的可用目标和一些能传给 make 的有效的命令行参数。举个例子,make V=1 会在构建过程中输出详细的编译信息,第一个 ifeq 就是检查传递给 make 的 V=n 选项。

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

export quiet Q KBUILD_VERBOSE

如果 V=n 这个选项传给了 make ,系统就会给变量 KBUILD_VERBOSE 选项附上 V 的值,否则的话KBUILD_VERBOSE 就会为 0。然后系统会检查 KBUILD_VERBOSE 的值,以此来决定 quietQ 的值。符号 @ 控制命令的输出,如果它被放在一个命令之前,这条命令的输出将会是 CC scripts/mod/empty.o,而不是Compiling .... scripts/mod/empty.o(LCTT 译注:CC 在 makefile 中一般都是编译命令)。在这段最后,系统导出了所有的变量。

下一个 ifeq 语句检查的是传递给 make 的选项 O=/dir,这个选项允许在指定的目录 dir 输出所有的结果文件:

ifeq ($(KBUILD_SRC),)

ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

ifneq ($(KBUILD_OUTPUT),)
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
                                && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))

sub-make: FORCE
    $(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
    -f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))

skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)

系统会检查变量 KBUILD_SRC,它代表内核代码的顶层目录,如果它是空的(第一次执行 makefile 时总是空的),我们会设置变量 KBUILD_OUTPUT 为传递给选项 O 的值(如果这个选项被传进来了)。下一步会检查变量 KBUILD_OUTPUT ,如果已经设置好,那么接下来会做以下几件事:

  • 将变量 KBUILD_OUTPUT 的值保存到临时变量 saved-output
  • 尝试创建给定的输出目录;
  • 检查创建的输出目录,如果失败了就打印错误;
  • 如果成功创建了输出目录,那么就在新目录重新执行 make 命令(参见选项-C)。

下一个 ifeq 语句会检查传递给 make 的选项 CM

ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

第一个选项 C 会告诉 makefile 需要使用环境变量 $CHECK 提供的工具来检查全部 c 代码,默认情况下会使用sparse。第二个选项 M 会用来编译外部模块(本文不做讨论)。

系统还会检查变量 KBUILD_SRC,如果 KBUILD_SRC 没有被设置,系统会设置变量 srctree.

ifeq ($(KBUILD_SRC),)
        srctree := .
endif

objtree := .
src     := $(srctree)
obj     := $(objtree)

export srctree objtree VPATH

这将会告诉 Makefile 内核的源码树就在执行 make 命令的目录,然后要设置 objtree 和其他变量为这个目录,并且将这些变量导出。接着就是要获取 SUBARCH 的值,这个变量代表了当前的系统架构(LCTT 译注:一般都指CPU 架构):

SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
                  -e s/sun4u/sparc64/ \
                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                  -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )

如你所见,系统执行 uname 得到机器、操作系统和架构的信息。因为我们得到的是 uname 的输出,所以我们需要做一些处理再赋给变量 SUBARCH 。获得 SUBARCH 之后就要设置SRCARCHhfr-archSRCARCH 提供了硬件架构相关代码的目录,hfr-arch 提供了相关头文件的目录:

ifeq ($(ARCH),i386)
        SRCARCH := x86
endif
ifeq ($(ARCH),x86_64)
        SRCARCH := x86
endif

hdr-arch  := $(SRCARCH)

注意:ARCHSUBARCH 的别名。如果没有设置过代表内核配置文件路径的变量 KCONFIG_CONFIG,下一步系统会设置它,默认情况下就是 .config

KCONFIG_CONFIG  ?= .config
export KCONFIG_CONFIG

以及编译内核过程中要用到的 shell

CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
      else if [ -x /bin/bash ]; then echo /bin/bash; \
      else echo sh; fi ; fi)

接下来就要设置一组和编译内核的编译器相关的变量。我们会设置主机的 CC++ 的编译器及相关配置项:

HOSTCC       = gcc
HOSTCXX      = g++
HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89
HOSTCXXFLAGS = -O2

接下来会去适配代表编译器的变量 CC,那为什么还要 HOST* 这些变量呢?这是因为 CC 是编译内核过程中要使用的目标架构的编译器,但是 HOSTCC 是要被用来编译一组 host 程序的(下面我们就会看到)。

然后我们就看到变量 KBUILD_MODULESKBUILD_BUILTIN 的定义,这两个变量决定了我们要编译什么东西(内核、模块或者两者):

KBUILD_MODULES :=
KBUILD_BUILTIN := 1

ifeq ($(MAKECMDGOALS),modules)
  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
endif

在这我们可以看到这些变量的定义,并且,如果们仅仅传递了 modulesmake,变量 KBUILD_BUILTIN 会依赖于内核配置选项 CONFIG_MODVERSIONS

下一步操作是引入下面的文件:

include scripts/Kbuild.include

文件 Kbuild 或者又叫做 Kernel Build System 是一个用来管理构建内核及其模块的特殊框架。kbuild 文件的语法与 makefile 一样。文件scripts/Kbuild.includekbuild 系统提供了一些常规的定义。因为我们包含了这个 kbuild 文件,我们可以看到和不同工具关联的这些变量的定义,这些工具会在内核和模块编译过程中被使用(比如链接器、编译器、来自 binutils 的二进制工具包 ,等等):

AS      = $(CROSS_COMPILE)as
LD      = $(CROSS_COMPILE)ld
CC      = $(CROSS_COMPILE)gcc
CPP     = $(CC) -E
AR      = $(CROSS_COMPILE)ar
NM      = $(CROSS_COMPILE)nm
STRIP       = $(CROSS_COMPILE)strip
OBJCOPY     = $(CROSS_COMPILE)objcopy
OBJDUMP     = $(CROSS_COMPILE)objdump
AWK     = awk
...
...
...

在这些定义好的变量后面,我们又定义了两个变量:USERINCLUDELINUXINCLUDE。他们包含了头文件的路径(第一个是给用户用的,第二个是给内核用的):

USERINCLUDE    := \
        -I$(srctree)/arch/$(hdr-arch)/include/uapi \
        -Iarch/$(hdr-arch)/include/generated/uapi \
        -I$(srctree)/include/uapi \
        -Iinclude/generated/uapi \
        -include $(srctree)/include/linux/kconfig.h

LINUXINCLUDE    := \
        -I$(srctree)/arch/$(hdr-arch)/include \
        ...

以及给 C 编译器的标准标志:

KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
           -fno-strict-aliasing -fno-common \
           -Werror-implicit-function-declaration \
           -Wno-format-security \
           -std=gnu89

这并不是最终确定的编译器标志,它们还可以在其他 makefile 里面更新(比如 arch/ 里面的 kbuild)。变量定义完之后,全部会被导出供其他 makefile 使用。

下面的两个变量 RCS_FIND_IGNORERCS_TAR_IGNORE 包含了被版本控制系统忽略的文件:

export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o    \
              -name CVS -o -name .pc -o -name .hg -o -name .git \) \
              -prune -o
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
             --exclude CVS --exclude .pc --exclude .hg --exclude .git

这就是全部了,我们已经完成了所有的准备工作,下一个点就是如果构建vmlinux

直面内核构建

现在我们已经完成了所有的准备工作,根 makefile(注:内核根目录下的 makefile)的下一步工作就是和编译内核相关的了。在这之前,我们不会在终端看到 make 命令输出的任何东西。但是现在编译的第一步开始了,这里我们需要从内核根 makefile 的 598 行开始,这里可以看到目标vmlinux

all: vmlinux
    include arch/$(SRCARCH)/Makefile

不要操心我们略过的从 export RCS_FIND_IGNORE.....all: vmlinux..... 这一部分 makefile 代码,他们只是负责根据各种配置文件(make *.config)生成不同目标内核的,因为之前我就说了这一部分我们只讨论构建内核的通用途径。

目标 all: 是在命令行如果不指定具体目标时默认使用的目标。你可以看到这里包含了架构相关的 makefile(在这里就指的是 arch/x86/Makefile)。从这一时刻起,我们会从这个 makefile 继续进行下去。如我们所见,目标 all 依赖于根 makefile 后面声明的 vmlinux

vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE

vmlinux 是 linux 内核的静态链接可执行文件格式。脚本 scripts/link-vmlinux.sh 把不同的编译好的子模块链接到一起形成了 vmlinux。

第二个目标是 vmlinux-deps,它的定义如下:

vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)

它是由内核代码下的每个顶级目录的 built-in.o 组成的。之后我们还会检查内核所有的目录,kbuild 会编译各个目录下所有的对应 $(obj-y) 的源文件。接着调用 $(LD) -r 把这些文件合并到一个 build-in.o 文件里。此时我们还没有vmlinux-deps,所以目标 vmlinux 现在还不会被构建。对我而言 vmlinux-deps 包含下面的文件:

arch/x86/kernel/vmlinux.lds arch/x86/kernel/head_64.o
arch/x86/kernel/head64.o    arch/x86/kernel/head.o
init/built-in.o             usr/built-in.o
arch/x86/built-in.o         kernel/built-in.o
mm/built-in.o               fs/built-in.o
ipc/built-in.o              security/built-in.o
crypto/built-in.o           block/built-in.o
lib/lib.a                   arch/x86/lib/lib.a
lib/built-in.o              arch/x86/lib/built-in.o
drivers/built-in.o          sound/built-in.o
firmware/built-in.o         arch/x86/pci/built-in.o
arch/x86/power/built-in.o   arch/x86/video/built-in.o
net/built-in.o

下一个可以被执行的目标如下:

$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
$(vmlinux-dirs): prepare scripts
    $(Q)$(MAKE) $(build)=$@

就像我们看到的,vmlinux-dir 依赖于两部分:preparescripts。第一个 prepare 定义在内核的根 makefile 中,准备工作分成三个阶段:

prepare: prepare0
prepare0: archprepare FORCE
    $(Q)$(MAKE) $(build)=.
archprepare: archheaders archscripts prepare1 scripts_basic

prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
                   include/config/auto.conf
    $(cmd_crmodverdir)
prepare2: prepare3 outputmakefile asm-generic

第一个 prepare0 展开到 archprepare ,后者又展开到 archheaderarchscripts,这两个变量定义在 x86_64 相关的 Makefile。让我们看看这个文件。x86_64 特定的 makefile 从变量定义开始,这些变量都是和特定架构的配置文件 (defconfig,等等)有关联。在定义了编译 16-bit 代码的编译选项之后,根据变量 BITS 的值,如果是 32, 汇编代码、链接器、以及其它很多东西(全部的定义都可以在arch/x86/Makefile找到)对应的参数就是 i386,而 64 就对应的是 x86_84

第一个目标是 makefile 生成的系统调用列表(syscall table)中的 archheaders

archheaders:
    $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all

第二个目标是 makefile 里的 archscripts

archscripts: scripts_basic
    $(Q)$(MAKE) $(build)=arch/x86/tools relocs

我们可以看到 archscripts 是依赖于根 Makefile里的scripts_basic 。首先我们可以看出 scripts_basic 是按照 scripts/basic 的 makefile 执行 make 的:

scripts_basic:
    $(Q)$(MAKE) $(build)=scripts/basic

scripts/basic/Makefile 包含了编译两个主机程序 fixdepbin2 的目标:

hostprogs-y := fixdep
hostprogs-$(CONFIG_BUILD_BIN2C)     += bin2c
always      := $(hostprogs-y)

$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep

第一个工具是 fixdep:用来优化 gcc 生成的依赖列表,然后在重新编译源文件的时候告诉make。第二个工具是 bin2c,它依赖于内核配置选项 CONFIG_BUILD_BIN2C,并且它是一个用来将标准输入接口(LCTT 译注:即 stdin)收到的二进制流通过标准输出接口(即:stdout)转换成 C 头文件的非常小的 C 程序。你可能注意到这里有些奇怪的标志,如 hostprogs-y 等。这个标志用于所有的 kbuild 文件,更多的信息你可以从documentation 获得。在我们这里, hostprogs-y 告诉 kbuild 这里有个名为 fixed 的程序,这个程序会通过和 Makefile 相同目录的 fixdep.c 编译而来。

执行 make 之后,终端的第一个输出就是 kbuild 的结果:

$ make
  HOSTCC  scripts/basic/fixdep

当目标 script_basic 被执行,目标 archscripts 就会 make arch/x86/tools 下的 makefile 和目标 relocs:

$(Q)$(MAKE) $(build)=arch/x86/tools relocs

包含了重定位 的信息的代码 relocs_32.crelocs_64.c 将会被编译,这可以在make 的输出中看到:

  HOSTCC  arch/x86/tools/relocs_32.o
  HOSTCC  arch/x86/tools/relocs_64.o
  HOSTCC  arch/x86/tools/relocs_common.o
  HOSTLD  arch/x86/tools/relocs

在编译完 relocs.c 之后会检查 version.h:

$(version_h): $(srctree)/Makefile FORCE
    $(call filechk,version.h)
    $(Q)rm -f $(old_version_h)

我们可以在输出看到它:

CHK     include/config/kernel.release

以及在内核的根 Makefiel 使用 arch/x86/include/generated/asm 的目标 asm-generic 来构建 generic 汇编头文件。在目标 asm-generic 之后,archprepare 就完成了,所以目标 prepare0 会接着被执行,如我上面所写:

prepare0: archprepare FORCE
    $(Q)$(MAKE) $(build)=.

注意 build,它是定义在文件 scripts/Kbuild.include,内容是这样的:

build := -f $(srctree)/scripts/Makefile.build obj

或者在我们的例子中,它就是当前源码目录路径:.

$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=.

脚本 scripts/Makefile.build 通过参数 obj 给定的目录找到 Kbuild 文件,然后引入 kbuild 文件:

include $(kbuild-file)

并根据这个构建目标。我们这里 . 包含了生成 kernel/bounds.sarch/x86/kernel/asm-offsets.sKbuild 文件。在此之后,目标 prepare 就完成了它的工作。 vmlinux-dirs 也依赖于第二个目标 scripts ,它会编译接下来的几个程序:filealiasmk_elfconfigmodpost 等等。之后,scripts/host-programs 就可以开始编译我们的目标 vmlinux-dirs 了。

首先,我们先来理解一下 vmlinux-dirs 都包含了那些东西。在我们的例子中它包含了下列内核目录的路径:

init usr arch/x86 kernel mm fs ipc security crypto block
drivers sound firmware arch/x86/pci arch/x86/power
arch/x86/video net lib arch/x86/lib

我们可以在内核的根 Makefile 里找到 vmlinux-dirs 的定义:

vmlinux-dirs    := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
             $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
             $(net-y) $(net-m) $(libs-y) $(libs-m)))

init-y      := init/
drivers-y   := drivers/ sound/ firmware/
net-y       := net/
libs-y      := lib/
...
...
...

这里我们借助函数 patsubstfilter去掉了每个目录路径里的符号 /,并且把结果放到 vmlinux-dirs 里。所以我们就有了 vmlinux-dirs 里的目录列表,以及下面的代码:

$(vmlinux-dirs): prepare scripts
    $(Q)$(MAKE) $(build)=$@

符号 $@ 在这里代表了 vmlinux-dirs,这就表明程序会递归遍历从 vmlinux-dirs 以及它内部的全部目录(依赖于配置),并且在对应的目录下执行 make 命令。我们可以在输出看到结果:

  CC      init/main.o
  CHK     include/generated/compile.h
  CC      init/version.o
  CC      init/do_mounts.o
  ...
  CC      arch/x86/crypto/glue_helper.o
  AS      arch/x86/crypto/aes-x86_64-asm_64.o
  CC      arch/x86/crypto/aes_glue.o
  ...
  AS      arch/x86/entry/entry_64.o
  AS      arch/x86/entry/thunk_64.o
  CC      arch/x86/entry/syscall_64.o

每个目录下的源代码将会被编译并且链接到 built-io.o 里:

$ find . -name built-in.o
./arch/x86/crypto/built-in.o
./arch/x86/crypto/sha-mb/built-in.o
./arch/x86/net/built-in.o
./init/built-in.o
./usr/built-in.o
...
...

好了,所有的 built-in.o 都构建完了,现在我们回到目标 vmlinux 上。你应该还记得,目标 vmlinux 是在内核的根makefile 里。在链接 vmlinux 之前,系统会构建 samples, Documentation 等等,但是如上文所述,我不会在本文描述这些。

vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
    ...
    ...
    +$(call if_changed,link-vmlinux)

你可以看到,调用脚本 scripts/link-vmlinux.sh 的主要目的是把所有的 built-in.o 链接成一个静态可执行文件,和生成 System.map。 最后我们来看看下面的输出:

  LINK    vmlinux
  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  KSYM    .tmp_kallsyms1.o
  KSYM    .tmp_kallsyms2.o
  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map

vmlinuxSystem.map 生成在内核源码树根目录下。

$ ls vmlinux System.map 
System.map  vmlinux

这就是全部了,vmlinux 构建好了,下一步就是创建 bzImage.

制作bzImage

bzImage 就是压缩了的 linux 内核镜像。我们可以在构建了 vmlinux 之后通过执行 make bzImage 获得bzImage。同时我们可以仅仅执行 make 而不带任何参数也可以生成 bzImage ,因为它是在 arch/x86/kernel/Makefile 里预定义的、默认生成的镜像:

all: bzImage

让我们看看这个目标,它能帮助我们理解这个镜像是怎么构建的。我已经说过了 bzImage 是被定义在 arch/x86/kernel/Makefile,定义如下:

bzImage: vmlinux
    $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
    $(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
    $(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@

在这里我们可以看到第一次为 boot 目录执行 make,在我们的例子里是这样的:

boot := arch/x86/boot

现在的主要目标是编译目录 arch/x86/bootarch/x86/boot/compressed 的代码,构建 setup.binvmlinux.bin,最后用这两个文件生成 bzImage。第一个目标是定义在 arch/x86/boot/Makefile$(obj)/setup.elf:

$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
    $(call if_changed,ld)

我们已经在目录 arch/x86/boot 有了链接脚本 setup.ld,和扩展到 boot 目录下全部源代码的变量 SETUP_OBJS 。我们可以看看第一个输出:

  AS      arch/x86/boot/bioscall.o
  CC      arch/x86/boot/cmdline.o
  AS      arch/x86/boot/copy.o
  HOSTCC  arch/x86/boot/mkcpustr
  CPUSTR  arch/x86/boot/cpustr.h
  CC      arch/x86/boot/cpu.o
  CC      arch/x86/boot/cpuflags.o
  CC      arch/x86/boot/cpucheck.o
  CC      arch/x86/boot/early_serial_console.o
  CC      arch/x86/boot/edd.o

下一个源码文件是 arch/x86/boot/header.S,但是我们不能现在就编译它,因为这个目标依赖于下面两个头文件:

$(obj)/header.o: $(obj)/voffset.h $(obj)/zoffset.h

第一个头文件 voffset.h 是使用 sed 脚本生成的,包含用 nm 工具从 vmlinux 获取的两个地址:

#define VO__end 0xffffffff82ab0000
#define VO__text 0xffffffff81000000

这两个地址是内核的起始和结束地址。第二个头文件 zoffset.harch/x86/boot/compressed/Makefile 可以看出是依赖于目标 vmlinux的:

$(obj)/zoffset.h: $(obj)/compressed/vmlinux FORCE
    $(call if_changed,zoffset)

目标 $(obj)/compressed/vmlinux 依赖于 vmlinux-objs-y —— 说明需要编译目录 arch/x86/boot/compressed 下的源代码,然后生成 vmlinux.binvmlinux.bin.bz2,和编译工具 mkpiggy。我们可以在下面的输出看出来:

  LDS     arch/x86/boot/compressed/vmlinux.lds
  AS      arch/x86/boot/compressed/head_64.o
  CC      arch/x86/boot/compressed/misc.o
  CC      arch/x86/boot/compressed/string.o
  CC      arch/x86/boot/compressed/cmdline.o
  OBJCOPY arch/x86/boot/compressed/vmlinux.bin
  BZIP2   arch/x86/boot/compressed/vmlinux.bin.bz2
  HOSTCC  arch/x86/boot/compressed/mkpiggy

vmlinux.bin 是去掉了调试信息和注释的 vmlinux 二进制文件,加上了占用了 u32 (LCTT 译注:即4-Byte)的长度信息的 vmlinux.bin.all 压缩后就是 vmlinux.bin.bz2。其中 vmlinux.bin.all 包含了 vmlinux.binvmlinux.relocs(LCTT 译注:vmlinux 的重定位信息),其中 vmlinux.relocsvmlinux 经过程序 relocs 处理之后的 vmlinux 镜像(见上文所述)。我们现在已经获取到了这些文件,汇编文件 piggy.S 将会被 mkpiggy 生成、然后编译:

  MKPIGGY arch/x86/boot/compressed/piggy.S
  AS      arch/x86/boot/compressed/piggy.o

这个汇编文件会包含经过计算得来的、压缩内核的偏移信息。处理完这个汇编文件,我们就可以看到 zoffset 生成了:

  ZOFFSET arch/x86/boot/zoffset.h

现在 zoffset.hvoffset.h 已经生成了,arch/x86/boot 里的源文件可以继续编译:

  AS      arch/x86/boot/header.o
  CC      arch/x86/boot/main.o
  CC      arch/x86/boot/mca.o
  CC      arch/x86/boot/memory.o
  CC      arch/x86/boot/pm.o
  AS      arch/x86/boot/pmjump.o
  CC      arch/x86/boot/printf.o
  CC      arch/x86/boot/regs.o
  CC      arch/x86/boot/string.o
  CC      arch/x86/boot/tty.o
  CC      arch/x86/boot/video.o
  CC      arch/x86/boot/video-mode.o
  CC      arch/x86/boot/video-vga.o
  CC      arch/x86/boot/video-vesa.o
  CC      arch/x86/boot/video-bios.o

所有的源代码会被编译,他们最终会被链接到 setup.elf

  LD      arch/x86/boot/setup.elf

或者:

ld -m elf_x86_64   -T arch/x86/boot/setup.ld arch/x86/boot/a20.o arch/x86/boot/bioscall.o arch/x86/boot/cmdline.o arch/x86/boot/copy.o arch/x86/boot/cpu.o arch/x86/boot/cpuflags.o arch/x86/boot/cpucheck.o arch/x86/boot/early_serial_console.o arch/x86/boot/edd.o arch/x86/boot/header.o arch/x86/boot/main.o arch/x86/boot/mca.o arch/x86/boot/memory.o arch/x86/boot/pm.o arch/x86/boot/pmjump.o arch/x86/boot/printf.o arch/x86/boot/regs.o arch/x86/boot/string.o arch/x86/boot/tty.o arch/x86/boot/video.o arch/x86/boot/video-mode.o arch/x86/boot/version.o arch/x86/boot/video-vga.o arch/x86/boot/video-vesa.o arch/x86/boot/video-bios.o -o arch/x86/boot/setup.elf

最后的两件事是创建包含目录 arch/x86/boot/* 下的编译过的代码的 setup.bin

objcopy  -O binary arch/x86/boot/setup.elf arch/x86/boot/setup.bin

以及从 vmlinux 生成 vmlinux.bin :

objcopy  -O binary -R .note -R .comment -S arch/x86/boot/compressed/vmlinux arch/x86/boot/vmlinux.bin

最最后,我们编译主机程序 arch/x86/boot/tools/build.c,它将会用来把 setup.binvmlinux.bin 打包成 bzImage:

arch/x86/boot/tools/build arch/x86/boot/setup.bin arch/x86/boot/vmlinux.bin arch/x86/boot/zoffset.h arch/x86/boot/bzImage

实际上 bzImage 就是把 setup.binvmlinux.bin 连接到一起。最终我们会看到输出结果,就和那些用源码编译过内核的同行的结果一样:

Setup is 16268 bytes (padded to 16384 bytes).
System is 4704 kB
CRC 94a88f9a
Kernel: arch/x86/boot/bzImage is ready  (#5)

全部结束。

结论

这就是本文的结尾部分。本文我们了解了编译内核的全部步骤:从执行 make 命令开始,到最后生成 bzImage。我知道,linux 内核的 makefile 和构建 linux 的过程第一眼看起来可能比较迷惑,但是这并不是很难。希望本文可以帮助你理解构建 linux 内核的整个流程。

链接


via: https://github.com/0xAX/linux-insides/blob/master/Misc/how_kernel_compiled.md

译者:oska874 校对:wxy

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

问题: 当我试图在 Ubuntu 上的 Wireshark 中打开一个 pre-recorded 数据包转储时,它的界面突然死机,在我运行 Wireshark 的终端出现了下面的错误和警告。我该如何解决这个问题?
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GObject'
(wireshark:3480): GLib-GObject-CRITICAL **: g_object_set_qdata_full: assertion 'G_IS_OBJECT (object)' failed
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GtkRange'
(wireshark:3480): Gtk-CRITICAL **: gtk_range_get_adjustment: assertion 'GTK_IS_RANGE (range)' failed
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GtkOrientable'
(wireshark:3480): Gtk-CRITICAL **: gtk_orientable_get_orientation: assertion 'GTK_IS_ORIENTABLE (orientable)' failed
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GtkScrollbar'
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GtkWidget'
(wireshark:3480): GLib-GObject-WARNING **: invalid unclassed pointer in cast to 'GObject'
(wireshark:3480): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed
(wireshark:3480): Gtk-CRITICAL **: gtk_widget_set_name: assertion 'GTK_IS_WIDGET (widget)' failed

Wireshark 是一个基于 GUI 的数据包捕获和嗅探工具。该工具被网络管理员普遍使用,网络安全工程师或开发人员对于各种任务的数据包级的网络分析是必需的,例如在网络故障,漏洞测试,应用程序调试,或逆向协议工程是必需的。 Wireshark 允许实时记录数据包,并通过便捷的图形用户界面浏览他们的协议首部和有效负荷。

这是 Wireshark 的 UI,尤其是在 Ubuntu 桌面下运行时,当你向上或向下滚动分组列表视图时,或开始加载一个 pre-recorded 包转储文件时,有时会挂起或冻结,并出现以下错误。

显然,这个错误是由 Wireshark 和叠加滚动条之间的一些不兼容造成的,在最新的 Ubuntu 桌面还没有被解决(例如,Ubuntu 15.04 的桌面)。

一种避免 Wireshark 的 UI 卡死的办法就是 暂时禁用叠加滚动条。在 Wireshark 上有两种方法来禁用叠加滚动条,这取决于你在桌面上如何启动 Wireshark 的。

命令行解决方法

叠加滚动条可以通过设置"LIBOVERLAY\_SCROLLBAR"环境变量为“0”来被禁止。

所以,如果你是在终端使用命令行启动 Wireshark 的,你可以在 Wireshark 中禁用叠加滚动条,如下所示。

打开你的 .bashrc 文件,并定义以下 alias。

alias wireshark="LIBOVERLAY_SCROLLBAR=0 /usr/bin/wireshark"

桌面启动解决方法

如果你是使用桌面启动器启动的 Wireshark,你可以编辑它的桌面启动器文件。

$ sudo vi /usr/share/applications/wireshark.desktop

查找以"Exec"开头的行,并如下更改。

Exec=env LIBOVERLAY_SCROLLBAR=0 wireshark %f

虽然这种解决方法可以在系统级帮助到所有桌面用户,但升级 Wireshark 后被覆盖就没用了。如果你想保留修改的 .desktop 文件,如下所示将它复制到你的主目录。

$ cp /usr/share/applications/wireshark.desktop ~/.local/share/applications/ 

via: http://ask.xmodulo.com/fix-wireshark-gui-freeze-linux-desktop.html

作者:Dan Nanni 译者:strugglingyouth 校对:wxy

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

这个有 5 年历史,由 Kent Oberstreet 创建,过去属于谷歌的文件系统,最近完成了全部关键组件。Bcachefs 文件系统自称其性能和稳定性与 ext4 和 xfs 相同,而其他方面的功能又可以与 btrfs 和 zfs 相媲美。主要特性包括校验、压缩、多设备支持、缓存、快照与其他“漂亮”的特性。

Bcachefs 来自 bcache,这是一个块级缓存层。从 bcache 到一个功能完整的写时复制文件系统,堪称是一项质的转变。

对自己的问题“为什么要出一个新的文件系统”中,Kent Oberstreet 自问自答道:当我还在谷歌的时候,我与其他在 bcache 上工作的同事在偶然的情况下意识到我们正在使用的东西可以成为一个成熟文件系统的功能块,我们可以用 bcache 创建一个拥有干净而优雅设计的文件系统,而最重要的一点是,bcachefs 的主要目的就是在性能和稳定性上能与 ext4 和 xfs 匹敌,同时拥有 btrfs 和 zfs 的特性。

Overstreet 邀请人们在自己的系统上测试 bcachefs,可以通过邮件列表[通告]获取 bcachefs 的操作指南。

Linux 生态系统中文件系统几乎处于一家独大状态,Fedora 在第 16 版的时候就想用 btrfs 换掉 ext4 作为其默认文件系统,但是到现在(LCTT:都出到 Fedora 22 了)还在使用 ext4。而几乎所有 Debian 系的发行版(Ubuntu、Mint、elementary OS 等)也使用 ext4 作为默认文件系统,并且这些主流的发行版都没有替换默认文件系统的意思。


via: http://www.linuxveda.com/2015/08/22/linux-gain-new-file-system-bcachefs/

作者:Paul Hill 译者:bazz2 校对:wxy

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

和管理其它Linux服务器一样,管理一个 RHEL 7 服务器要求你能够添加、修改、暂停或删除用户帐户,并且授予他们执行其分配的任务所需的文件、目录、其它系统资源所必要的权限。

User and Group Management in Linux

RHCSA: 用户和组管理 – Part 3

管理用户帐户

如果想要给RHEL 7 服务器添加账户,你需要以root用户执行如下两条命令之一:

# adduser [new_account]
# useradd [new_account]

当添加新的用户帐户时,默认会执行下列操作。

  • 它/她的主目录就会被创建(一般是"/home/用户名",除非你特别设置)
  • 一些隐藏文件 如.bash_logout, .bash_profile 以及 .bashrc 会被复制到用户的主目录,它们会为用户的回话提供环境变量。你可以进一步查看它们的相关细节。
  • 会为您的账号添加一个邮件池目录。
  • 会创建一个和用户名同样的组(LCTT 译注:除非你给新创建的用户指定了组)。

用户帐户的全部信息被保存在/etc/passwd文件。这个文件以如下格式保存了每一个系统帐户的所有信息(字段以“:”分割)

[username]:[x]:[UID]:[GID]:[Comment]:[Home directory]:[Default shell]
  • [username][Comment] 其意自明,就是用户名和备注
  • 第二个‘x’表示帐户的启用了密码保护(记录在/etc/shadow文件),密码用于登录[username]
  • [UID][GID]是整数,它们表明了[username]的用户ID 和所属的主组ID

最后。

  • [Home directory]显示[username]的主目录的绝对路径
  • [Default shell] 是当用户登录系统后使用的默认shell

另外一个你必须要熟悉的重要的文件是存储组信息的/etc/group。和/etc/passwd类似,也是每行一个记录,字段由“:”分割

[Group name]:[Group password]:[GID]:[Group members]
  • [Group name] 是组名
  • 这个组是否使用了密码 (如果是"x"意味着没有)
  • [GID]: 和/etc/passwd中一样
  • [Group members]:用户列表,使用“,”隔开。里面包含组内的所有用户

添加过帐户后,任何时候你都可以通过 usermod 命令来修改用户账户信息,基本的语法如下:

# usermod [options] [username]

相关阅读

示例1 : 设置帐户的过期时间

如果你的公司有一些短期使用的帐户或者你要在有限时间内授予访问,你可以使用 --expiredate 参数 ,后加YYYY-MM-DD 格式的日期。为了查看是否生效,你可以使用如下命令查看

# chage -l [username]

帐户更新前后的变动如下图所示

Change User Account Information

修改用户信息

示例 2: 向组内追加用户

除了创建用户时的主用户组,一个用户还能被添加到别的组。你需要使用 -aG或 -append -group 选项,后跟逗号分隔的组名。

示例 3: 修改用户主目录或默认Shell

如果因为一些原因,你需要修改默认的用户主目录(一般为 /home/用户名),你需要使用 -d 或 -home 参数,后跟绝对路径来修改主目录。

如果有用户想要使用其它的shell来取代默认的bash(比如zsh)。使用 usermod ,并使用 -shell 的参数,后加新的shell的路径。

示例 4: 展示组内的用户

当把用户添加到组中后,你可以使用如下命令验证属于哪一个组

# groups [username]
# id [username]

下面图片的演示了示例2到示例4

Adding User to Supplementary Group

添加用户到额外的组

在上面的示例中:

# usermod --append --groups gacanepa,users --home /tmp --shell /bin/sh tecmint

如果想要从组内删除用户,取消 --append 选项,并使用 --groups 和你要用户属于的组的列表。

示例 5: 通过锁定密码来停用帐户

如果想要关闭帐户,你可以使用 -l(小写的L)或 -lock 选项来锁定用户的密码。这将会阻止用户登录。

示例 6: 解锁密码

当你想要重新启用帐户让它可以继续登录时,使用 -u 或 –unlock 选项来解锁用户的密码,就像示例5 介绍的那样

# usermod --unlock tecmint

下面的图片展示了示例5和示例6:

Lock Unlock User Account

锁定上锁用户

示例 7:删除组和用户

如果要删除一个组,你需要使用 groupdel ,如果需要删除用户 你需要使用 userdel (添加 -r 可以删除主目录和邮件池的内容)。

# groupdel [group_name]        # 删除组
# userdel -r [user_name]       # 删除用户,并删除主目录和邮件池

如果一些文件属于该组,删除组时它们不会也被删除。但是组拥有者的名字将会被设置为删除掉的组的GID。

列举,设置,并且修改标准 ugo/rwx 权限

著名的 ls 命令 是管理员最好的助手. 当我们使用 -l 参数, 这个工具允许您以长格式(或详细格式)查看一个目录中的内容。

而且,该命令还可以用于单个文件中。无论哪种方式,在“ls”输出中的前10个字符表示每个文件的属性。

这10个字符序列的第一个字符用于表示文件类型:

  • – (连字符): 一个标准文件
  • d: 一个目录
  • l: 一个符号链接
  • c: 字符设备(将数据作为字节流,例如终端)
  • b: 块设备(以块的方式处理数据,例如存储设备)

文件属性的接下来的九个字符,分为三个组,被称为文件模式,并注明读(r)、写(w)、和执行(x)权限授予文件的所有者、文件的所有组、和其它的用户(通常被称为“世界”)。

同文件上的读取权限允许文件被打开和读取一样,如果目录同时有执行权限时,就允许其目录内容被列出。此外,如果一个文件有执行权限,就允许它作为一个程序运行。

文件权限是通过chmod命令改变的,它的基本语法如下:

# chmod [new_mode] file

new\_mode 是一个八进制数或表达式,用于指定新的权限。随意试试各种权限看看是什么效果。或者您已经有了一个更好的方式来设置文件的权限,你也可以用你自己的方式自由地试试。

八进制数可以基于二进制等价计算,可以从所需的文件权限的文件的所有者、所有组、和世界组合成。每种权限都等于2的幂(R = 2^2,W = 2^1,x = 2^0),没有时即为0。例如:

File Permissions

文件权限

在八进制形式下设置文件的权限,如上图所示

# chmod 744 myfile

请用马上来对比一下我们以前的计算,在更改文件的权限后,我们的实际输出为:

Long List Format

长列表格式

示例 8: 寻找777权限的文件

出于安全考虑,你应该确保在正常情况下,尽可能避免777权限(任何人可读、可写、可执行的文件)。虽然我们会在以后的教程中教你如何更有效地找到您的系统的具有特定权限的全部文件,你现在仍可以组合使用ls 和 grep来获取这种信息。

在下面的例子,我们会寻找 /etc 目录下的777权限文件。注意,我们要使用第二章:文件和目录管理中讲到的管道的知识:

# ls -l /etc | grep rwxrwxrwx

Find All Files with 777 Permission

查找所有777权限的文件

示例 9: 为所有用户指定特定权限

shell脚本,以及一些二进制文件,所有用户都应该有权访问(不只是其相应的所有者和组),应该有相应的执行权限(我们会讨论特殊情况下的问题):

# chmod a+x script.sh

注意: 我们可以使用表达式设置文件模式,表示用户权限的字母如“u”,组所有者权限的字母“g”,其余的为“o” ,同时具有所有权限为“a”。权限可以通过+- 来授予和收回。

Set Execute Permission on File

为文件设置执行权限

长目录列表还用两列显示了该文件的所有者和所有组。此功能可作为系统中文件的第一级访问控制方法:

Check File Owner and Group

检查文件的所有者和所有组

改变文件的所有者,您应该使用chown命令。请注意,您可以在同时或分别更改文件的所有组:

# chown user:group file

你可以更改用户或组,或在同时更改两个属性,但是不要忘记冒号区分,如果你想要更新其它属性,让另外的部分为空:

# chown :group file              # 仅改变所有组
# chown user: file               # 仅改变所有者

示例 10:从一个文件复制权限到另一个文件

如果你想“克隆”一个文件的所有权到另一个,你可以这样做,使用–reference参数,如下:

# chown --reference=ref_file file

ref\_file的所有信息会复制给 file

Clone File Ownership

复制文件属主信息

设置 SETGID 协作目录

假如你需要授予在一个特定的目录中拥有访问所有的文件的权限给一个特定的用户组,你有可能需要使用给目录设置setgid的方法。当setgid设置后,该真实用户的有效GID会变成属主的GID。

因此,任何访问该文件的用户会被授予该文件的属组的权限。此外,当setgid设置在一个目录中,新创建的文件继承组该目录的组,而且新创建的子目录也将继承父目录的setgid权限。

# chmod g+s [filename]

要以八进制形式设置 setgid,需要在基本权限前缀以2。

# chmod 2755 [directory]

总结

扎实的用户和组管理知识,以及标准和特殊的 Linux权限管理,通过实践,可以帮你快速解决 RHEL 7 服务器的文件权限问题。

我向你保证,当你按照本文所概述的步骤和使用系统文档(在本系列的第一章 回顾基础命令及系统文档中讲到), 你将掌握基本的系统管理的能力。

请随时使用下面的评论框让我们知道你是否有任何问题或意见。


via: http://www.tecmint.com/rhcsa-exam-manage-users-and-groups/

作者:Gabriel Cánepa 译者:xiqingongzi 校对:wxy

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

iTOP是一个简单的基于Web的开源IT服务管理工具。它有所有的ITIL功能,包括服务台、配置管理、事件管理、问题管理、变更管理和服务管理。iTOP依赖于Apache/IIS、MySQL和PHP,因此它可以运行在任何支持这些软件的操作系统中。因为iTOP是一个Web程序,因此你不必在用户的PC端任何客户端程序。一个简单的浏览器就足够每天的IT环境操作了。

我们要在一台有满足基本需求的LAMP环境的CentOS 7上安装和配置iTOP。

下载 iTOP

iTOP的下载包现在在SourceForge上,我们可以从这获取它的官方链接

itop download

我们从这里的连接用wget命令获取压缩文件。

[root@centos-007 ~]# wget http://downloads.sourceforge.net/project/itop/itop/2.1.0/iTop-2.1.0-2127.zip

iTop扩展和网络安装

使用unzip命令解压到apache根目录下的itop文件夹下。

[root@centos-7 ~]# ls
iTop-2.1.0-2127.zip
[root@centos-7 ~]# unzip iTop-2.1.0-2127.zip -d /var/www/html/itop/

列出安装包中的内容。

[root@centos-7 ~]# ls -lh /var/www/html/itop/
total 68K
-rw-r--r--. 1 root root 1.4K Dec 17 2014 INSTALL
-rw-r--r--. 1 root root 35K Dec 17 2014 LICENSE
-rw-r--r--. 1 root root 23K Dec 17 2014 README
drwxr-xr-x. 19 root root 4.0K Jul 14 13:10 web

这些是我们可以安装的扩展。

[root@centos-7 2.x]# ls
authent-external itop-backup itop-config-mgmt itop-problem-mgmt itop-service-mgmt-provider itop-welcome-itil
authent-ldap itop-bridge-virtualization-storage itop-datacenter-mgmt itop-profiles-itil itop-sla-computation version.xml
authent-local itop-change-mgmt itop-endusers-devices itop-request-mgmt itop-storage-mgmt wizard-icons
installation.xml itop-change-mgmt-itil itop-incident-mgmt-itil itop-request-mgmt-itil itop-tickets
itop-attachments itop-config itop-knownerror-mgmt itop-service-mgmt itop-virtualization-mgmt

在解压的目录下,使用如下的 cp 命令将不同的数据模型从web 下的 datamodels 目录下复制到 extensions 目录,来迁移需要的扩展。

[root@centos-7 2.x]# pwd
/var/www/html/itop/web/datamodels/2.x
[root@centos-7 2.x]# cp -r itop-request-mgmt itop-service-mgmt itop-service-mgmt itop-config itop-change-mgmt /var/www/html/itop/web/extensions/

安装 iTop web界面

大多数服务端设置和配置已经完成了。最后我们安装web界面来完成安装。

打开浏览器使用ip地址或者完整域名来访问iTop 的 web目录。

http://servers_ip_address/itop/web/

你会被重定向到iTOP的web安装页面。让我们按照要求配置,就像在这篇教程中做的那样。

验证先决要求

这一步你就会看到验证完成的欢迎界面。如果你看到了一些警告信息,你需要先安装这些软件来解决这些问题。

mcrypt missing

这一步有一个叫php mcrypt的可选包丢失了。下载下面的rpm包接着尝试安装php mcrypt包。

[root@centos-7 ~]#yum localinstall php-mcrypt-5.3.3-1.el6.x86_64.rpm libmcrypt-2.5.8-9.el6.x86_64.rpm.

成功安装完php-mcrypt后,我们需要重启apache服务,接着刷新页面,这时验证应该已经OK。

安装或者升级 iTop

现在我们要在没有安装iTOP的服务器上选择全新安装。

Install New iTop

iTop 许可协议

勾选接受 iTOP所有组件的许可协议,并点击“NEXT”。

License Agreement

数据库配置

现在我们输入数据库凭据来配置数据库连接,接着选择如下选择创建新数据库。

DB Connection

管理员账户

这一步中我们会输入它的登录信息来配置管理员账户。

Admin Account

杂项参数

让我们选择额外的参数来选择你是否需要安装一个带有演示内容的数据库或者使用全新的数据库,接着下一步。

Misc Parameters

iTop 配置管理

下面的选项允许你配置在iTOP要管理的元素类型,像CMDB、数据中心设备、存储设备和虚拟化这些东西在iTOP中是必须的。

Conf Management

服务管理

选择一个最能描述你的IT设备和环境之间的关系的选项。因此我们这里选择为服务提供商的服务管理。

Service Management

iTop Tickets 管理

从不同的可用选项我们选择符合ITIL Tickets管理选项来管理不同类型的用户请求和事件。

Ticket Management

改变管理选项

选择不同的ticket类型以便管理可用选项中的IT设备变更。我们选择ITTL变更管理选项。

ITIL Change

iTop 扩展

这一节我们选择额外的扩展来安装或者不选直接跳过。

iTop Extensions

准备开始web安装

现在我们开始准备安装先前先前选择的组件。我们也可以下拉这些安装参数来浏览我们的配置。

确认安装参数后点击安装按钮。

Installation Parameters

让我们等待进度条来完成安装步骤。它也许会花费几分钟来完成安装步骤。

iTop Installation Process

iTop安装完成

我们的iTOP安装已经完成了,只要如下一个简单的手动操作就可以进入到iTOP。

iTop Done

欢迎来到iTop (IT操作门户)

itop welcome note

iTop 面板

你这里可以配置任何东西,服务、计算机、通讯录、位置、合同、网络设备等等。你可以创建你自己的。事实是刚安装的CMDB模块是每一个IT人员的必备模块。

iTop Dashboard

总结

ITOP是一个最棒的开源桌面服务解决方案。我们已经在CentOS 7上成功地安装和配置了。因此,iTOP最强大的一方面是它可以很简单地通过扩展来自定义。如果你在安装中遇到任何问题欢迎评论。


via: http://linoxide.com/tools/setup-itop-centos-7/

作者:Kashif Siddique 译者:geekpi 校对:wxy

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

在2015年8月16日, Debian项目组庆祝了 Debian 的22周年纪念日;这也是开源世界历史最悠久、热门的发行版之一。 Debian项目于1993年由Ian Murdock创立。彼时,Slackware 作为最早的 Linux 发行版已经名声在外。

Happy 22nd Birthday to Debian

22岁生日快乐! Debian Linux!

Ian Ashly Murdock, 一个美国职业软件工程师, 在他还是普渡大学的学生时构想出了 Debian 项目的计划。他把这个项目命名为 Debian 是由于这个名字组合了他彼时女友的名字 Debra Lynn 和他自己的名字 Ian。 他之后和 Lynn 结婚并在2008年1月离婚。

Ian Murdock

Debian 创始人:Ian Murdock

Ian 目前是 ExactTarget 的平台与开发社区的副总裁。

Debian (如同Slackware一样) 都是由于当时缺乏满足合乎标准的发行版才应运而生的。 Ian 在一次采访中说:“免费提供一流的产品会是 Debian 项目的唯一使命。 尽管过去的 Linux 发行版均不尽然可靠抑或是优秀。 我印象里...比如在不同的文件系统间移动文件, 处理大型文件经常会导致内核出错。 但是 Linux 其实是很可靠的, 自由的源代码让这个项目本质上很有前途。”

"我记得过去我像其他想解决问题的人一样, 想在家里运行一个像 UNIX 的东西。 但那是不可能的, 无论是经济上还是法律上或是别的什么角度。 然后我就听闻了 GNU 内核开发项目, 以及这个项目是如何没有任何法律纷争", Ian 补充到。 他早年在开发 Debian 时曾被自由软件基金会(FSF)资助, 这份资助帮助 Debian 取得了长足的发展; 尽管一年后由于学业原因 Ian 退出了 FSF 转而去完成他的学位。

Debian开发历史

  • Debian 0.01 – 0.09 : 发布于 1993 年八月 – 1993 年十二月。
  • Debian 0.91 : 发布于 1994 年一月。 有了原始的包管理系统, 没有依赖管理机制。
  • Debian 0.93 rc5 : 发布于 1995 年三月。 “现代”意义的 Debian 的第一次发布, 在基础系统安装后会使用dpkg 安装以及管理其他软件包。
  • Debian 0.93 rc6: 发布于 1995 年十一月。 最后一次 a.out 发布, deselect 机制第一次出现, 有60位开发者在彼时维护着软件包。
  • Debian 1.1: 发布于 1996 年六月。 项目代号 – Buzz, 软件包数量 – 474, 包管理器 dpkg, 内核版本 2.0, ELF 二进制。
  • Debian 1.2: 发布于 1996 年十二月。 项目代号 – Rex, 软件包数量 – 848, 开发者数量 – 120。
  • Debian 1.3: 发布于 1997 年七月。 项目代号 – Bo, 软件包数量 974, 开发者数量 – 200。
  • Debian 2.0: 发布于 1998 年七月。 项目代号 - Hamm, 支持构架 – Intel i386 以及 Motorola 68000 系列, 软件包数量: 1500+, 开发者数量: 400+, 内置了 glibc。
  • Debian 2.1: 发布于1999 年三月九日。 项目代号 – slink, 支持构架 - Alpha 和 Sparc, apt 包管理器开始成型, 软件包数量 – 2250。
  • Debian 2.2: 发布于 2000 年八月十五日。 项目代号 – Potato, 支持构架 – Intel i386, Motorola 68000 系列, Alpha, SUN Sparc, PowerPC 以及 ARM 构架。 软件包数量: 3900+ (二进制) 以及 2600+ (源代码), 开发者数量 – 450。 有一群人在那时研究并发表了一篇论文, 论文展示了自由软件是如何在被各种问题包围的情况下依然逐步成长为优秀的现代操作系统的。
  • Debian 3.0: 发布于 2002 年七月十九日。 项目代号 – woody, 支持构架新增 – HP, PA\_RISC, IA-64, MIPS 以及 IBM, 首次以DVD的形式发布, 软件包数量 – 8500+, 开发者数量 – 900+, 支持加密。
  • Debian 3.1: 发布于 2005 年六月六日。 项目代号 – sarge, 支持构架 – 新增 AMD64(非官方渠道发布), 内核 – 2.4 以及 2.6 系列, 软件包数量: 15000+, 开发者数量 : 1500+, 增加了诸如 OpenOffice 套件, Firefox 浏览器, Thunderbird, Gnome 2.8, 支持: RAID, XFS, LVM, Modular Installer。
  • Debian 4.0: 发布于 2007 年四月八日。 项目代号 – etch, 支持构架 – 如前,包括 AMD64。 软件包数量: 18,200+ 开发者数量 : 1030+, 图形化安装器。
  • Debian 5.0: 发布于 2009 年二月十四日。 项目代号 – lenny, 支持构架 – 新增 ARM。 软件包数量: 23000+, 开发者数量: 1010+。
  • Debian 6.0: 发布于 2009 年七月二十九日。 项目代号 – squeeze, 包含的软件包: 内核 2.6.32, Gnome 2.3. Xorg 7.5, 同时包含了 DKMS, 基于依赖包支持。 支持构架 : 新增 kfreebsd-i386 以及 kfreebsd-amd64, 基于依赖管理的启动过程。
  • Debian 7.0: 发布于 2013 年五月四日。 项目代号: wheezy, 支持 Multiarch, 私有云工具, 升级了安装器, 移除了第三方软件依赖, 全功能多媒体套件-codec, 内核版本 3.2, Xen Hypervisor 4.1.4 ,软件包数量: 37400+。
  • Debian 8.0: 发布于 2015 年五月二十五日。 项目代号: Jessie, 将 Systemd 作为默认的初始化系统, 内核版本 3.16, 增加了快速启动(fast booting), service进程所依赖的 cgroups 使隔离部分 service 进程成为可能, 43000+ 软件包。 Sysvinit 初始化工具在 Jessie 中可用。

注意: Linux的内核第一次是在1991 年十月五日被发布, 而 Debian 的首次发布则在1993 年九月十三日。 所以 Debian 已经在只有24岁的 Linux 内核上运行了整整22年了。

Debian 的那些事

1994年管理和重整了 Debian 项目以使得其他开发者能更好地加入,所以在那一年并没有发布面向用户的更新, 当然, 内部版本肯定是有的。

Debian 1.0 从来就没有被发布过。 一家 CD-ROM 的生产商错误地把某个未发布的版本标注为了 1.0, 为了避免产生混乱, 原本的 Debian 1.0 以1.1的面貌发布了。 从那以后才有了所谓的官方CD-ROM的概念。

每个 Debian 新版本的代号都是玩具总动员里某个角色的名字哦。

Debian 有四种可用版本: 旧稳定版(old stable), 稳定版(stable), 测试版(testing) 以及 试验版(experimental)。 始终如此。

Debian 项目组一直工作在不稳定发行版上, 这个不稳定版本始终被叫做Sid(玩具总动员里那个邪恶的臭小孩)。 Sid是unstable版本的永久名称, 同时Sid也取自'Still In Development"(译者:还在开发中)的首字母。 Sid 将会成为下一个稳定版, 当前的稳定版本代号为 jessie。

Debian 的官方发行版只包含开源并且自由的软件, 绝无其他东西. 不过 contrib 和非自由软件包使得安装那些本身自由但是其依赖的软件包不自由(contrib)的软件和非自由软件成为了可能。

Debian 是一堆Linux 发行版之母。 举几个例子:

  • Damn Small Linux
  • KNOPPIX
  • Linux Advanced
  • MEPIS
  • Ubuntu
  • 64studio (不再活跃开发)
  • LMDE

Debian 是世界上最大的非商业 Linux 发行版。它主要是由C编写的(32.1%), 一并的还有其他70多种语言。

Debian 开发语言贡献表

Debian 开发语言贡献表,图片来源: Xmodulo

Debian 项目包含6,850万行代码, 以及 450万行空格和注释。

国际空间站放弃了 Windows 和红帽子, 进而换成了 Debian - 在上面的宇航员使用落后一个版本的稳定发行版, 目前是 squeeze; 这么做是为了稳定程度以及来自 Debian 社区的雄厚帮助支持。

感谢上帝! 我们差点就听到来自国际空间宇航员面对 Windows Metro 界面的尖叫了 :P

黑色星期三

2002 年十一月二十日, Twente 大学的网络运营中心(NOC)着火。 当地消防部门放弃了服务器区域。 NOC维护着satie.debian.org 的网站服务器, 这个网站包含了安全、非美国相关的存档、新维护者资料、数量报告、数据库等等;这一切都化为了灰烬。 之后这些服务由 Debian 重建了。

未来版本

下一个待发布版本是 Debian 9, 项目代号 – Stretch, 它会带来什么还是个未知数。 满心期待吧!

有很多发行版在 Linux 发行版的历史上出现过一瞬间然后很快消失了。 在多数情况下, 维护一个日渐庞大的项目是开发者们面临的挑战。 但这对 Debian 来说不是问题。 Debian 项目有全世界成百上千的开发者、维护者。 它在 Linux 诞生的之初起便一直存在。

Debian 在 Linux 生态环境中的贡献是难以用语言描述的。 如果 Debian 没有出现过, 那么 Linux 世界将不会像现在这样丰富和用户友好。 Debian 是为数不多可以被认为安全可靠又稳定的发行版,是作为网络服务器完美选择。

这仅仅是 Debian 的一个开始。 它走过了这么长的征程, 并将一直走下去。 未来即是现在! 世界近在眼前! 如果你到现在还从来没有使用过 Debian, 我只想问, 你还再等什么? 快去下载一份镜像试试吧, 我们会在此守候遇到任何问题的你。


via: http://www.tecmint.com/happy-birthday-to-debian-gnu-linux/

作者:Avishek Kumar 译者:jerryling315 校对:wxy

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