Linux Makefile analysis for plain usr

摘要:
编译内核时,将head y表示的文件与内置的连接起来。o、 库。a和顶级Makefile中定义的其他文件,以生成内核映像文件vmlinux。顶级Makefile和脚本/Makefile。生成间接包含。config文件config中定义的变量决定要编译的文件。顶级MakefileLine486:includeinclude/config/auto.coscripts/Makefile。buildLine34:includeinclude/config/auto confinclude/config/auto的生成过程。conf文件不再描述。魏东山在他的书中说,汽车。Linux 2.6.22.6内核的conf文件与auto。Linux 2.6.22.6内核的conf文件删除了conf文件中的注释,并根据顶级Makefile中定义的变量添加了一些变量。内置。o文件将被其上层Makefile使用。

一、本文主旨

  笔者写了一篇linux内核Makefile整体分析 ,测重于理论分析,对于实际应用不算对头,所以需要写一篇实用性较强的文章,为以后内核、驱动移植做好铺垫。

二、本文内容概要

1、编译哪些文件

2、怎样编译这些文件

3、怎样连接这些文件,它们的顺序如何

三、编译哪些文件

  本文的实验源码是对“linux-2.6.30.4”进行移植后的运行在TQ2440开发板上的源码包。

1、顶层Makefile决定内核根目录下哪些子目录被编进内核  

Line 477: 
init-y        := init/
drivers-y    := drivers/ sound/ firmware/
net-y        := net/
libs-y        := lib/
core-y        := usr/

Line 650: 
core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

  编译内核时,将依次通过调用scripts/Makefile.build进入init-y、core-y、libs-y、drivers-y、net-y所列出的目录中配合它们的Makefile进行编译。每个子目录都会生成一个built-in.o(libs-y所列目录下,有可能生成lib.a文件)。  

2、arch/$(ARCH)/Makefile决定与架构有关目录下的哪些文件、哪些目录被编译内核

  以ARM体系为例,在arch/arm/Makefile中可以看到如下内容:

Line 100:
head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

Line 195:
# If we have a machine-specific directory, then include it in the build.
core-y                += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y                += $(machdirs) $(platdirs)
core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE)    += $(FASTFPE_OBJ)
core-$(CONFIG_VFP)        += arch/arm/vfp/

Line 204:
libs-y:= arch/arm/lib/ $(libs-y)

  head-y,MMUEXT在arch/arm/Makefile前面定义,对于没有MMU的处理器,MMUEXT的值为-nommu,使用文件head-nommu.S;对于有MMU的处理器,MMUEXT的值为空,使用文件head.S。

  arch/arm/Makefile中从第195行开始扩展了core-y的内容,第204行扩展了libs-y的内容,这些都是体系结构相关的目录。CONFIG_FPE_NWFPE在配置内核时定义,它的值有三种:y、m或空。y表示编进内核,m表示编为模块,空代表不使用。

  编译内核时,将head-y所表示的文件和顶层Makefile中定义的built-in.o、lib.a等文件一起连接生成内核映像文件vmlinux。

3、各级子目录下的Makefile决定所在目录下的哪些文件将被编进内核,哪些文件将被编成模块

  在配置内核时,生成.conf文件。顶层Makefile和scripts/Makefile.build间接包含.config文件,.config中定义的各个变量决定编译哪些文件。之所以说是“间接”包含,是因为包含的是include/config/auto.conf文件。

顶层Makefile Line 486: 
-include include/config/auto.conf

scripts/Makefile.build Line 34: 
-include include/config/auto.conf

  include/config/auto.conf文件的生成过程不再描述,韦东山书上说:Linux 2.6.22.6版本的内核的auto.conf文件,是将.conf文件中的注释去掉,并根据顶层Makefile中定义的变量增加了一些变量生成的。据我观察,linux-2.6.30.4版本的内核的auto.conf文件就是将.conf文件中的注释去掉而已,没有添加变量。摘选部分内容如下:

Line 36: CONFIG_ARCH_S3C2410=y
Line 40: CONFIG_ARCH_S3C2440=y
Line 253: CONFIG_LOCALVERSION="-EmbedSky"

Line 384: CONFIG_ARM=y
Line 407: CONFIG_ARCH_TQ2440=y

  在include/config/auto.conf文件中,变量的值主要有两类:y、m。各级子目录的Makefile就是使用这些变量来决定哪些文件被编进内核,哪些文件被编译成模块(即驱动程序)。

①obj-y用来指定哪些文件被编进内核(built-in)

  obj-y中定义的.o文件是由当期那目录下的.c或.S文件编译生成的,它们连同下级子目录下的built-in.o文件一起被组合成(使用$(LD) -r命令)当前目录下的built-in.o文件。这个built-in.o文件将被它的上一层Makefile使用。

  obj-y中各个.o文件的顺序是有意义的,因为内核中使用module_init()或__initcall定义的函数将按照它们的连接顺序被调用。

例如:当下面的CONFIG_ISDN、CONFIG_ISDN_PPP_BSDCOMP在.config中被定义为y时,isdc.c或isdn.S、idsn_bsdcomp.c或isdn_bsdcomp.S被编译成isdn.o、isdn_bsdcomp.o。这两个.o文件被组合成built-in.o文件中,最后被连接进入内核。假如isdn.o、isdn_bsdcomp.o中分别用module_init(A)、module(B)定义了函数A、B,则内核启动时A先被调用,然后才是B。

obj-$(CONFIG_ISDN)            += isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP)    +=isdn_bsdcomp.o

②obj-m用来定义哪些文件被编译成可加载模块(Loadable module)

  obj-m中定义的.o文件由当前目录下的.c或者.S文件生成,它们不会被编进内核built-in.o,而是被编成可加载模块。

一个模块可以由一个或者几个.o文件组成。

  对于只有一个源文件的模块,在obj-m中直接增加它的.o文件即可。

  对于由多个源文件组成的模块,除在obj-m中增加一个.o文件外,还要定义一个<module_name>-objs变量来告诉Makefile这个.o文件由哪些文件组成。

例1:当下面的CONFIG_ISDN_PPP_BSDCOMP在.cofig文件中被定义为m时,isdn_bsdcomp.c或isdn_bsdcomp.S将被编译成isdn_bsdcomp.o文件,它最后被制作成isdn_bsdcomp.ko模块,如下所示:

#drivers/isdn/i41/Makefile:
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

例2:当下面的CONFIG_ISDN在.config文件中被定义为m时,将会生成一个isdn.o文件,它由isdn-objs中定义的isdn_net_lib.o、isdn_v110.o、isdn_common.o等三个文件组合而成。isdn.o文件最后被制作成isdn.ko模块。

#drivers/isdn/i41/Makefile
obj-$(CONFIG_ISDN) +=isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

③lib-y用来定义哪些文件被编成库文件

  lib-y中定义的.o文件由当前目录下的.c或者.S文件编译生成,它们被打包成当前目录下的库文件的内核代码一般都在这两个目录下:lib/、arch/$(ARCH)/lib/。

④ obj-y、obj-m还可以用来指定要进入的下一层子目录

  Linux中的一个Makefile文件只负责生成当前目录下的目标文件,子目录下的目标文件由子目录下的Makefile生成。Linux的编译系统会自动进入这些子目录调用它们的Makefile,只是在这之前指定这些目录。

  这要用到obj-y、obj-m,只要在其中增加这些目录名即可。

例如:fs/Makefile中有如下一行,当CONFIG_JFFS2_FS被定义为y或者m时,在编译时会进入jffs2目录进行编译。Linux的编译系统只会根据这些信息决定是否进入下一级目录,而下一级的文件如何编译成built-in.o或模块有它们的Makefile决定。

obj-$(CONFIG_JFFS2_FS) +=jffs2/

四、怎样编译这些文件

  即编译选项、连接选项是什么。这些选项分3类:全局的,适用于整个内核源码树;局部的,仅适用于某个Makefile中的所有文件;个体的,仅适用于某个文件。

1、全局选项

  全局选项在顶层Makefile和arch/$(ARCH)/Makefile中定义,这些选项的名称为:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS,它们分别是编译C文件的选项、编译汇编文件的选项、连接文件的选项、制作库文件的选项。

2、局部选项

  需要使用局部选项时,它们在各个子目录中定义,名称为:EXTRA_CFLAFS、EXTRA_AFLAGS、EXTRA_LDFLAGS、EXTRA_ARFLAGS,它们的用途与前述选项相同。只是使用范围更小,只针对当前Makefile中的所有文件。

3、个体选项

  如果想只针对某个文件定义它的编译选项,可以使用CFLAGS_@,AFLAGS_@。前者由于编译某个C文件,后者用于编译某个汇编文件。@表示某个目标文件名,比如以下代码表示编译aha152x.c时,选项要额外加上“-DAHA152X_STAT -DAUTOCONF”。

#drivers/scsi/Makefile
CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF

  需要注意的是,这3类选项是一起使用的,在scripts/Makefile.lib中可以看到。

_c_flags  = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o)

 五、怎样连接这些文件,它们的顺序如何

  在linux内核Makefile整体分析中的章节2、vmlinux的生成中详细讲了vmlinux的依赖,以及它们的顺序。

顶层Makefile Line 696:
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(SRCARCH)/kernel/vmlinux.lds

  vmlinux-all表示所有构成内核映像的目标文件,它们的连接顺序为:head-y、init-y、core-y、libs-y、drivers-y、net-y,即arch/arm/kernel/head.o、arch/arm/kernel/init_task.o、init/built-in.o、usr/built-in.o等等。通过打印命令的方式显示它们完整的连接顺序。

root@daneiqi:/workspace/linux-EmbedSky# make uImage V=1
  arm-linux-ld -EL  -p --no-undefined -X --build-id -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o 
  arch/arm/kernel/init_task.o  init/built-in.o --start-group  usr/built-in.o  arch/arm/kernel/built-in.o  
  arch/arm/mm/built-in.o  arch/arm/common/built-in.o  arch/arm/mach-s3c2410/built-in.o  
  arch/arm/mach-s3c2400/built-in.o  arch/arm/mach-s3c2412/built-in.o  arch/arm/mach-s3c2440/built-in.o  
  arch/arm/mach-s3c2442/built-in.o  arch/arm/mach-s3c2443/built-in.o  arch/arm/plat-s3c24xx/built-in.o  
  arch/arm/plat-s3c/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  arch/arm/lib/lib.a  lib/lib.a  arch/arm/lib/built-in.o  lib/built-in.o  
  drivers/built-in.o  sound/built-in.o  firmware/built-in.o  net/built-in.o --end-group .tmp_kallsyms2.o

  连接脚本为arch/$(ARCH)/kernel/vmlinux.lds。对于ARM体系,连接脚本就是arch/arm/kernel/vmlinux.lds,它由arch/arm/kernel/vmlinux.lds.S文件生成,生成规则在scripts/Makefile.build中,如下所示:

Line 268: 
$(obj)/%.lds: $(src)/%.lds.S FORCE
    $(call if_changed_dep,cpp_lds_S)

  先将生成的arch/arm/kernel/vmlinux.lds摘录如下:]

OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
{
 . = 0xC0000000 + 0x00008000; /* 代码段起始地址,这是个虚地址      */
 .text.head : {
  _stext = .;
  _sinittext = .;
  *(.text.head)
 }
 .init : { /* 内核初始化的代码和数据       */
   *(.init.text) *(.cpuinit.text) *(.meminit.text)
  _einittext = .;
  __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;
  __arch_info_begin = .;
   *(.arch.info.init)
  __arch_info_end = .;
  __tagtable_begin = .;
   *(.taglist.init)
  __tagtable_end = .;
  . = ALIGN(16);
  __setup_start = .;
   *(.init.setup)
  __setup_end = .;
  __early_begin = .;
   *(.early_param.init)
  __early_end = .;
  __initcall_start = .;
   *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
  __initcall_end = .;
  __con_initcall_start = .;
   *(.con_initcall.init)
  __con_initcall_end = .;
  __security_initcall_start = .;
   *(.security_initcall.init)
  __security_initcall_end = .;
  . = ALIGN(4096);
  __per_cpu_load = .;
  __per_cpu_start = .;
   *(.data.percpu.page_aligned)
   *(.data.percpu)
   *(.data.percpu.shared_aligned)
  __per_cpu_end = .;
  __init_begin = _stext;
  *(.init.data) *(.cpuinit.data) *(.cpuinit.rodata) *(.meminit.data) *(.meminit.rodata)
  . = ALIGN(4096);
  __init_end = .;
 }
 /DISCARD/ : { /* Exit code and data        */
  *(.exit.text) *(.cpuexit.text) *(.memexit.text)
  *(.exit.data) *(.cpuexit.data) *(.cpuexit.rodata) *(.memexit.data) *(.memexit.rodata)
  *(.exitcall.exit)
  *(.ARM.exidx.exit.text)
  *(.ARM.extab.exit.text)
 }
 .text : { /* 真正的代码段        */
  _text = .; /* 代码段和只读数据段的开始地址   */
   __exception_text_start = .;
   *(.exception.text)
   __exception_text_end = .;
   . = ALIGN(8); *(.text.hot) *(.text) *(.ref.text) *(.devinit.text) *(.devexit.text) *(.text.unlikely)
   . = ALIGN(8); __sched_text_start = .; *(.sched.text) __sched_text_end = .;
   . = ALIGN(8); __lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
   . = ALIGN(8); __kprobes_text_start = .; *(.kprobes.text) __kprobes_text_end = .;
   *(.fixup)
   *(.gnu.warning)
   *(.rodata)
   *(.rodata.*)
   *(.glue_7)
   *(.glue_7t)
  *(.got) /* Global offset table        */
 }

/* 只读数据段       */
 . = ALIGN((4096)); .rodata : AT(ADDR(.rodata) - 0) { __start_rodata = .; *(.rodata) *(.rodata.*) *(__vermagic) *(__markers_strings) *(__tracepoints_strings) } .rodata1 : AT(ADDR(.rodata1) - 0) { *(.rodata1) } .pci_fixup : AT(ADDR(.pci_fixup) - 0) { __start_pci_fixups_early = .; *(.pci_fixup_early) __end_pci_fixups_early = .; __start_pci_fixups_header = .; *(.pci_fixup_header) __end_pci_fixups_header = .; __start_pci_fixups_final = .; *(.pci_fixup_final) __end_pci_fixups_final = .; __start_pci_fixups_enable = .; *(.pci_fixup_enable) __end_pci_fixups_enable = .; __start_pci_fixups_resume = .; *(.pci_fixup_resume) __end_pci_fixups_resume = .; __start_pci_fixups_resume_early = .; *(.pci_fixup_resume_early) __end_pci_fixups_resume_early = .; __start_pci_fixups_suspend = .; *(.pci_fixup_suspend) __end_pci_fixups_suspend = .; } .builtin_fw : AT(ADDR(.builtin_fw) - 0) { __start_builtin_fw = .; *(.builtin_fw) __end_builtin_fw = .; } .rio_route : AT(ADDR(.rio_route) - 0) { __start_rio_route_ops = .; *(.rio_route_ops) __end_rio_route_ops = .; } __ksymtab : AT(ADDR(__ksymtab) - 0) { __start___ksymtab = .; *(__ksymtab) __stop___ksymtab = .; } __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - 0) { __start___ksymtab_gpl = .; *(__ksymtab_gpl) __stop___ksymtab_gpl = .; } __ksymtab_unused : AT(ADDR(__ksymtab_unused) - 0) { __start___ksymtab_unused = .; *(__ksymtab_unused) __stop___ksymtab_unused = .; } __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - 0) { __start___ksymtab_unused_gpl = .; *(__ksymtab_unused_gpl) __stop___ksymtab_unused_gpl = .; } __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - 0) { __start___ksymtab_gpl_future = .; *(__ksymtab_gpl_future) __stop___ksymtab_gpl_future = .; } __kcrctab : AT(ADDR(__kcrctab) - 0) { __start___kcrctab = .; *(__kcrctab) __stop___kcrctab = .; } __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - 0) { __start___kcrctab_gpl = .; *(__kcrctab_gpl) __stop___kcrctab_gpl = .; } __kcrctab_unused : AT(ADDR(__kcrctab_unused) - 0) { __start___kcrctab_unused = .; *(__kcrctab_unused) __stop___kcrctab_unused = .; } __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - 0) { __start___kcrctab_unused_gpl = .; *(__kcrctab_unused_gpl) __stop___kcrctab_unused_gpl = .; } __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - 0) { __start___kcrctab_gpl_future = .; *(__kcrctab_gpl_future) __stop___kcrctab_gpl_future = .; } __ksymtab_strings : AT(ADDR(__ksymtab_strings) - 0) { *(__ksymtab_strings) } __init_rodata : AT(ADDR(__init_rodata) - 0) { *(.ref.rodata) *(.devinit.rodata) *(.devexit.rodata) } __param : AT(ADDR(__param) - 0) { __start___param = .; *(__param) __stop___param = .; . = ALIGN((4096)); __end_rodata = .; } . = ALIGN((4096));
 _etext = .;                /* 代码段和只读数据段的结束地址    */
 . = ALIGN(8192);
 __data_loc = .;
 .data : AT(__data_loc) {  /* 数据段   */
  _data = .; /* 数据段的起始地址 */
  /*
         * first, the init task union, aligned
         * to an 8192 byte boundary.
         */
  *(.data.init_task)
  . = ALIGN(4096);
  __nosave_begin = .;
  *(.data.nosave)
  . = ALIGN(4096);
  __nosave_end = .;
  /*
         * then the cacheline aligned data
         */
  . = ALIGN(32);
  *(.data.cacheline_aligned)
  /*
         * The exception fixup table (might need resorting at runtime)
         */
  . = ALIGN(32);
  __start___ex_table = .;
  *(__ex_table)
  __stop___ex_table = .;
  /*
         * and the usual data section
         */
  *(.data) *(.ref.data) *(.devinit.data) *(.devexit.data) . = ALIGN(8); __start___markers = .; *(__markers) __stop___markers = .; . = ALIGN(32); __start___tracepoints = .; *(__tracepoints) __stop___tracepoints = .; . = ALIGN(8); __start___verbose = .; *(__verbose) __stop___verbose = .;
  CONSTRUCTORS
  _edata = .;/* 数据段的结束地址    */
 }
 _edata_loc = __data_loc + SIZEOF(.data);/* 数据段的结束地址    */
 .bss : {    /* bss段    */
  __bss_start = .; /* bss段起始地址              */
  *(.bss)
  *(COMMON)
  _end = .;    /* bss段结束地址    */
 }
     /*调试信息段    */
 .stab 0 : { *(.stab) }
 .stabstr 0 : { *(.stabstr) }
 .stab.excl 0 : { *(.stab.excl) }
 .stab.exclstr 0 : { *(.stab.exclstr) }
 .stab.index 0 : { *(.stab.index) }
 .stab.indexstr 0 : { *(.stab.indexstr) }
 .comment 0 : { *(.comment) }
}
/*
 * These must never be empty
 * If you have to comment these two assert statements out, your
 * binutils is too old (for other reasons as well)
 */
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")                    

六、总结

(1)顶层Makefile和arch/arm/Makefile决定根目录下哪些子目录、arch/arm目录下哪些文件和目录被编进内核

(2)配置文件.conf中定义了一系列的变量,子目录的Makefile将结合它们来决定子目录下哪些文件被编进内核、哪些文件被编成模块、涉及及哪些子目录。

(3)顶层Makefile和arch/$(ARCH)/Makefile设置了可以影响所有文件的编译、连接选项:CFLAGS、AFLAGS、LDFLAGS、ARFLAGS。

(4)各级子目录下的Makefile中设置能够影响当前目录下所有文件的编译、连接选项:EXTRA_CFLAFS、EXTRA_AFLAGS、EXTRA_LDFLAGS、EXTRA_ARFLAGS;还可以设置影响某个文件的编译选项:CFLAFS_@、 AFLAGS_@。

(5)顶层Makefile按照一定的顺序组织文件,根据连接脚本arch/$(ARCH)/kernel/vmlinux.lds生成内核映像文件vmlinux。

参考:大部分摘录于《嵌入式Linux应用开发完全手册》

    linux2.6内核Makefile详解documention/kbuild/makefiles.txt中文版翻译

免责声明:文章转载自《Linux Makefile analysis for plain usr》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【解决】GridView设置了 android:listSelector,选中某项背景色也会被选中Enigma Virtual Box:生成可执行文件。下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Golang之基于Linux开发环境

Golang之基于Linux开发环境 简述   常规方式是在windows本地安装Goland及sdk进行开发工作,这次在Linux上安装Golang tar包,并在windows远程连接Linux环境使用Goland开发。 详细操作 golang的官网在国内访问比较慢,建议去国内的网站下载https://studygolang.com/dl 根据不同的平...

XAMPP 的安装配置(Linux 版)

 --姜庭华  msn: jaimejth@live.cn --博客:http://blog.csdn.net/jaimejth 软件下载在以下网站 http://www.apachefriends.org/zh_cn/index.html XAMPP 是一个易于安装且包含 MySQL、PHP 和 Perl 的 Apache 发行版。XAMPP 的确非常容...

帆软Linux导出或打印乱码

Linux导出或打印乱码 目录: 1. 问题描述 2. 原因 3. 解决方案 1. 问题描述 (1)在Linux环境下,会发现客户端预览是正常的,但是在导出或打印时会出现乱码,或者一些特殊符号如人民币符号"¥",在导出或打印时发现变成了美元符号"$"。 (2)在Linux系统的客户端,预览或导出的图片乱码。   2. 原因   2.1 ...

linux报错-bash: xhost: command not found

本帖转自倔强小梦https://www.cnblogs.com/xphdbky/p/8243008.html 倔强小梦参考自:http://blog.csdn.net/csdnones/article/details/51513163,感谢原作者解决了我的问题。  在root用户下执行xhost +,报以下错误,原因是因未没有安装相关的包(其他类似comm...

(转)FreeBSD和LINUX新手命令

 1.登录和退出   登录时(当看到login:时)你必须是在系统安装时创建的用户或root超级用户. (在FreeBSD系统安装时就已经创建了root用户了 ,root用户遍历到系统的任何一个目录并且可以做任何事情,包括删除系统文件,所以一定要千万小心!)符号%和符号# 代表提示符(你的可能不一样),%表示普通用户,#表示超级用户root要退出系统(并且...

Linux rpm命令

      rpm,英文全称RedHat Package Manager,是Linux下的软件包管理软件,类似Windows下的“添加/删除程序”。通过rpm软件管理系统,Linux实现了对.rpm软件包安装、删除、更新、管理的自动化操作。rpm软件包名称中包含了软件包的版本信息,适用的操作系统信息,适用的硬件架构信息(noarch说明软件包与硬件架构无关...