2016-10-29 00:37:24 u012891948 阅读数 2225
  • Linux应用软件服务篇-五剑客

    第一章节讲解主流的 Vsftp服务器如何通过服务端与客户端实现文件资源共享,讲解了Vsftp之间三种用户在不同的配置方法对不同的目录文件资源限制访问,达到更安全高效的资源共享数据传输。 第二章节讲解企业级NTP时间服务器对公司内网所有客户机及服务器批量实现时间同步,多个节点如何去快速同步主服务器时间。  第三章节讲解 NFS服务器实现与客户机磁盘文件的共享,通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,重点讲解了通过客户端远程挂载服务器磁盘共享文件及如何使用指定用户去访问指定的共享文件夹数据。 第四章节讲解samba服务器在企业中,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源,重点介绍了通过 samba配置文件权限配置去对匿名文件夹及指定用户文件夹共享资源服务。 第五章节介绍了去部署 DHCP服务器对批量客户端实现自动获取IP,通过配置文件IP池获取到IP形式,及绑定客户端Mac地址及指定IP给予客户端,从而获得IP方法。

    140 人正在学习 去看看 吴光科



【转自 http://blog.csdn.net/guopeixin/article/details/5962482】



前言:

本篇文章以S3C6410公版的Linux BSP和U-Boot来进行分析,文中所有提及的名词和数据都是以该环境为例,所有的代码流程也是以该环境为例来进行分析。哈哈。如果有不正确或者不完善的地方,欢迎前来拍砖留言或者发邮件到guopeixin@126.com进行讨论,先行谢过。

简单的来说,根文件系统包括虚拟根文件系统和真实根文件系统。在Kernel启动的初始阶段,首先去创建虚拟的根文件系统,接下来再去调用do_mount来加载真正的文件系统,并将根文件系统切换到真正的文件系统,也即真实的文件系统。

一.什么是根文件系统

在传统的Windows机器上目录结构中,可能会包括C:或者D:盘,而他们一般就称之为特定逻辑磁盘的根目录。从文件系统的层面来说,每一个分区都包含了一个根目录区,也即系统中存在多个根目录。

但是,在Linux系统中,目录结构与Windows上有较大的不同。系统中只有一个根目录,路径是“/”,而其它的分区只是挂载在根目录中的一个文件夹,如“/proc”和“system”等,这里的“/”就是Linux中的根目录。

对应根目录也就存在一个根目录文件系统的概念,我们可以将某一个分区挂载为根目录文件系统,如6410公版中就将mtdblk2挂载为根目录文件系统。程序中可以通过U-Boot给Kernel指定参数或者编译选项来指定,如目前的开发板中就通过如下的编译选项来制定根目录文件系统:

CONFIG_CMDLINE="console=ttyS0,115200 mem=108M rdinit=/linuxrc root=/dev/mtdblock2"

简单的来说,根目录文件系统就是一种目录结构,包括了Linux启动的时候所必须的一些目录结构和重要文件。

根文件系统有两种,一种是虚拟根文件系统,另外一种是真实的根文件系统。一般情况下,会首先在虚拟的根文件系统中做一部分工作,然后切换到真实的根文件系统下面。

笼统的来说,虚拟的根文件系统包括三种类型,即Initramfs、cpio-initrd和image-initrd。

二.相关重要概念

1. Initrd

Initrd是在Linux中普遍采用的一种技术,就是由Bootloader加载的内存盘。在系统启动的过程中,首先会执行Initrd中的“某一个文件” 来完成驱动模块加载的任务,第二阶段才会执行真正的根文件系统中的/sbin/init。这里提到的第一阶段是为第二阶段服务的,主要是用来加载根文件系统以及根文件系统存储介质的驱动程序。

资料中提到,存在多种类型的Initrd,实际应用中包括无Initrd、Linux Kernel和Initrd打包、Linux Kernel和Initrd分离以及RAMDisk Initrd。

目前,手中项目采用的就是第四种策略。在系统启动的时候,U-Boot会将Linux Kernel和Rootfs加载到内存,并跳转到Linux Kernel的入口地址执行程序。这篇文章将侧重对该种情况进行分析。

三.根文件系统加载代码分析

1. VFS的注册

首先不得不从老掉牙的Linux系统的函数start_kernel()说起。函数start_kernel()中会去调用vfs_caches_init()来初始化VFS。

下面看一下函数vfs_caches_init ()的代码:

void __init vfs_caches_init(unsigned long mempages)

{

unsigned long reserve;

/* Base hash sizes on available memory, with a reserve equal to

150% of current kernel size */

reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);

mempages -= reserve;

names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,

SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);

dcache_init();

inode_init();

files_init(mempages);

[1] mnt_init();

bdev_cache_init();

chrdev_init();

}

代码【1】:vfs_caches_init()中最重要的函数。函数mnt_init()会创建一个rootfs,这是个虚拟的rootfs,即内存文件系统,后面还会指向真实的文件系统。

接下来看一下函数mnt_init():

Void __init mnt_init(void)

{

unsigned u;

int err;

init_rwsem(&namespace_sem);

mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),

0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);

mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);

if (!mount_hashtable)

panic("Failed to allocate mount hash table/n");

printk("Mount-cache hash table entries: %lu/n", HASH_SIZE);

for (u = 0; u < HASH_SIZE; u++)

INIT_LIST_HEAD(&mount_hashtable[u]);

err = sysfs_init();

if (err)

printk(KERN_WARNING "%s: sysfs_init error: %d/n",

__func__, err);

fs_kobj = kobject_create_and_add("fs", NULL);

if (!fs_kobj)

printk(KERN_WARNING "%s: kobj create error/n", __func__);

[1] init_rootfs();

[2] init_mount_tree();

}

代码[1]:创建虚拟根文件系统;

代码[2]:注册根文件系统。

接下来看一下函数init_mount_tree()的代码:

static void __init init_mount_tree(void)

{

struct vfsmount *mnt;

struct mnt_namespace *ns;

struct path root;

[1] mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);

if (IS_ERR(mnt))

panic("Can't create rootfs");

ns = kmalloc(sizeof(*ns), GFP_KERNEL);

if (!ns)

panic("Can't allocate initial namespace");

atomic_set(&ns->count, 1);

INIT_LIST_HEAD(&ns->list);

init_waitqueue_head(&ns->poll);

ns->event = 0;

list_add(&mnt->mnt_list, &ns->list);

ns->root = mnt;

mnt->mnt_ns = ns;

init_task.nsproxy->mnt_ns = ns;

get_mnt_ns(ns);

root.mnt = ns->root;

root.dentry = ns->root->mnt_root;

set_fs_pwd(current->fs, &root);

[2] set_fs_root(current->fs, &root);

}

代码[1]:创建虚拟文件系统;

代码[2]:将当前的文件系统配置为根文件系统。

可能有人会问,为什么不直接把真实的文件系统配置为根文件系统?

答案很简单,内核中没有根文件系统的设备驱动,如USB等存放根文件系统的设备驱动,而且即便你将根文件系统的设备驱动编译到内核中,此时它们还尚未加载,其实所有的Driver是由在后面的Kernel_Init线程进行加载。所以需要CPIO Initrd、Initrd和RAMDisk Initrd。另外,我们的Root设备都是以设备文件的方式指定的,如果没有根文件系统,设备文件怎么可能存在呢?

2. VFS的挂载

接下来,Kernel_Start会去调用rest_init()并会去创建系统中的第一个进程Kernel_Init,并由其调用所有模块的初始化函数,其中ROOTFS的初始化函数也在这个期间被调用。

函数rest_init代码如下:

/*

* We need to finalize in a non-__init function or else race conditions

* between the root thread and the init thread may cause start_kernel to

* be reaped by free_initmem before the root thread has proceeded to

* cpu_idle.

*

* gcc-3.4 accidentally inlines this function, so use noinline.

*/

static noinline void __init_refok rest_init(void)

__releases(kernel_lock)

{

int pid;

kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

numa_default_policy();

pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);

unlock_kernel();

/*

* The boot idle thread must execute schedule()

* at least once to get things moving:

*/

init_idle_bootup_task(current);

rcu_scheduler_starting();

preempt_enable_no_resched();

schedule();

preempt_disable();

/* Call into cpu_idle with preempt disabled */

cpu_idle();

}

函数Kernel_Init代码如下:

static int __init kernel_init(void * unused)

{

lock_kernel();

/*

* init can run on any cpu.

*/

set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);

/*

* Tell the world that we're going to be the grim

* reaper of innocent orphaned children.

*

* We don't want people to have to make incorrect

* assumptions about where in the task array this

* can be found.

*/

init_pid_ns.child_reaper = current;

cad_pid = task_pid(current);

smp_prepare_cpus(setup_max_cpus);

do_pre_smp_initcalls();

start_boot_trace();

smp_init();

sched_init_smp();

cpuset_init_smp();

[1] do_basic_setup();

/*

* check if there is an early userspace init. If yes, let it do all

* the work

*/

[2] if (!ramdisk_execute_command)

ramdisk_execute_command = "/init";

[3] if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {

ramdisk_execute_command = NULL;

prepare_namespace();

}

/*

* Ok, we have completed the initial bootup, and

* we're essentially up and running. Get rid of the

* initmem segments and start the user-mode stuff..

*/

init_post();

return 0;

}

代码[1]:函数do_basic_setup()调用所有模块的初始化函数,包括initramfs的初始化函数populate_rootfs。这部分代码在init/initramfs.c下面,函数populate_rootfs通过如下方式导出:

rootfs_initcall(populate_rootfs);

代码[2]:ramdisk_execute_command值通过“rdinit=”指定,如果未指定,则采用默认的值/init。

代码[3]:检查根文件系统中是否存在文件ramdisk_execute_command,如果存在的话则执行init_post(),否则执行prepare_namespace()挂载根文件系统。

需要特别指出的是initramfs.c模块的入口函数populate_rootfs()是否执行取决于Kernel的编译选项。参照linux/init目录下的makefile文件,如下:

#

# Makefile for the linux kernel.

#

obj-y := main.o version.o mounts.o

ifneq ($(CONFIG_BLK_DEV_INITRD),y)

obj-y += noinitramfs.o

else

obj-$(CONFIG_BLK_DEV_INITRD) += initramfs.o

endif

obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o

mounts-y := do_mounts.o

mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o

mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o

mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o

主要完成Initrd的检测工作,检查出是CPIO Initrd还是Initramfs还是Image-Initrd还是需要在编译的时候做如下的配置(General setupàInitramfs/initrd support):

clip_image002

该函数的代码如下:

static int __init populate_rootfs(void)

{

[1] char *err = unpack_to_rootfs(__initramfs_start,

__initramfs_end - __initramfs_start, 0);

if (err)

panic(err);

[2] if (initrd_start) {

#ifdef CONFIG_BLK_DEV_RAM

int fd;

printk(KERN_INFO "checking if image is initramfs...");

[3] err = unpack_to_rootfs((char *)initrd_start,

initrd_end - initrd_start, 1);

if (!err) {

printk(" it is/n");

unpack_to_rootfs((char *)initrd_start,

initrd_end - initrd_start, 0);

free_initrd();

return 0;

}

printk("it isn't (%s); looks like an initrd/n", err);

[4] fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);

if (fd >= 0) {

[5] sys_write(fd, (char *)initrd_start,

initrd_end - initrd_start);

sys_close(fd);

[6] free_initrd();

}

#else

printk(KERN_INFO "Unpacking initramfs...");

[7] err = unpack_to_rootfs((char *)initrd_start,

initrd_end - initrd_start, 0);

if (err)

panic(err);

printk(" done/n");

free_initrd();

#endif

}

return 0;

}

代码[1]:unpack_to_rootfs顾名思义,就是解压包到rootfs,其具有两个功能,一个是检测是否是属于cpio包,另外一个就是解压cpio包,通过最后一个参数进行控制。1:检测,0:解压。其实,Initramfs也是压缩过后的CPIO文件。

资料中提到,Linux2.5中开始引入initramfs,在Linux2.6中一定存在,而且编译的时候通过连接脚本arch/arm/kernel/vmlinux.lds将其编译到__initramfs_start~__initramfs_end,执行完unpack_to_rootfs后将被拷贝到根目录。

代码[2]:判断是否加载了Initrd,无论对于那种格式的Initrd,即无论是CPIO-Initrd还是Image-Initrd,U-Boot都会将其拷贝到initrd_start。当然了,如果是initramfs的情况下,该值肯定为空了。

代码[3]:判断加载的是不是CPIO-Initrd。

通过在这里主要用于检测,如果是编译到Linux Kernel的CPIO Initrd,__initramfs_end - __initramfs_start应该是大于零的,否则为零,其实也就是通过这里来判断是否为CPIO Initrd。

代码[4]:如果不是CPIO-Initrd,则就是Image-Initrd,将其内容保存到文件/initrd.image中。在根文件系统中创建文件/initrd.image。

代码[5]:这里是对Image-Initrd提供支持的,将内存中的initrd赋值到initrd.image中,以释放内存空间。

代码[6]:释放Initrd所占用的内存空间。

另外,如果要支持Image-Initrd的话,必须要配置CONFIG_BLK_DEV_RAM,配置的方法上面已经讲过。

下面接着来分析函数kernel_init

static int __init kernel_init(void * unused)

{

do_basic_setup();

/*

* check if there is an early userspace init. If yes, let it do all

* the work

*/

if (!ramdisk_execute_command)

ramdisk_execute_command = "/init";

[1] if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {

ramdisk_execute_command = NULL;

prepare_namespace();

}

/*

* Ok, we have completed the initial bootup, and

* we're essentially up and running. Get rid of the

* initmem segments and start the user-mode stuff..

*/

init_post();

return 0;

}

代码[1]:前面在对函数populate_rootfs进行分析的时候已经知道,对于initramfs和cpio-initrd的情况,都会将文件系统(其实是一个VFS)解压到根文件系统。如果虚拟文件系统中存在ramdisk_execute_command指定的文件则直接转向init_post()来执行,否则执行函数prepare_namespace()。

3. 根文件系统的挂载

从上面的代码分析中知道,对于Image-Initrd或者VFS(即InitRamfs或者CPIO-Initrd)中不存在文件ramdisk_execute_command的情况,则执行prepare_namespace()。

接下来看一下函数prepare_namespace()的代码:

/*

* Prepare the namespace - decide what/where to mount, load ramdisks, etc.

*/

void __init prepare_namespace(void)

{

int is_floppy;

[1] if (root_delay) {

printk(KERN_INFO "Waiting %dsec before mounting root device.../n",

root_delay);

ssleep(root_delay);

}

/*

* wait for the known devices to complete their probing

*

* Note: this is a potential source of long boot delays.

* For example, it is not atypical to wait 5 seconds here

* for the touchpad of a laptop to initialize.

*/

[2] wait_for_device_probe();

md_run_setup();

[3] if (saved_root_name[0]) {

root_device_name = saved_root_name;

if (!strncmp(root_device_name, "mtd", 3) ||

!strncmp(root_device_name, "ubi", 3)) {

[4] mount_block_root(root_device_name, root_mountflags);

goto out;

}

[5] ROOT_DEV = name_to_dev_t(root_device_name);

if (strncmp(root_device_name, "/dev/", 5) == 0)

root_device_name += 5;

}

[6] if (initrd_load())

goto out;

[7] /* wait for any asynchronous scanning to complete */

if ((ROOT_DEV == 0) && root_wait) {

printk(KERN_INFO "Waiting for root device %s.../n",

saved_root_name);

while (driver_probe_done() != 0 ||

(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)

msleep(100);

async_synchronize_full();

}

is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;

if (is_floppy && rd_doload && rd_load_disk(0))

ROOT_DEV = Root_RAM0;

mount_root();

out:

[9] sys_mount(".", "/", NULL, MS_MOVE, NULL);

[10] sys_chroot(".");

}

代码[1]:资料中提到,对于将根文件系统存放到USB或者SCSI设备上的情况,Kernel需要等待这些耗费时间比较久的设备驱动加载完毕,所以这里存在一个Delay。

代码[2]:从字面的意思来看,这里也是来等待根文件系统所在的设备探测函数的完成。

代码[3]:参数saved_root_name存放的是Kernel参数root=所指定的设备文件,这点不再赘述,可以参照代码。

代码[4]:按照资料中的解释,这里相当于将saved_root_nam指定的设备进行加载。如下面传递给内核的command line:

CONFIG_CMDLINE="console=ttyS0,115200 mem=108M rdinit=/linuxrc root=/dev/mtdblock2"

实际上就是加载/dev/mtdblock2。

代码[5]:参数ROOT_DEV存放设备节点号。

代码[6]:挂载initrd,这里进行的操作相当的复杂,可以参照后续关于该函数的详细解释。

代码[7]:如果指定mount_initrd为true,即没有指定在函数initrd_load中mount的话,则在这里重新realfs的mount操作。

代码[9]:将挂载点从当前目录(实际当前的目录在mount_root中或者在mount_block_root中指定)移到根目录。对于上面的command line的话,当前的目录就是/dev/mtdblock2。

代码[10]:将当前目录当作系统的根目录,至此虚拟系统根目录文件系统切换到了实际的根目录文件系统。

接下来看一下函数initrd_load()的代码:

int __init initrd_load(void)

{

[1] if (mount_initrd) {

[2] create_dev("/dev/ram", Root_RAM0);

/*

* Load the initrd data into /dev/ram0. Execute it as initrd

* unless /dev/ram0 is supposed to be our actual root device,

* in that case the ram disk is just set up here, and gets

* mounted in the normal path.

*/

[3] if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {

sys_unlink("/initrd.image");

[4] handle_initrd();

return 1;

}

}

sys_unlink("/initrd.image");

return 0;

}

代码[1]:可以通过Kernel的参数“noinitrd“来配置mount_initrd的值,默认为1,很少看到有项目区配置该值,所以一般情况下,mount_initrd的值应该为1;

代码[2]:创建一个Root_RAM0的设备节点/dev/ram;

代码[3]:如果根文件设备号不是Root_RAM0则程序就会执行代码[4],换句话说,就是给内核指定的参数不是/dev/ram,例如上面指定的/dev/mtdblock2设备节点肯定就不是Root_RAM0。

另外这行代码还将文件initrd.image释放到节点/dev/ram0,也就是对应image-initrd的操作。

代码[4]:函数handle_initrd主要功能是执行Initrd中的linuxrc文件,并且将realfs的根目录设置为当前目录。其实前面也已经提到了,这些操作只对image-cpio的情况下才会去执行。

函数handle_initrd的代码如下:

static void __init handle_initrd(void)

{

int error;

int pid;

[1] real_root_dev = new_encode_dev(ROOT_DEV);

[2] create_dev("/dev/root.old", Root_RAM0);

/* mount initrd on rootfs' /root */

mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);

[3] sys_mkdir("/old", 0700);

root_fd = sys_open("/", 0, 0);

old_fd = sys_open("/old", 0, 0);

/* move initrd over / and chdir/chroot in initrd root */

[4] sys_chdir("/root");

sys_mount(".", "/", NULL, MS_MOVE, NULL);

sys_chroot(".");

/*

* In case that a resume from disk is carried out by linuxrc or one of

* its children, we need to tell the freezer not to wait for us.

*/

current->flags |= PF_FREEZER_SKIP;

[5] pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);

if (pid > 0)

while (pid != sys_wait4(-1, NULL, 0, NULL))

yield();

current->flags &= ~PF_FREEZER_SKIP;

/* move initrd to rootfs' /old */

sys_fchdir(old_fd);

sys_mount("/", ".", NULL, MS_MOVE, NULL);

/* switch root and cwd back to / of rootfs */

[6] sys_fchdir(root_fd);

sys_chroot(".");

sys_close(old_fd);

sys_close(root_fd);

[7] if (new_decode_dev(real_root_dev) == Root_RAM0) {

sys_chdir("/old");

return;

}

[8] ROOT_DEV = new_decode_dev(real_root_dev);

mount_root();

[9] printk(KERN_NOTICE "Trying to move old root to /initrd ... ");

error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);

if (!error)

printk("okay/n");

else {

int fd = sys_open("/dev/root.old", O_RDWR, 0);

if (error == -ENOENT)

printk("/initrd does not exist. Ignored./n");

else

printk("failed/n");

printk(KERN_NOTICE "Unmounting old root/n");

sys_umount("/old", MNT_DETACH);

printk(KERN_NOTICE "Trying to free ramdisk memory ... ");

if (fd < 0) {

error = fd;

} else {

error = sys_ioctl(fd, BLKFLSBUF, 0);

sys_close(fd);

}

printk(!error ? "okay/n" : "failed/n");

}

}

代码[1]:real_root_dev为一个全局变量,用来保存realfs的设备号。

代码[2]:调用mount_block_root将realfs加载到VFS的/root下。

代码[3]:提取rootfs的根文件描述符并将其保存到root_fd,资料中提及其用处就是在后续调用sys_chroot到initrd的文件系统后,处理完init请求后,还能够再次切回到rootfs,这一点在一份IBM官方有关cpio-initrd和image-initrd的执行流程图中可以看到,如下:

clip_image004

代码[4]:sys_chroot到initrd文件系统,前面已经挂载initrd到VFS的root目录下;

代码[5]:执行initrd中的linuxrc,并等待执行结束;

代码[6]:initrd执行结束后,切回到rootfs,不知道为什么直接用节点切呢?

代码[7]:如果real_root_dev直接配置为Root_RAM0,也即直接使用直接使用initrd作为realfs,改变当前目录到initrd中,并直接返回。

代码[8]:执行完Linuxrc后,realfs已经确定,则调用mount_root将realfs挂载到VFS的/root目录下,并将当前的目录配置为VFS的/root。

代码[9]:收尾的工作,例如释放内存等。

4. 真实根文件系统挂载后的操作

下面回过头来再看上面提到的init_post,该函数实际上是在Kernel_init中最后执行的函数。其代码如下:

/* This is a non __init function. Force it to be noinline otherwise gcc

* makes it inline to init() and it becomes part of init.text section

*/

static noinline int init_post(void)

{

/* need to finish all async __init code before freeing the memory */

async_synchronize_full();

free_initmem();

unlock_kernel();

mark_rodata_ro();

system_state = SYSTEM_RUNNING;

numa_default_policy();

if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)

printk(KERN_WARNING "Warning: unable to open an initial console./n");

(void) sys_dup(0);

(void) sys_dup(0);

current->signal->flags |= SIGNAL_UNKILLABLE;

if (ramdisk_execute_command) {

run_init_process(ramdisk_execute_command);

printk(KERN_WARNING "Failed to execute %s/n",

ramdisk_execute_command);

}

/*

* We try each of these until one succeeds.

*

* The Bourne shell can be used instead of init if we are

* trying to recover a really broken machine.

*/

if (execute_command) {

run_init_process(execute_command);

printk(KERN_WARNING "Failed to execute %s. Attempting "

"defaults.../n", execute_command);

}

run_init_process("/sbin/init");

run_init_process("/etc/init");

run_init_process("/bin/init");

run_init_process("/bin/sh");

panic("No init found. Try passing init= option to kernel.");

}

可以看到,在该函数的最后,以此会去搜索文件并执行ramdisk_execute_command、execute_command、/sbin/init、/etc/init、/bin/init和/bin/sh,如果发现这些文件均不存在的话,则通过panic输出错误命令,并将当前的系统Halt在那里。

四.RootFS加载过程流程图描述

详细的流程图如下:

clip_image006

(完)


[p1]之所以称之为“某一个文件”,是因为这里文件的名字因为操作系统的版本不同而不同


2019-01-04 16:45:46 yetaibing1990 阅读数 919
  • Linux应用软件服务篇-五剑客

    第一章节讲解主流的 Vsftp服务器如何通过服务端与客户端实现文件资源共享,讲解了Vsftp之间三种用户在不同的配置方法对不同的目录文件资源限制访问,达到更安全高效的资源共享数据传输。 第二章节讲解企业级NTP时间服务器对公司内网所有客户机及服务器批量实现时间同步,多个节点如何去快速同步主服务器时间。  第三章节讲解 NFS服务器实现与客户机磁盘文件的共享,通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,重点讲解了通过客户端远程挂载服务器磁盘共享文件及如何使用指定用户去访问指定的共享文件夹数据。 第四章节讲解samba服务器在企业中,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源,重点介绍了通过 samba配置文件权限配置去对匿名文件夹及指定用户文件夹共享资源服务。 第五章节介绍了去部署 DHCP服务器对批量客户端实现自动获取IP,通过配置文件IP池获取到IP形式,及绑定客户端Mac地址及指定IP给予客户端,从而获得IP方法。

    140 人正在学习 去看看 吴光科

Table of Contents

 

一、代码流程

二、相关数据结构

0.基本概念

1.进程控制块PCB

2.文件系统类型

3.文件系统挂载vfsmount

4.超级块(struct super_bloc)

5.目录索引节点(struct inode):

5.目录项对象(struct dentry):

6.file 结构体

7. 打开的文件集

8.文件查找相关的数据结构

三、注册/创建、安装/挂载rootfs

1.向内核注册rootfs虚拟文件系统init_rootfs

2.建立rootfs的根目录,并将rootfs挂载到自己的根目录


一、代码流程

在执行kernel_init之前,会建立roofs文件系统。(kernel_init启动用户空间的第一个进程init)

根文件系统的挂载会经过如下步骤:

  1. [1*]处设置了根目录的名字为“/”。
  2. [2*]处设置了vfsmount中的root目录
  3. [3*]处设置了vfsmount中的超级块
  4. [4*]处设置了vfsmount中的文件挂载点,指向了自己
  5. [5*]处设置了vfsmount中的父文件系统的vfsmount为自己
start_kernel
  vfs_caches_init
    mnt_init
      init_rootfs注册rootfs文件系统
      init_mount_tree 挂载rootfs文件系统
        vfs_kern_mount
          mount_fs
            type->mount其实是rootfs_mount 
              mount_nodev
                fill_super 其实是ramfs_fill_super
                  inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
                  sb->s_root = d_make_root(inode);
                    static const struct qstr name = QSTR_INIT("/", 1);[1*]
                    __d_alloc(root_inode->i_sb, &name);
          ...
          mnt->mnt.mnt_root = root;[2*]
          mnt->mnt.mnt_sb = root->d_sb;[3*]
          mnt->mnt_mountpoint = mnt->mnt.mnt_root;[4*]
          mnt->mnt_parent = mnt;[5*]
                 root.mnt = mnt;
        root.dentry = mnt->mnt_root;
        mnt->mnt_flags |= MNT_LOCKED;
        set_fs_pwd(current->fs, &root);
        set_fs_root(current->fs, &root);
  ...
  rest_init
    kernel_thread(kernel_init, NULL, CLONE_FS);

二、相关数据结构

0.基本概念

从本质上讲,文件系统是特殊的数据分层存储结构,它包含文件、目录和相关的控制信息。为了描述 这个结构,Linux引入了一些基本概念:

文件 一组在逻辑上具有完整意义的信息项的系列。在Linux中,除了普通文件,其他诸如目录、设备、套接字等 也以文件被对待。总之,“一切皆文件”。

目录 目录好比一个文件夹,用来容纳相关文件。因为目录可以包含子目录,所以目录是可以层层嵌套,形成 文件路径。在Linux中,目录也是以一种特殊文件被对待的,所以用于文件的操作同样也可以用在目录上。

目录项 在一个文件路径中,路径中的每一部分都被称为目录项;如路径/home/source/helloworld.c中,目录 /, home, source和文件 helloworld.c都是一个目录项。

索引节点 用于存储文件的元数据的一个数据结构。文件的元数据,也就是文件的相关信息,和文件本身是两个不同 的概念。它包含的是诸如文件的大小、拥有者、创建时间、磁盘位置等和文件相关的信息。

超级块 用于存储文件系统的控制信息的数据结构。描述文件系统的状态、文件系统类型、大小、区块数、索引节 点数等,存放于磁盘的特定扇区中。

如上的几个概念在磁盘中的位置关系如图所示。

1.进程控制块PCB

struct task_struct {  
      ......  
      struct thread_info *thread_info;  
      struct list_head tasks;  
      pid_t pid;  
      pid_t tgid;  
      uid_t uid,euid,suid,fsuid;  
      gid_t gid,egid,sgid,fsgid;  
      struct fs_struct *fs;  //本节将大量使用这个  
      struct files_struct *files;  
      ......  
}  

 

struct fs_struct {
	int users;
	spinlock_t lock;
	seqcount_t seq;
	int umask;
	int in_exec;
	struct path root, pwd;
};

2.文件系统类型

kernel/include/linux/fs.h

struct file_system_type {
	const char *name;
	int fs_flags;
#define FS_REQUIRES_DEV		1 
#define FS_BINARY_MOUNTDATA	2
#define FS_HAS_SUBTYPE		4
#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
#define FS_USERNS_DEV_MOUNT	16 /* A userns mount does not imply MNT_NODEV */
#define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
	struct dentry *(*mount) (struct file_system_type *, int,
		       const char *, void *);  //安装/挂载文件系统时,会调用;获取超级块。
	void (*kill_sb) (struct super_block *);   //卸载文件系统时会调用。
	struct module *owner;
	struct file_system_type * next;      //指向下一个文件系统类型。
	struct hlist_head fs_supers;      //同一个文件系统类型中所有超级块组成双向链表。 

	struct lock_class_key s_lock_key;
	struct lock_class_key s_umount_key;
	struct lock_class_key s_vfs_rename_key;
	struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];

	struct lock_class_key i_lock_key;
	struct lock_class_key i_mutex_key;
	struct lock_class_key i_mutex_dir_key;
};

3.文件系统挂载vfsmount

本质上,mount操作的过程就是新建一个vfsmount结构,然后将此结构和挂载点(目录项对象)关联。关联之后,目录查找时就能沿着vfsmount挂载点一级级向下查找文件了。对于每一个mount的文件系统,都由一个vfsmount实例来表示。

kernel/include/linux/mount.h


    struct vfsmount {  
      struct list_head mnt_hash; //内核通过哈希表对vfsmount进行管理  
      struct vfsmount *mnt_parent;  //指向父文件系统对应的vfsmount  
      struct dentry *mnt_mountpoint; //指向该文件系统挂载点对应的目录项对象dentry  
      struct dentry *mnt_root; //该文件系统对应的设备根目录dentry  
      struct super_block *mnt_sb; //指向该文件系统对应的超级块  
      struct list_head mnt_mounts;   
      struct list_head mnt_child;  //同一个父文件系统中的所有子文件系统通过该字段链接成双联表  
      int mnt_flags;  
      /* 4 bytes hole on 64bits arches */  
      const char *mnt_devname;  /* Name of device e.g. /dev/dsk/hda1 */  
      struct list_head mnt_list;  //所有已挂载文件系统的vfsmount结构通过该字段链接在一起  
      struct list_head mnt_expire;  /* link in fs-specific expiry list */  
      struct list_head mnt_share;   /* circular list of shared mounts */  
      struct list_head mnt_slave_list;/* list of slave mounts */  
      struct list_head mnt_slave;   /* slave list entry */  
      struct vfsmount *mnt_master;  /* slave is on master->mnt_slave_list */  
      struct mnt_namespace *mnt_ns; /* containing namespace */  
      int mnt_id;           /* mount identifier */  
      int mnt_group_id;     /* peer group identifier */  
      /* 
      * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount 
      * to let these frequently modified fields in a separate cache line 
      * (so that reads of mnt_flags wont ping-pong on SMP machines) 
      */  
      atomic_t mnt_count;  
      int mnt_expiry_mark;      /* true if marked for expiry */  
      int mnt_pinned;  
      int mnt_ghosts;  
      /* 
      * This value is not stable unless all of the mnt_writers[] spinlocks 
      * are held, and all mnt_writer[]s on this mount have 0 as their ->count 
      */  
      atomic_t __mnt_writers;  
    };  

4.超级块(struct super_bloc)

kernel/include/linux/fs.h

struct super_block {
	struct list_head	s_list;		/* 指向超级块链表的指针 */
	dev_t			s_dev;		/* search index; _not_ kdev_t */
	unsigned char		s_blocksize_bits;
	unsigned long		s_blocksize;
	loff_t			s_maxbytes;	/* Max file size */
	struct file_system_type	*s_type;       //文件系统类型
	const struct super_operations	*s_op;
	const struct dquot_operations	*dq_op;
	const struct quotactl_ops	*s_qcop;
	const struct export_operations *s_export_op;
	unsigned long		s_flags;
	unsigned long		s_magic;
	struct dentry		*s_root;
	struct rw_semaphore	s_umount;
	int			s_count;
	atomic_t		s_active;
#ifdef CONFIG_SECURITY
	void                    *s_security;
#endif
	const struct xattr_handler **s_xattr;

	struct list_head	s_inodes;	/* all inodes */
	struct hlist_bl_head	s_anon;		/* anonymous dentries for (nfs) exporting */
	struct list_head	s_mounts;	/* list of mounts; _not_ for fs use */
	struct block_device	*s_bdev;
	struct backing_dev_info *s_bdi;
	struct mtd_info		*s_mtd;
	struct hlist_node	s_instances;
	struct quota_info	s_dquot;	/* Diskquota specific options */

	struct sb_writers	s_writers;

	char s_id[32];				/* Informational name */
	u8 s_uuid[16];				/* UUID */

	void 			*s_fs_info;	/* Filesystem private info */
	unsigned int		s_max_links;
	fmode_t			s_mode;

	/* Granularity of c/m/atime in ns.
	   Cannot be worse than a second */
	u32		   s_time_gran;

	/*
	 * The next field is for VFS *only*. No filesystems have any business
	 * even looking at it. You had been warned.
	 */
	struct mutex s_vfs_rename_mutex;	/* Kludge */

	/*
	 * Filesystem subtype.  If non-empty the filesystem type field
	 * in /proc/mounts will be "type.subtype"
	 */
	char *s_subtype;

	/*
	 * Saved mount options for lazy filesystems using
	 * generic_show_options()
	 */
	char __rcu *s_options;
	const struct dentry_operations *s_d_op; /* default d_op for dentries */

	/*
	 * Saved pool identifier for cleancache (-1 means none)
	 */
	int cleancache_poolid;

	struct shrinker s_shrink;	/* per-sb shrinker handle */

	/* Number of inodes with nlink == 0 but still referenced */
	atomic_long_t s_remove_count;

	/* Being remounted read-only */
	int s_readonly_remount;

	/* AIO completions deferred from interrupt context */
	struct workqueue_struct *s_dio_done_wq;
	struct hlist_head s_pins;

	/*
	 * Keep the lru lists last in the structure so they always sit on their
	 * own individual cachelines.
	 */
	struct list_lru		s_dentry_lru ____cacheline_aligned_in_smp;
	struct list_lru		s_inode_lru ____cacheline_aligned_in_smp;
	struct rcu_head		rcu;

	/*
	 * Indicates how deep in a filesystem stack this SB is
	 */
	int s_stack_depth;
};

5.目录索引节点(struct inode):

文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。

kernel/include/linux/fs.h


    struct inode {  
      struct hlist_node i_hash; //哈希表节点  
      struct list_head  i_list;  
      struct list_head  i_sb_list;  
      struct list_head  i_dentry;  
      unsigned long     i_ino;  
      atomic_t      i_count;  
      unsigned int      i_nlink;  
      uid_t         i_uid;     //文件所有者
      gid_t         i_gid;      //文件所有者所属的用户组
      dev_t         i_rdev;  
      u64           i_version;  
      loff_t            i_size;  
    #ifdef __NEED_I_SIZE_ORDERED  
      seqcount_t        i_size_seqcount;  
    #endif  
      struct timespec       i_atime;  
      struct timespec       i_mtime;  //修改时间
      struct timespec       i_ctime;  //创建时间
      unsigned int      i_blkbits;  
      blkcnt_t      i_blocks;  
      unsigned short          i_bytes;  
      umode_t           i_mode;         //文件的读写权限
      spinlock_t        i_lock; /* i_blocks, i_bytes, maybe i_size */  
      struct mutex      i_mutex;  
      struct rw_semaphore   i_alloc_sem;  
      const struct inode_operations *i_op;  
      const struct file_operations  *i_fop; /* former ->i_op->default_file_ops */  
      struct super_block    *i_sb;  
      struct file_lock  *i_flock;  
      struct address_space  *i_mapping;  
      struct address_space  i_data;  
    #ifdef CONFIG_QUOTA  
      struct dquot      *i_dquot[MAXQUOTAS];  
    #endif  
      struct list_head  i_devices;  
      union {  
        struct pipe_inode_info  *i_pipe;  
        struct block_device *i_bdev;  
        struct cdev     *i_cdev;  
      };  
      int           i_cindex;  
      
      __u32         i_generation;  
      
    #ifdef CONFIG_DNOTIFY  
      unsigned long     i_dnotify_mask; /* Directory notify events */  
      struct dnotify_struct *i_dnotify; /* for directory notifications */  
    #endif  
      
    #ifdef CONFIG_INOTIFY  
      struct list_head  inotify_watches; /* watches on this inode */  
      struct mutex      inotify_mutex;  /* protects the watches list */  
    #endif  
      
      unsigned long     i_state;  
      unsigned long     dirtied_when;   /* jiffies of first dirtying */  
      
      unsigned int      i_flags;  
      
      atomic_t      i_writecount;  
    #ifdef CONFIG_SECURITY  
      void          *i_security;  
    #endif  
      void          *i_private; /* fs or device private pointer */  
    };  

5.目录项对象(struct dentry):

dentry的中文名称是目录项,是Linux文件系统中某个索引节点(inode)的链接。这个索引节点可以是文件,也可以是目录。

inode(可理解为ext2 inode)对应于物理磁盘上的具体对象,dentry是一个内存实体,其中的d_inode成员指向对应的inode。也就是说,一个inode可以在运行的时候链接多个dentry,而d_count记录了这个链接的数量。

kernel/include/linux/dcache.h


    struct dentry {  
      atomic_t d_count;     //一个inode可以在运行的时候链接多个dentry,而d_count记录了这个链接的数量
      unsigned int d_flags;     /* protected by d_lock */  
      spinlock_t d_lock;        /* per dentry lock */  
      int d_mounted;  
      struct inode *d_inode; //目录项对象与目录索引的关联          
      /* Where the name belongs to - NULL is 
      * negative */  
      /* 
      * The next three fields are touched by __d_lookup.  Place them here 
      * so they all fit in a cache line. 
      */  
      struct hlist_node d_hash; //哈希表节点 /* lookup hash list */  
      struct dentry *d_parent; //目录项对象的父亲   /* parent directory */  
      struct qstr d_name; //d_name.name这个是文件名,目录对象与目录名的关联  
      
      struct list_head d_lru;       /* LRU list */  
      /* 
      * d_child and d_rcu can share memory 
      */  
      union {  
        struct list_head d_child;   /* child of parent list */  
        struct rcu_head d_rcu;  
      } d_u;  
      struct list_head d_subdirs;   /* our children */  
      struct list_head d_alias; /* inode alias list */  
      unsigned long d_time;     /* used by d_revalidate */  
      struct dentry_operations *d_op;  
      struct super_block *d_sb; //指向文件系统的超级块/* The root of the dentry tree */  
      void *d_fsdata;           /* fs-specific data */  
      
      unsigned char d_iname[DNAME_INLINE_LEN_MIN];  /* small names */  
    };  

6.file 结构体

struct file(file结构体):
  struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。


    struct file {  
      /* 
      * fu_list becomes invalid after file_free is called and queued via 
      * fu_rcuhead for RCU freeing 
      */  
      union {  
        struct list_head    fu_list;  
        struct rcu_head     fu_rcuhead;  
      } f_u;  
      struct path       f_path;  //重要!!!记录挂载信息和目录项信息  
    #define f_dentry    f_path.dentry  
    #define f_vfsmnt    f_path.mnt  
      const struct file_operations  *f_op;  
      atomic_long_t     f_count;  
      unsigned int      f_flags;  
      fmode_t           f_mode;  
      loff_t            f_pos;  
      struct fown_struct    f_owner;  
      const struct cred *f_cred;  
      struct file_ra_state  f_ra;  
      
      u64           f_version;  
    #ifdef CONFIG_SECURITY  
      void          *f_security;  
    #endif  
      /* needed for tty driver, and maybe others */  
      void          *private_data;  
      
    #ifdef CONFIG_EPOLL  
      /* Used by fs/eventpoll.c to link all the hooks to this file */  
      struct list_head  f_ep_links;  
      spinlock_t        f_ep_lock;  
    #endif /* #ifdef CONFIG_EPOLL */  
      struct address_space  *f_mapping;  
    #ifdef CONFIG_DEBUG_WRITECOUNT  
      unsigned long f_mnt_write_state;  
    #endif  
    };  

每个进程在PCB(Process Control Block)即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指

向已打开文件的指针,现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。

我们在进程中打开一个文件F,实际上就是要在内存中建立F的dentry,和inode结构,并让它们与进程结构联系来,把VFS中定义的接口给接起来。我们来看一看这个经典的图:

file结构体详解

7. 打开的文件集

struct files_struct {//打开的文件集
         atomic_t count;              /*结构的使用计数*/
        ……
         int max_fds;                 /*文件对象数的上限*/
        int max_fdset;               /*文件描述符的上限*/
        int next_fd;                 /*下一个文件描述符*/
        struct file ** fd;           /*全部文件对象数组*/
        ……
 };

struct fs_struct {//建立进程与文件系统的关系
         atomic_t count;              /*结构的使用计数*/
        rwlock_t lock;               /*保护该结构体的锁*/
        int umask;                  /*默认的文件访问权限*/
        struct dentry * root;        /*根目录的目录项对象*/
        struct dentry * pwd;         /*当前工作目录的目录项对象*/
        struct dentry * altroot;    /*可供选择的根目录的目录项对象*/
        struct vfsmount * rootmnt;   /*根目录的安装点对象*/
        struct vfsmount * pwdmnt;    /*pwd的安装点对象*/
        struct vfsmount * altrootmnt;/*可供选择的根目录的安装点对象*/
};

回顾上节的图片很容易理解这两个数据结构

8.文件查找相关的数据结构

include/linux/fs_struct.h


    struct fs_struct {  
      atomic_t count;  
      rwlock_t lock;  
      int umask;  
      struct path root, pwd; //重要!!!记录挂载信息和目录项信息  
    };  

include/linux/namei.h


    struct nameidata {  
      struct path   path;  //重要!!!记录挂载信息和目录项信息  
      struct qstr   last;  //重要!!!记录目录名  
      unsigned int  flags;  
      int       last_type;  
      unsigned  depth;  
      char *saved_names[MAX_NESTED_LINKS + 1];  
      
      /* Intent data */  
      union {  
        struct open_intent open;  
      } intent;  
    };  

include/linux/path.h


    struct path {  
      struct vfsmount *mnt; //重要!!!记录文件系统挂载信息  
      struct dentry *dentry;  //重要!!!记录目录项信息  
    };  

include/linux/dcache.h

 struct qstr {  
  unsigned int hash;  
  unsigned int len;  
  const unsigned char *name;//重要!!!目录/文件名字,如"/","tank1"等具体的文件名  
}; 

三、注册/创建、安装/挂载rootfs

第一步:建立rootfs文件系统;

第二步:调用其get_sb函数(对于rootfs这种内存/伪文件系统是get_sb_nodev,实际文件系统比如ext2等是get_sb_bdev)、建立超级块(包含目录项和i节点);

第三步:挂载该文件系统(该文件系统的挂载点指向该文件系统超级块的根目录项);

第四步:将系统current的根文件系统和根目录设置为rootfs和其根目录。

kernel/init/main.c


    asmlinkage void __init start_kernel(void)  
    {  
      setup_arch(&command_line);//解析uboot命令行,实际文件系统挂载需要  
      parse_args("Booting kernel", static_command_line, __start___param,  
               __stop___param - __start___param,  
               &unknown_bootoption);  
      vfs_caches_init(num_physpages);  
    }  


kernel/fs/dcache.c


    void __init vfs_caches_init(unsigned long mempages)  
    {  
      mnt_init();  
      bdev_cache_init(); //块设备文件创建  
      chrdev_init();//字符设备文件创建  
    }  

kernel/fs/namespace.c

 void __init mnt_init(void)  
{  
  init_rootfs(); //向内核注册rootfs  
  init_mount_tree();//重要!!!rootfs根目录的建立以及rootfs文件系统的挂载;设置系统current根目录和根文件系统为rootfs  
} 

1.向内核注册rootfs虚拟文件系统init_rootfs

kernel/fs/ramfs/inode.c


    int __init init_rootfs(void)  
    {  
      err = register_filesystem(&rootfs_fs_type);  
    }  
    static struct file_system_type rootfs_fs_type = {  
      .name     = "rootfs",  
      .get_sb       = rootfs_get_sb,  
      .kill_sb  = kill_litter_super,  
    };  

2.建立rootfs的根目录,并将rootfs挂载到自己的根目录

kernel/fs/namespace.c



    static void __init init_mount_tree(void)  
    {  
      struct vfsmount *mnt;  
      struct mnt_namespace *ns;  
      struct path root;  
      //创建rootfs的vfsmount结构,建立rootfs的超级块、并将rootfs挂载到自己的根目录。  
      /* 
      mnt->mnt_mountpoint = mnt->mnt_root = dget(sb->s_root),而该mnt和自己的sb是关联的; 
      所以,是把rootfs文件系统挂载到了自己对应的超级块的根目录上。 
      这里也是实现的关键:一般文件系统的挂载是调用do_mount->do_new_mount而该函数中首先调用do_kern_mount,这时mnt->mnt_mountpoint = mnt->mnt_root;但后边 
      它还会调用do_add_mount->graft_tree->attach_recursive_mnt如下代码mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt)改变了其挂载点!!! 
      */  
      mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);  
      list_add(&mnt->mnt_list, &ns->list);  
      ns->root = mnt; //将创建好的mnt加入系统当前  
      mnt->mnt_ns = ns;  
      
      init_task.nsproxy->mnt_ns = ns; //设置进程的命名空间  
      get_mnt_ns(ns);  
      
      root.mnt = ns->root; //文件系统为rootfs,相当与root.mnt = mnt;  
      root.dentry = ns->root->mnt_root;//目录项为根目录项,相当与root.dentry = mnt->mnt_root;  
      
      //设置系统current的pwd目录和文件系统  
      set_fs_pwd(current->fs, &root);  
      //设置系统current根目录,根文件系统。这个是关键!!!整个内核代码最多只有两处调用  
      set_fs_root(current->fs, &root);    
    }  

 

2008-09-06 15:57:50 iteye_10416 阅读数 70
  • Linux应用软件服务篇-五剑客

    第一章节讲解主流的 Vsftp服务器如何通过服务端与客户端实现文件资源共享,讲解了Vsftp之间三种用户在不同的配置方法对不同的目录文件资源限制访问,达到更安全高效的资源共享数据传输。 第二章节讲解企业级NTP时间服务器对公司内网所有客户机及服务器批量实现时间同步,多个节点如何去快速同步主服务器时间。  第三章节讲解 NFS服务器实现与客户机磁盘文件的共享,通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,重点讲解了通过客户端远程挂载服务器磁盘共享文件及如何使用指定用户去访问指定的共享文件夹数据。 第四章节讲解samba服务器在企业中,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源,重点介绍了通过 samba配置文件权限配置去对匿名文件夹及指定用户文件夹共享资源服务。 第五章节介绍了去部署 DHCP服务器对批量客户端实现自动获取IP,通过配置文件IP池获取到IP形式,及绑定客户端Mac地址及指定IP给予客户端,从而获得IP方法。

    140 人正在学习 去看看 吴光科
转自:[url]http://13233.blog.51cto.com/3233/82680[/url]
[b]摘要:[/b]
本文对新增硬盘,切割硬盘,创建硬盘分区,为硬盘分区创建文件系统,以及加载文件系统的流程做总结性论述;
主要是为初学者弄清楚这一操作过程;
本文涉及fdisk、mkfs、mount ... ... 等工具;
对/etc/fstab 进行了解说;
还有磁盘扫描工具fsck 等介绍;
如果您想加载一个分区(文件系统),首先您得确认文件系统的类型,然后才能挂载使用,比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载;
如果您想添加一个新的分区,或者增加一个新的硬盘,您要通过分区工具来添加分区,然后要创建分区的文件系统,然后才是挂载文件系统;比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载。

[b]一、对存储设备的分区[/b]
我们这里所指的存储设备主要是本地硬盘、移动硬盘(比如USB 和1394接口的硬盘);由于磁盘很大并且为了满足我们各种需要,所以把硬盘分成若干个分区;
在 Linux中进行硬盘分区操作的工具有:
fdisk ,目前看来也是最好用的分区工具;
parted 和cfdisk在某一方面有点优点,如 parted中的数据备份功能;
推荐您用 fdisk 分区工具;

[b]二、存储设备进行格式化,即建立文件系统的过程;[/b]
1、文件系统的一点介绍
对存储设备分区还是远远不够的,我们还要对这些新增分区进行格式化;一个分区只有建立了某种文件系统后,这个分区才能使用;建立文件系统过程,就是用相应格式化工具格式化分区的过程;
在Linux操作系统中,目前几乎支持目前主流的文件系统,比如NTFS(只读)、FAT(可读可写)、ext2、ext3、reiserfs、hfs (MAC 操作系统的文件系统)、swap 交换分区... ... 还有一些不熟悉的操作系统的文件系统等;
在Linux中,我们常用的文件系统无非是上面例出的这些;如果您新增了一个硬盘,可能想格式化成 Linux的文件系统,最佳选择是 reiserfs 或ext3;
ext2的使用风险比较大;
速度最快的文件系统,当属reiserfs;reiserfs 还有很多优点,比如更安全;
ext3是Redhat认为最好的文件系统;
2、格式化工具介绍和使用;
我们常用的工具mkfs mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mkswap
提示:如果您不能创建reiserfs 文件系统,也就是说没有mkfs.reiserfs 或者mkreiserfs 命令
1)mkfs的使用;
使用方法:
# mkfs -t 文件系统 存储设备
注:
这里的文件系统是要指定的,比如 ext3 ;reiserfs ;ext2 ;fat32 ;msdos 等... ...
设备比如是一个硬盘的分区,软盘,光驱等.. ...
在格式化分区之前,您得懂得如何查看硬盘分区情况,并有针对性的格式化;比如用 fdisk -l 来查看;
比如我想格式化一个移动U盘中的一个分区;应该是:
# fdisk -l
Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 765 6144831 7 HPFS/NTFS
/dev/hda2 766 2805 16386300 c W95 FAT32 (LBA)
/dev/hda3 2806 9729 55617030 5 Extended
/dev/hda5 2806 3825 8193118+ 83 Linux
/dev/hda6 3826 5100 10241406 83 Linux
/dev/hda7 5101 5198 787153+ 82 Linux swap / Solaris
/dev/hda8 5199 6657 11719386 83 Linux
/dev/hda9 6658 7751 8787523+ 83 Linux
/dev/hda10 7752 9729 15888253+ 83 Linux
Disk /dev/sda: 1035 MB, 1035730944 bytes
256 heads, 63 sectors/track, 125 cylinders
Units = cylinders of 16128 * 512 = 8257536 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 25 201568+ 83 Linux
/dev/sda2 26 125 806400 5 Extended
/dev/sda5 26 50 201568+ 83 Linux
/dev/sda6 51 76 200781 83 Linux
sda这个设备是移动U盘,所以可以用 fdisk -l /dev/sda专门来显示他的分区情况;
格式化 /dev/sda6 分区为 ext3文件系统,则为:
# mkfs -t ext3 /dev/sda6
mke2fs 1.37 (21-Mar-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
50200 inodes, 200780 blocks
10039 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
25 block groups
8192 blocks per group, 8192 fragments per group
2008 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: 注:在这里直接回车;
done
This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
这样就格式化好了,sda6现在就是ext3文件系统了;我们就可以用mount 加载这个分区,然后使用这个文件系统;
# mkdir /mnt/sda6
# chmod 777 /mnt/sda6
# mount /dev/sda6 /mnt/sda6
当然您也可以把分区格式化成其它的文件系统;比如我们把 /dev/sda6格式化为ext3 、ext2、reiserfs、fat32、msdos 文件系统,命令格式如下;
# mkfs -t ext3 /dev/sda6
# mkfs -t ext2 /dev/sda6
# mkfs -t reiserfs /dev/sda6
# mkfs -t fat32 /dev/sda6
# mkfs -t msdos /dev/sda6
... ...

2)mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mke2fs 的介绍;
mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkdosfs mkfs.msdos mkfs.vfat ,其实mkfs 在执行的命令的时候,也是调用的这些工具;
通过文件名,我们就知道这些工具是支持什么文件系统;这些命令为我们提供了更多的方便;

# mkfs.ext3 /dev/sda6 注:把该设备格式化成ext3文件系统
# mke2fs -j /dev/sda6 注:把该设备格式化成ext3文件系统
# mkfs.ext2 /dev/sda6 注:把该设备格式化成ext2文件系统
root@localhost]# mke2fs /dev/sda6 注:把该设备格式化成ext2文件系统
# mkfs.reiserfs /dev/sda6 注:把该设备格式化成reiserfs文件系统
# mkfs.vfat /dev/sda6 注:把该设备格式化成fat32文件系统
# mkfs.msdos /dev/sda6 注:把该设备格式化成fat16文件系统,msdos文件系统就是fat16;
# mkdosfs /dev/sda6 注:把该设备格式化成fat16文件系统,同mkfs.msdos
... ...

2)mkswap 把一个分区格式化成为swap交换区;
# mkswap /dev/sda6 注:创建此分区为swap 交换分区
# swapon /dev/sda6 注:加载交换分区;
# swapoff /dev/sda6 注:关闭交换分区;

查看系统已经加载的swap交换分区;
# swapon /dev/sda6 注:加载交换分区;
# swapon -s
Filename Type Size Used Priority
/dev/hda7 partition 787144 0 -1
/dev/sda6 partition 225144 0 -3

如果让swap开机就加载,应该改 /etc/fstab文件,加类似如下一行;
/dev/sda6 swap swap defaults 0 0 注:把此行中的/dev/hda7 改为您的交换分区就行;
或者把命令行直接写入 /etc/rc.d/rc.local中也行;
swapon /dev/sda6
如果您的硬盘不能再分区,您可以创建一个swap文件
# dd if=/dev/zero of=/tmp/swap bs=1024 count=524288 注:创建一个大小为512M 的swap 文件,在/tmp目录中;您可以根据自己的需要的大小来创建swap 文件;
读入了 524288+0 个块
输出了 524288+0 个块
# mkswap /tmp/swap 注:把/tmp/swap 文件,创建成swap 交换区
Setting up swapspace version 1, size = 536866 kB
no label, UUID=d9d8645d-92cb-4d33-b36e-075bb0a2e278
# swapon /tmp/swap 注:挂载swap
# swapon -s
Filename Type Size Used Priority
/dev/hda7 partition 787144 888 -1
/tmp/swap file 524280 0 -2
注意:其实我们在安装系统的时候,就已经划分了交换分区;查看/etc/fstab,应该swap的行;如果您在安装系统时没有添加swap,可以通过这种办法来添加;

[b]三、挂载文件系统;[/b]
挂载文件系统,目前有两种方法,一是通过 mount 来挂载,另一种方法是通过/etc/fstab文件来开机自动挂载;
1、通过mount 来挂载磁盘分区(或存储设备)
mount的用法其实也简单,我们说几个常用的;
挂载文件系统的命令格式:
# mount [-t 文件系统 ] [-o 选项] 设备 目录

注:
-t 通过这个参数,我们来指定文件系统的类型,一般的情况下不必指定有时也能识加,-t 后面跟 ext3 、ext2 、reiserfs、vfat 、ntfs 等,其中 vfat 是fat32和fat16分区文件系统所所用的参数;如果您忘记了文件系统,也可以在-t 后面加auto ;
-o 这个选项,主要选项有权限、用户、磁盘限额、语言编码等,但语言编码的选项,大多用于vfat和ntfs文件系统;
由于选项太多,还是请您看看 man mount ;
设备 指存储设备,比如/dev/hda1, /dev/sda1 ,cdrom 等...至于您的系统中有哪些存储设备,主要通过 fdisk -l 或者查看 /etc/fstab 或 dmesg ;一般的情况下光驱设备是/dev/cdrom ;软驱设备是/dev/fd0 ;硬盘及移动硬盘以 fdisk -l 的输出为准;
1) 对光驱和软驱的挂载;
# mount /dev/cdrom
# mount /dev/fd0
第一行是mount 光驱,至于mount 到哪了,我们可以通过查看 /etc/fstab来查看;同理软驱/dev/fd0设备也是如此;比如我们在/etc/fstab
/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0
我们可以肯定的是光盘被mount 到了 /media/cdrecorder 目录;
但我们也可以自己来指定cdrom 挂载的位置 ;比如 /mnt/cdrom ,所以我们也可以这样来挂载光驱;
#mkdir /mnt/cdrom
#mount /dev/cdrom /mnt/cdrom

有时我们的设备是COMBO的,有支持dvd cd 还能支持刻录的;我们最好查一下光驱设备的,主要有两个方法,一是通过查看 /etc/fstab ,二是通过ls -l 来查看;比如我们在/etc/fstab中查看到类似下面的一行;
/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0
通过这个,我们能知道hdc 就是cdrom 也是dvdrom的设备 ,更是 cdrecorder的设备;为了验证我们的说法;请用ls -l 来列文件;
# ls -lh /dev/dvd*
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/dvd -> hdc
# ls -lh /dev/cdrom
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/cdrom -> hdc
# ls -lh /dev/cdwriter
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/cdwriter -> hdc
dvd 、cdrom 、cdwriter 的文件名都链接到了hdc这个设备,所以光驱设备根源就是/dev/hdc ;所以我们也可以这样挂载光驱;
# mkdir /mnt/cdrom
# mount /dev/hdc /mnt/cdrom

2)挂载硬盘和移动硬盘的文件系统;
一个分区只有创建了文件系统后才能使用,前面我们说过了,我们在Linux大多用的是ext2 、ext3、reiserfs、fat32、msdos 、ntfs等;
[1]挂载Linux文件系统;
对于ext2 、ext3 、reiserfs 不需要指定文件系统的编码,其实mount 也没有这个功能;这些Linux文件系统,如果出现编码问题,一般是通过export LANG来指定;所以挂载这些文件系统比较简单;
首先我们得建一个文件系统挂载的目录;我们前面已经提到了;一个有文件系统的分区要挂到系统中,必须要有一个挂载点;这个挂载点就是一个目录;比如我们通过fdisk -l 得知hda5 是Linux分区,并且创建了文件系统,比如是reiserfs 文件系统吧;
# fdisk -l /dev/hda
Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 765 6144831 7 HPFS/NTFS
/dev/hda2 766 2805 16386300 c W95 FAT32 (LBA)
/dev/hda3 2806 9729 55617030 5 Extended
/dev/hda5 2806 3825 8193118+ 83 Linux
/dev/hda6 3826 5100 10241406 83 Linux
/dev/hda7 5101 5198 787153+ 82 Linux swap / Solaris
/dev/hda8 5199 6657 11719386 83 Linux
/dev/hda9 6658 7751 8787523+ 83 Linux
/dev/hda10 7752 9729 15888253+ 83 Linux

# mkdir /mnt/hda5/ 注:先创建一个挂载目录;
# chmod 777 /mnt/hda5/ 注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;
# mount -t reiserfs /dev/hda5 /mnt/hda5 注:通过-t reiserfs 来指定/dev/hda5是reiserfs 文件系统, 并且挂载到/mnt/hda5目录;
# mount -t auto /dev/hda5 /mnt/hda5 注:假如我们不知道hda5上reiserfs 文件系统,我们可以用 -t auto 让系统定夺,然后挂载到/mnt/hda5 ;
# mount /dev/hda5 /mnt/hda5 注:不加任何参数,直接 mount /dev/hda5 到/mnt/hda5;系统自动判断分区文件系统;
是不是被挂载了,我们通过df -lh 来查看;
# df -lh
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
/dev/hda5 7.9G 5.8G 2.1G 74% /mnt/hda5

[2]挂载Windows文件系统;
略,相对于linux文件系统挂接来说,windows文件系统的挂接类同;
2) 卸载文件系统umount ;
命令用法:
# umount 设备或挂载目录
举例:
# mount -t auto /dev/hda5 /mnt/hda5 注:挂载/dev/hda5;
# df -lh 注:查看/dev/hda5是否被挂载;
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
/dev/hda5 7.9G 5.8G 2.1G 74% /mnt/hda5
# umount /dev/hda5 注:卸载/dev/hda5
# df -lh 注:看是否卸载了/dev/hda5;
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
#umount /dev/cdrom 注:卸载cdrom ;
#umount /dev/fd0 注:卸载软驱;
... ...
再说一个查看分区是否被挂载了的命令,直接用 mount -s
# mount -s

2、通过/etc/fstab文件来开机自动挂载文件系统
1)理解fstab
上面我们说了mount挂载存储设备文件系统的办法;现在我们再来说一说在/etc/fstab 中实现开机自动挂载文件系统的办法;首先我们要查看 /etc/fstab ;主要看他的规划写法;
# This file is edited by fstab-sync - see 'man fstab-sync' for details
LABEL=/1 / ext3 defaults 1 1
/dev/devpts /dev/pts devpts gid=5,mode=620 0 0
/dev/shm /dev/shm tmpfs defaults 0 0
/dev/proc /proc proc defaults 0 0
/dev/sys /sys sysfs defaults 0 0
LABEL=SWAP-hda7 swap swap defaults 0 0
/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0
第一字段:设备名,在这里表示是文件系统; 有时我们把挂载文件系统也说成挂载分区; 在这个字段中也可以用分区标签;在例子中/LABEL=/1就是linux系统安装分区的标签,至于是在哪个分区,可以用 df -lh 来查看;
# df -lh
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
我们可以知道 LABEL=/1是/dev/hda8的标签;那我们用什么命令来创建硬盘分区的标签呢?
对于ext3和ext2文件系统,我们可以用 e2label 来设置
e2label device [newlabel] 创建设备的标签命令
比如我们想把文件系统为ext3 的分区/dev/hda5的标签设备为 /5 ,我们应该执行如下的命令:
# e2label /dev/hda5 /5
# mkdir /mnt/hda5 注:创建挂载/dev/hda5分区的目录;
# chmod 777 /mnt/hda5 注:打开权限,所有用户可读可写可执行;
然后我们要改/etc/fstab 中加一行
/5 /mnt/hda5 ext3 defaults 0 0
警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试;
如果是reiserfs文件系统,我们应该用
# reiserfstune -l 标签 设备
举例:比如我为reiserfs 文件系统 /dev/hda10设置标签为 /10 ;
# reiserfstune -l /10 /dev/hda10
我们在/etc/fstab中加入一行;
/10 /mnt/hda10 reiserfs defaults 0 0

警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试;
第二字段:文件系统的挂载点;
第三字段:文件系统类型;
第四字段:mount 命令的选项,和mount 中的-o 同理;defaults包括这些选项 rw, suid, dev, exec, auto, nouser, async;通过实践,这个默认的还能满足我们的需要;
第五字段:表示文件系统是否需要dump 备份,是真假关系;1是需要,0 是不需要;
第六字段: 是否在系统启动时,通过fsck磁盘检测工具来检查文件系统,1是需要,0是不需要,2是跳过;
基于这些认识;比如我们要开机自动挂载/dev/hda5 ;我们可以如下做;
# mkdir /mnt/hda5/ 注:先创建一个挂载目录;
# chmod 777 /mnt/hda5/ 注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;
然后我们在/etc/fstab 中加如下的一行;
/dev/hda5 /mnt/hda5 reiserfs defaults 0 0
这样重启机器就能看到效果了;

[b]四、对文件系统进行扫描fsck[/b]
类似于Windows中的scandisk,在Linux中就有类似这样的工具fsck,不过fsck 可不仅仅是扫描,还能修正文件系统的一些问题。值得注意的是fsck 扫描文件系统时一定要在单用户模式、修复模式或把设备umount后进行。
警告:如果扫描正在运行中的系统,会造成系统文件损坏;如果您的系统是正常,请不要用扫描工具,她可能会把您的系统搞坏掉,fsck运行是有危险的;
文件系统扫描工具有 fsck fsck.ext2 fsck.jfs fsck.msdos fsck.vfat fsck.ext3 fsck.reiserfs(reiserfsck)
其中fsck 默认支持文件系统ext2,如果想支持ext3文件系统的扫描,应该加-j 参数,最好是我们应该根据不同的文件系统来调用不同的扫描工具,比如 fsck.ext2,fsck.jfs,fsck.msdos,fsck.ext3,fsck.reiserfs(reiserfsck)等。我们也可以根据自己的文件系统选择不同的扫描工具;
举例:扫描/dev/hda10分区(基于reiserfs文件系统 );
# fsck.reiserfs /dev/hda10
reiserfsck 3.6.19 (2003 www.namesys.com)
*************************************************************
** If you are using the latest reiserfsprogs and it fails **
** please email bug reports to reiserfs-list@namesys.com, **
** providing as much information as possible -- your **
** hardware, kernel, patches, settings, all reiserfsck **
** messages (including version), the reiserfsck logfile, **
** check the syslog file for any related information. **
** If you would like advice on using this program, support **
** is available for $25 at www.namesys.com/support.html. **
*************************************************************
Will read-only check consistency of the filesystem on /dev/hda10
Will put log info to 'stdout'
Do you want to run this program?[N/Yes] (note need to type Yes if you do):Yes
###########
reiserfsck --check started at Wed Sep 14 08:54:17 2005
###########
Replaying journal..
Reiserfs journal '/dev/hda10' in blocks [18..8211]: 0 transactions replayed
Checking internal tree..finished
Comparing bitmaps..finished
Checking Semantic tree:
finished
No corruptions found 注:没有发现错误;
There are on the filesystem:
Leaves 2046
Internal nodes 15
Directories 130
Other files 2305
Data block pointers 1863657 (70565 of them are zero)
Safe links 0
###########
reiserfsck finished at Wed Sep 14 08:54:33 2005
###########
对于fsck.ext2和fsck.ext3常用的几个选项:
-p Automatic repair (no questions) 注:自动修复文件系统存在的问题;
-y Assume "yes" to all questions 注:如果文件系统有问题,会跳出提示是否修复,如果修复请按y;
-c Check for bad blocks and add them to the badblock list 注:对文件系统进行坏块检查;这是一个极为漫长的过程;
-n Make no changes to the filesystem 注:不对文件系统做任何改变,只要扫描,以检测是否有问题;
举例:比如 /dev/hda6 (文件系统是ext3的),我想扫描并自动修复;
# fsck.ext3 -p /dev/hda6
注意: 针对不同文件系统,最好用相应的工具;虽然有时fsck 在不加参数的情况下能识别不同的文件系统;
对于不同工具的最为详细的参数,请参看--help或者man;
补充:Fedora Core 4.0 默认安装不支持创建reiserfs 文件系统,解决办法是安装reiserfs-utils ,这也是需要的。
2008-03-08 09:44:00 edzjx 阅读数 544
  • Linux应用软件服务篇-五剑客

    第一章节讲解主流的 Vsftp服务器如何通过服务端与客户端实现文件资源共享,讲解了Vsftp之间三种用户在不同的配置方法对不同的目录文件资源限制访问,达到更安全高效的资源共享数据传输。 第二章节讲解企业级NTP时间服务器对公司内网所有客户机及服务器批量实现时间同步,多个节点如何去快速同步主服务器时间。  第三章节讲解 NFS服务器实现与客户机磁盘文件的共享,通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,重点讲解了通过客户端远程挂载服务器磁盘共享文件及如何使用指定用户去访问指定的共享文件夹数据。 第四章节讲解samba服务器在企业中,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源,重点介绍了通过 samba配置文件权限配置去对匿名文件夹及指定用户文件夹共享资源服务。 第五章节介绍了去部署 DHCP服务器对批量客户端实现自动获取IP,通过配置文件IP池获取到IP形式,及绑定客户端Mac地址及指定IP给予客户端,从而获得IP方法。

    140 人正在学习 去看看 吴光科
 

Linux 创建文件系统及挂载文件系统流程详解

作者:北南南北
来自: LinuxSir.Org
摘要:本文对新增硬盘,切割硬盘,创建硬盘分区,为硬盘分区创建文件系统,以及加载文件系统的流程做总结性论述;主要是为初学者弄清楚这一操作过程;本文 涉及fdisk、mkfs、mount ... ... 等工具;对/etc/fstab 进行了解说;还有磁盘扫描工具fsck 等介绍;
++++++++++++++++++++++++++++++++++++++++++++++++++++++
正文
++++++++++++++++++++++++++++++++++++++++++++++++++++++

阅读此文,必须具备知识点:
《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》
《实例解说 fdisk 使用方法》
《合理规划您的硬盘分区》
《Fedora / Redhat 软件包管理指南》 如果您想加载一个分区(文件系统),首先您得确认文件系统的类型,然后才能挂载使用,比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载;
如果您想添加一个新的分区,或者增加一个新的硬盘,您要通过分区工具来添加分区,然后要创建分区的文件系统,然后才是挂载文件系统;比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载; 本文总有一部份是您想要的;比如在新的分区上创建文件系统,如何挂载; 如何卸载文件系统或者设备(比如cdrom )等;我建您最好通读本文,然后根据自己的需要再做选择性实践; Linux的一个小问题涉及的很多方面的知识,有时一篇文档是难以说清楚;我为了尽可能详细解说每一个过程,所以把分区工具、创建文件系统工具、查看文件 系统的工具分开来说,主要是让初学者比较容易理解。希望您能理解本人的用心;传说北南长的比较丑,但心的还是善良的 ... ...我是不会用一些垃圾文档来害您 ... ... 哈哈 ... ... 言归正传,开文~~~~
一、对存储设备的分区;
我们这里所指的存储设备主要是本地硬盘、移动硬盘(比如USB 和1394接口的硬盘);由于磁盘很大并且为了满足我们各种需要,所以把硬盘分成若干个分区;比如我们可以用这个分区来安装Linux系统,那个分区用来 安装Windows系统... ... ;这点小事大家都明白; 至于如何在 Linux中进行硬盘分区操作,我们推荐您用 fdisk ,目前看来也是最好用的分区工具;其它工具比如parted 和cfdisk在某一方面有点优点,但这些优点可能为大家带来一些方便 ,比如 parted中的数据备份功能,这个功能对老手来说可能是优点,但对新手来说,的确是有风险的;所以我们还是推荐您用 fdisk 分区工具; fdisk 的使用说明: 请参考:《实例解说 fdisk 使用方法》
二、存储设备进行格式化,即建立文件系统的过程;

1、文件系统的一点介绍
我们对存储设备分区还是远远不够的,我们还要对这些新增分区进行格式化;一个分区只有建立了某种文件系统后,这个分区才能使用;建立文件系统过程,就是用 相应格式化工具格式化分区的过程,这个过程和我们在Windows中格式化某个分区为NTFS分区类似;没有什么高深的内容,只是所用的工具不一样罢了; 在Linux操作系统中,目前几乎支持目前主流的文件系统,比如NTFS(只读)、FAT(可读可写)、ext2、ext3、reiserfs、hfs (MAC 操作系统的文件系统)、swap 交换分区... ... 还有一些咱们不熟悉的操作系统的文件系统等; 在Linux中,我们常用的文件系统无非是上面例出的这些;如果您新增了一个硬盘,可能想格式化成 Linux的文件系统,最佳选择是 reiserfs 或ext3;目前ext2已被 ext3取代;我们不推荐用ext2文件系统,ext2的使用风险比较大;速度最快的文件系统,当属reiserfs;reiserfs 还有很多优点,比如更安全;ext3是Redhat认为最好的文件系统,所以在Fedora 4.0在安装时,特地为reiserfs 的选择弄出点麻烦; 相对来说reiserfs还是比ext3要优秀;如果想深入学习文件系统的,您可以到官方论坛找相应的资料,最好是实践实践;

2、格式化工具介绍和使用;
以fedora 4.0为例,我们常用的工具mkfs mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mkswap 提示:如果您不能创建reiserfs 文件系统,也就是说没有mkfs.reiserfs 或者mkreiserfs 命令,是您没有安装reiserfs-utils工具包,请参考:《让Fedora 支持创建reiserfs 文件系统,以及创建reiserfs文件系统的一点说明》
1)mkfs的使用;
使用方法:
[root@localhost beinan]# mkfs -t 文件系统  存储设备



注:
这里的文件系统是要指定的,比如 ext3 ;reiserfs ;ext2 ;fat32 ;msdos 等... ...
设备比如是一个硬盘的分区,软盘,光驱等.. ... 在格式化分区之前,您得懂得如何查看硬盘分区情况,并有针对性的格式化;比如用 fdisk -l 来查看; 请参考:《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》 比如我想格式化一个移动U盘中的一个分区;全景应该是:
[root@localhost beinan]# fdisk -l

Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1         765     6144831    7  HPFS/NTFS
/dev/hda2             766        2805    16386300    c  W95 FAT32 (LBA)
/dev/hda3            2806        9729    55617030    5  Extended
/dev/hda5            2806        3825     8193118+  83  Linux
/dev/hda6            3826        5100    10241406   83  Linux
/dev/hda7            5101        5198      787153+  82  Linux swap / Solaris
/dev/hda8            5199        6657    11719386   83  Linux
/dev/hda9            6658        7751     8787523+  83  Linux
/dev/hda10           7752        9729    15888253+  83  Linux

Disk /dev/sda: 1035 MB, 1035730944 bytes
256 heads, 63 sectors/track, 125 cylinders
Units = cylinders of 16128 * 512 = 8257536 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1          25      201568+  83  Linux
/dev/sda2              26         125      806400    5  Extended
/dev/sda5              26          50      201568+  83  Linux
/dev/sda6              51          76      200781     83  Linux
我们可以看到有sda这个设备,所以可以用 fdisk -l /dev/sda专门来显示他的分区情况;比如我想格式化 /dev/sda6 分区为 ext3文件系统,则为:
[root@localhost beinan]# mkfs -t ext3  /dev/sda6
mke2fs 1.37 (21-Mar-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
50200 inodes, 200780 blocks
10039 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
25 block groups
8192 blocks per group, 8192 fragments per group
2008 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information:  注:在这里直接回车;
done

This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
这样就格式化好了,sda6现在就是ext3文件系统了;我们就可以用mount 加载这个分区,然后使用这个文件系统;
[root@localhost beinan]# mkdir /mnt/sda6
[root@localhost beinan]# chmod 777 /mnt/sda6
[root@localhost beinan]# mount /dev/sda6   /mnt/sda6
当然您也可以把分区格式化成其它的文件系统;比如我们把 /dev/sda6格式化为ext3 、ext2、reiserfs、fat32、msdos 文件系统,命令格式如下;
[root@localhost beinan]# mkfs -t ext3  /dev/sda6
[root@localhost beinan]# mkfs -t ext2  /dev/sda6
[root@localhost beinan]# mkfs -t reiserfs  /dev/sda6
[root@localhost beinan]# mkfs -t fat32   /dev/sda6
[root@localhost beinan]# mkfs -t msdos   /dev/sda6
... ...

2)mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mke2fs 的介绍;
我们先说了一个mkfs 工具后,我们再来介绍 mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkdosfs mkfs.msdos mkfs.vfat ,其实mkfs 在执行的命令的时候,也是调用的这个工具,这也是我先把mkfs介绍的主要原因; 通过文件名,我们就知道这些工具是支持什么文件系统;这些命令为我们提供了更多的方便;


[root@localhost beinan]# mkfs.ext3    /dev/sda6     注:把该设备格式化成ext3文件系统
[root@localhost beinan]# mke2fs -j   /dev/sda6       注:把该设备格式化成ext3文件系统
[root@localhost beinan]# mkfs.ext2  /dev/sda6       注:把该设备格式化成ext2文件系统
root@localhost beinan]# mke2fs    /dev/sda6          注:把该设备格式化成ext2文件系统
[root@localhost beinan]# mkfs.reiserfs  /dev/sda6   注:把该设备格式化成reiserfs文件系统
[root@localhost beinan]# mkfs.vfat   /dev/sda6        注:把该设备格式化成fat32文件系统
[root@localhost beinan]# mkfs.msdos   /dev/sda6   注:把该设备格式化成fat16文件系统,msdos文件系统就是fat16;
[root@localhost beinan]# mkdosfs   /dev/sda6         注:把该设备格式化成fat16文件系统,同mkfs.msdos
... ...



2)mkswap 把一个分区格式化成为swap交换区;

[root@localhost beinan]# mkswap /dev/sda6  注:创建此分区为swap 交换分区
[root@localhost beinan]# swapon  /dev/sda6  注:加载交换分区;
[root@localhost beinan]# swapoff  /dev/sda6  注:关闭交换分区;
我们查看系统已经加载的swap交换分区;
[root@localhost beinan]# swapon  /dev/sda6  注:加载交换分区;
[root@localhost beinan]# swapon -s               
Filename                                Type            Size    Used    Priority
/dev/hda7                               partition       787144  0       -1
/dev/sda6                               partition       225144  0       -3
<code>

为什么我的系统有两个交换分区?因为我用移动U盘做的实验,主要是为写教程之用;sda6是我在U盘上建的swap分区;

如果让swap开机就加载,应该改 /etc/fstab文件,加类似如下一行;

<code>
/dev/sda6         swap                    swap    defaults        0 0  注:把此行中的/dev/hda7 改为您的交换分区就行;
或者把命令行直接写入 /etc/rc.d/rc.local中也行;
swapon  /dev/sda6 
如果您的硬盘不能再分区,您可以创建一个swap文件
[root@localhost beinan]# dd if=/dev/zero of=/tmp/swap bs=1024 count=524288 注:创建一个大小为512M 的swap 文件,在/tmp目录中;您可以根据自己的需要的大小来创建swap 文件;

读入了 524288+0 个块
输出了 524288+0 个块
[root@localhost beinan]# mkswap /tmp/swap 注:把/tmp/swap 文件,创建成swap 交换区
Setting up swapspace version 1, size = 536866 kB
no label, UUID=d9d8645d-92cb-4d33-b36e-075bb0a2e278
[root@localhost beinan]# swapon /tmp/swap   注:挂载swap

[root@localhost beinan]# swapon -s
Filename Type Size Used Priority
/dev/hda7 partition 787144 888 -1
/tmp/swap file 524280 0 -2
注意:其实我们在安装系统的时候,就已经划分了交换分区;查看/etc/fstab,应该swap的行;如果您在安装系统时没有添加swap,可以通过这种办法来添加;
三、挂载文件系统;
挂载文件系统,目前有两种方法,一是通过 mount 来挂载,另一种方法是通过/etc/fstab文件来开机自动挂载
1、通过mount 来挂载磁盘分区(或存储设备)
mount的用法其实也简单,我们说几个常用的;

挂载文件系统的命令格式:

[root@localhost beinan]# mount  [-t  文件系统 ]  [-o  选项]  设备  目录
注: -t 通过这个参数,我们来指定文件系统的类型,一般的情况下不必指定有时也能识加,-t 后面跟 ext3 、ext2 、reiserfs、vfat 、ntfs 等,其中 vfat 是fat32和fat16分区文件系统所所用的参数;如果您忘记了文件系统,也可以在-t 后面加auto ; -o 这个选项,主要选项有权限、用户、磁盘限额、语言编码等,但语言编码的选项,大多用于vfat和ntfs文件系统;由于选项太多,还是请您看看 man mount ;这里不多说; 设备 指存储设备,比如/dev/hda1, /dev/sda1 ,cdrom 等...至于您的系统中有哪些存储设备,主要通过 fdisk -l 或者查看 /etc/fstab 或 dmesg ;一般的情况下光驱设备是/dev/cdrom ;软驱设备是/dev/fd0 ;硬盘及移动硬盘以 fdisk -l 的输出为准;
1)对光驱和软驱的挂载


举例:

[root@localhost beinan]# mount /dev/cdrom
[root@localhost beinan]# mount /dev/fd0
第一行是mount 光驱,至于mount 到哪了,我们可以通过查看 /etc/fstab来查看;同理软驱/dev/fd0设备也是如此;比如我们在/etc/fstab
/dev/hdc                /media/cdrecorder       auto    users,exec,noauto,managed 0 0
我们可以肯定的是光盘被mount 到了 /media/cdrecorder 目录; 但我们也可以自己来指定cdrom 挂载的位置 ;比如 /mnt/cdrom ,所以我们也可以这样来挂载光驱;
[root@localhost beinan]#mkdir /mnt/cdrom
[root@localhost beinan]# mount /dev/cdrom  /mnt/cdrom
我 们先建一个目录,然后执行mount 命令,这样cdrom 就挂在 /mnt/cdrom 中了;我们就可以在/mnt/cdrom 中查看光盘中资料和文件;这个目录您想怎么建就怎么建。用什么目录不是最重要的。重要的是您知道自己在做什么就行了。比如我们也可以把这个目录建成 dvdrom ;然后用 mount /dev/cdrom /mnt/dvdrom 来挂载; 有时我们的设备是COMBO的,有支持dvd cd 还能支持刻录的;我们最好查一下光驱设备的,主要有两个方法,一是通过查看 /etc/fstab ,二是通过ls -l 来查看;比如我们在/etc/fstab中查看到类似下面的一行;
/dev/hdc                /media/cdrecorder       auto    users,exec,noauto,managed 0 0
通过这个,我们能知道hdc 就是cdrom 也是dvdrom的设备 ,更是 cdrecorder的设备;为了验证我们的说法;请用ls -l 来列文件;
[root@localhost beinan]# ls -lh /dev/dvd*
lrwxrwxrwx  1 root root 3 2005-09-13  /dev/dvd -> hdc
[root@localhost beinan]# ls -lh /dev/cdrom
lrwxrwxrwx  1 root root 3 2005-09-13  /dev/cdrom -> hdc
[root@localhost beinan]# ls -lh /dev/cdwriter
lrwxrwxrwx  1 root root 3 2005-09-13  /dev/cdwriter -> hdc
这不一目了然了吗?dvd 、cdrom 、cdwriter 的文件名都链接到了hdc这个设备,所以光驱设备根源就是/dev/hdc ;所以我们也可以这样挂载光驱;
[root@localhost beinan]# mkdir /mnt/cdrom
[root@localhost beinan]# mount  /dev/hdc   /mnt/cdrom




2)挂载硬盘和移动硬盘的文件系统;
一个分区只有创建了文件系统后才能使用,前面我们说过了,我们在Linux大多用的是ext2 、ext3、reiserfs、fat32、msdos 、ntfs等;

[1]挂载Linux文件系统;
对于ext2 、ext3 、reiserfs 不需要指定文件系统的编码,其实mount 也没有这个功能;这些Linux文件系统,如果出现编码问题,一般是通过export LANG来指定;所以挂载这些文件系统比较简单; 首先我们得建一个文件系统挂载的目录;我们前面已经提到了;一个有文件系统的分区要挂到系统中,必须要有一个挂载点;这个挂载点就是一个目录;比如我们通过fdisk -l 得知hda5 是Linux分区,并且创建了文件系统,比如是reiserfs 文件系统吧;
[root@localhost beinan]# fdisk -l /dev/hda

Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1   *           1         765     6144831    7  HPFS/NTFS
/dev/hda2             766        2805    16386300    c  W95 FAT32 (LBA)
/dev/hda3            2806        9729    55617030    5  Extended
/dev/hda5            2806        3825     8193118+  83  Linux
/dev/hda6            3826        5100    10241406   83  Linux
/dev/hda7            5101        5198      787153+  82  Linux swap / Solaris
/dev/hda8            5199        6657    11719386   83  Linux
/dev/hda9            6658        7751     8787523+  83  Linux
/dev/hda10           7752        9729    15888253+  83  Linux
我们先用fdisk -l 来查看一下分区情况:我们想要挂载/dev/hda5分区,比如hda5分区创建的是reiserfs文件系统;
[root@localhost beinan]# mkdir /mnt/hda5/   注:先创建一个挂载目录;
[root@localhost beinan]# chmod 777  /mnt/hda5/    注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;
[root@localhost beinan]# mount -t reiserfs /dev/hda5 /mnt/hda5    注:通过-t reiserfs 来指定/dev/hda5是reiserfs 文件系统, 并且挂载到/mnt/hda5目录;
[root@localhost beinan]# mount  -t auto   /dev/hda5 /mnt/hda5   注:假如我们不知道hda5上reiserfs 文件系统,我们可以用 -t auto 让系统定夺,然后挂载到/mnt/hda5 ;
[root@localhost beinan]# mount /dev/hda5 /mnt/hda5   注:不加任何参数,直接 mount   /dev/hda5 到/mnt/hda5;系统自动判断分区文件系统;
是不是被挂载了,我们通过df -lh 来查看;
[root@localhost beinan]# df -lh
Filesystem            容量  已用 可用 已用% 挂载
/dev/hda8              11G  8.5G  1.9G  83% /
/dev/shm              236M     0  236M   0% /dev/shm
/dev/hda10             16G  6.9G  8.3G  46% /mnt/hda10
/dev/hda5             7.9G  5.8G  2.1G  74% /mnt/hda5




[2]挂载Windows文件系统;
请参考: 《在Fedora core 4.0 加载NTFS和FAT32分区详述》
3)卸载文件系统umount ;


命令用法:
[root@localhost beinan]# umount  设备或挂载目录


举例:

[root@localhost beinan]# mount -t auto /dev/hda5 /mnt/hda5   注:挂载/dev/hda5;
[root@localhost beinan]# df -lh       注:查看/dev/hda5是否被挂载
Filesystem            容量  已用 可用 已用% 挂载
/dev/hda8              11G  8.5G  1.9G  83% /
/dev/shm              236M     0  236M   0% /dev/shm
/dev/hda10             16G  6.9G  8.3G  46% /mnt/hda10
/dev/hda5             7.9G  5.8G  2.1G  74% /mnt/hda5
[root@localhost beinan]# umount /dev/hda5  注:卸载/dev/hda5
[root@localhost beinan]# df -lh        注:看是否卸载了/dev/hda5;
Filesystem            容量  已用 可用 已用% 挂载
/dev/hda8              11G  8.5G  1.9G  83% /
/dev/shm              236M     0  236M   0% /dev/shm
/dev/hda10             16G  6.9G  8.3G  46% /mnt/hda10
[root@localhost beinan]#umount /dev/cdrom  注:卸载cdrom ;
[root@localhost beinan]#umount  /dev/fd0   注:卸载软驱;
... ... 再说一个查看分区是否被挂载了的命令,直接用 mount -s
[root@localhost beinan]# mount -s

2、通过/etc/fstab文件来开机自动挂载文件系统


1)理解fstab
上面我们说了mount挂载存储设备文件系统的办法;现在我们再来说一说在/etc/fstab 中实现开机自动挂载文件系统的办法;首先我们要查看 /etc/fstab ;主要看他的规划写法;
# This file is edited by fstab-sync - see 'man fstab-sync' for details
LABEL=/1                /                       ext3    defaults        1 1
/dev/devpts             /dev/pts                devpts  gid=5,mode=620  0 0
/dev/shm                /dev/shm                tmpfs   defaults        0 0
/dev/proc               /proc                   proc    defaults        0 0
/dev/sys                /sys                    sysfs   defaults        0 0
LABEL=SWAP-hda7         swap                    swap    defaults        0 0
/dev/hdc                /media/cdrecorder       auto    users,exec,noauto,managed 0 0
第一字段:设备名,在这里表示是文件系统; 有时我们把挂载文件系统也说成挂载分区; 在这个字段中也可以用分区标签;在例子中/LABEL=/1就是Fedora 系统安装分区的标签,至于是在哪个分区,可以用 df -lh 来查看;
[root@localhost beinan]# df -lh
Filesystem            容量  已用 可用 已用% 挂载
/dev/hda8              11G  8.5G  1.9G  83% /
/dev/shm              236M     0  236M   0% /dev/shm
/dev/hda10             16G  6.9G  8.3G  46% /mnt/hda10
我们可以知道 LABEL=/1是/dev/hda8的标签;那我们用什么命令来创建硬盘分区的标签呢? 对于ext3和ext2文件系统,我们可以用 e2label 来设置
e2label device [newlabel]
比如我们想把文件系统为ext3 的分区/dev/hda5的标签设备为 /5 ,我们应该执行如下的命令:
[root@localhost beinan]# e2label /dev/hda5  /5  
[root@localhost beinan]# mkdir /mnt/hda5  注:创建挂载/dev/hda5分区的目录;
[root@localhost beinan]# chmod 777 /mnt/hda5  注:打开权限,所有用户可读可写可执行;
然后我们要改/etc/fstab 中加一行
/5         /mnt/hda5                    ext3     defaults        0 0
警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试; 如果是reiserfs文件系统,我们应该用 [root@localhost beinan]# reiserfstune -l 标签 设备 举例:比如我为reiserfs 文件系统 /dev/hda10设置标签为 /10 ;
[root@localhost beinan]# reiserfstune -l /10 /dev/hda10
我们在/etc/fstab中加入一行;
/10              /mnt/hda10              reiserfs defaults       0 0

警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试; 第二字段:文件系统的挂载点;
第三字段:文件系统类型;
第四字段:mount 命令的选项,和mount 中的-o 同理;defaults包括这些选项 rw, suid, dev, exec, auto, nouser, async;通过实践,这个默认的还能满足我们的需要;至于这些选项的意思,请参看man mount ; 第五字段:表示文件系统是否需要dump 备份,是真假关系;1是需要,0 是不需要;
第六字段: 是否在系统启动时,通过fsck磁盘检测工具来检查文件系统,1是需要,0是不需要,2是跳过; 基于这些认识;比如我们要开机自动挂载/dev/hda5 ;我们可以如下做;
[root@localhost beinan]# mkdir /mnt/hda5/   注:先创建一个挂载目录;
[root@localhost beinan]# chmod 777  /mnt/hda5/    注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;
然后我们在/etc/fstab 中加如下的一行;
/dev/hda5              /mnt/hda5             reiserfs defaults       0 0
这样重启机器就能看到效果了;
四、对文件系统进行扫描fsck;
大家对Windows中的scandisk不寞生吧,在Linux中就有类似这样的工具fsck,不过fsck 可不仅仅是扫描,还能修正文件系统的一些问题。值得注意的是fsck 扫描文件系统时一定要在单用户模式、修复模式或把设备umount后进行。 警告:如果扫描正在运行中的系统,会造成系统文件损坏;如果您的系统是正常,请不要用扫描工具,她可能会把您的系统搞坏掉,fsck运行是有危险的; 以Fedora 为例,文件系统扫描工具有 fsck fsck.ext2 fsck.jfs fsck.msdos fsck.vfat fsck.ext3 fsck.reiserfs(reiserfsck) 其中fsck 默认支持文件系统ext2,如果想支持ext3文件系统的扫描,应该加-j 参数,最好是我们应该根据不同的文件系统来调用不同的扫描工具,比如 fsck.ext2,fsck.jfs,fsck.msdos,fsck.ext3,fsck.reiserfs(reiserfsck)等。我们也可以 根据自己的文件系统选择不同的扫描工具; 举例:扫描/dev/hda10分区(基于reiserfs文件系统 );
[root@localhost beinan]# fsck.reiserfs /dev/hda10
reiserfsck 3.6.19 (2003 www.namesys.com)

*************************************************************
** If you are using the latest reiserfsprogs and  it fails **
** please  email bug reports to reiserfs-list@namesys.com, **
** providing  as  much  information  as  possible --  your **
** hardware,  kernel,  patches,  settings,  all reiserfsck **
** messages  (including version),  the reiserfsck logfile, **
** check  the  syslog file  for  any  related information. **
** If you would like advice on using this program, support **
** is available  for $25 at  www.namesys.com/support.html. **
*************************************************************

Will read-only check consistency of the filesystem on /dev/hda10
Will put log info to 'stdout'

Do you want to run this program?[N/Yes] (note need to type Yes if you do):Yes
###########
reiserfsck --check started at Wed Sep 14 08:54:17 2005
###########
Replaying journal..
Reiserfs journal '/dev/hda10' in blocks [18..8211]: 0 transactions replayed
Checking internal tree..finished
Comparing bitmaps..finished
Checking Semantic tree:
finished
No corruptions found   注:没有发现错误;
There are on the filesystem:
        Leaves 2046
        Internal nodes 15
        Directories 130
        Other files 2305
        Data block pointers 1863657 (70565 of them are zero)
        Safe links 0
###########
reiserfsck finished at Wed Sep 14 08:54:33 2005
###########
对于fsck.ext2和fsck.ext3常用的几个选项:
-p         Automatic repair (no questions) 注:自动修复文件系统存在的问题;
-y         Assume "yes" to all questions   注:如果文件系统有问题,会跳出提示是否修复,如果修复请按y;
-c         Check for bad blocks and add them to the badblock list 注:对文件系统进行坏块检查;这是一个极为漫长的过程;
-n         Make no changes to the filesystem   注:不对文件系统做任何改变,只要扫描,以检测是否有问题;
举例:比如 /dev/hda6 (文件系统是ext3的),我想扫描并自动修复;
[root@localhost beinan]# fsck.ext3  -p /dev/hda6
注意: 针对不同文件系统,最好用相应的工具;虽然有时fsck 在不加参数的情况下能识别不同的文件系统; 对于不同工具的最为详细的参数,请参看--help或者man ,谢谢。。
后记: 创建文件系统和加载文件系统就算写的差不多了;再高深的可能也不是我所能写的。为了写文件系统系统的挂载,我已经写过几篇文档。可能还得需补充几篇短小文档,以及还有一个总结性的文档; 比如Fedora Core 4.0 默认安装不支持创建reiserfs 文件系统,解决办法是安装reiserfs-utils ,这也是需要补充的;
附录: 《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》
《实例解说 fdisk 使用方法》
《在Fedora core 4.0 加载NTFS和FAT32分区详述》
《合理规划您的硬盘分区》
《系统引导过程及硬盘分区结构论述》
《Fedora Core 4.0 HAL配置即插即用移动存储(USB及1394)的实践》
2019-06-18 11:48:06 cuifei8741 阅读数 6
  • Linux应用软件服务篇-五剑客

    第一章节讲解主流的 Vsftp服务器如何通过服务端与客户端实现文件资源共享,讲解了Vsftp之间三种用户在不同的配置方法对不同的目录文件资源限制访问,达到更安全高效的资源共享数据传输。 第二章节讲解企业级NTP时间服务器对公司内网所有客户机及服务器批量实现时间同步,多个节点如何去快速同步主服务器时间。  第三章节讲解 NFS服务器实现与客户机磁盘文件的共享,通过网络让不同的机器、不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据,重点讲解了通过客户端远程挂载服务器磁盘共享文件及如何使用指定用户去访问指定的共享文件夹数据。 第四章节讲解samba服务器在企业中,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源,重点介绍了通过 samba配置文件权限配置去对匿名文件夹及指定用户文件夹共享资源服务。 第五章节介绍了去部署 DHCP服务器对批量客户端实现自动获取IP,通过配置文件IP池获取到IP形式,及绑定客户端Mac地址及指定IP给予客户端,从而获得IP方法。

    140 人正在学习 去看看 吴光科
Linux 创建文件系统及挂载文件系统流程详解

作者:北南南北
来自: LinuxSir.Org
摘要:本文对新增硬盘,切割硬盘,创建硬盘分区,为硬盘分区创建文件系统,以及加载文件系统的流程做总结性论述;主要是为初学者弄清楚这一操作过程;本文涉及fdisk、mkfs、mount ... ... 等工具;对/etc/fstab 进行了解说;还有磁盘扫描工具fsck 等介绍;


++++++++++++++++++++++++++++++++++++++++++++++++++++++
正文
++++++++++++++++++++++++++++++++++++++++++++++++++++++


阅读此文,必须具备知识点:

《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》
《实例解说 fdisk 使用方法》
《合理规划您的硬盘分区》
《Fedora / Redhat 软件包管理指南》

如果您想加载一个分区(文件系统),首先您得确认文件系统的类型,然后才能挂载使用,比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载;
如果您想添加一个新的分区,或者增加一个新的硬盘,您要通过分区工具来添加分区,然后要创建分区的文件系统,然后才是挂载文件系统;比如通过mount 加载,或者通过修改 /etc/fstab来开机自动加载;

本文总有一部份是您想要的;比如在新的分区上创建文件系统,如何挂载;如何卸载文件系统或者设备(比如cdrom )等;我建您最好通读本文,然后根据自己的需要再做选择性实践;

Linux的一个小问题涉及的很多方面的知识,有时一篇文档是难以说清楚;我为了尽可能详细解说每一个过程,所以把分区工具、创建文件系统工具、查看文件系统的工具分开来说,主要是让初学者比较容易理解。希望您能理解本人的用心;传说北南长的比较丑,但心的还是善良的 ... ...我是不会用一些垃圾文档来害您 ... ... 哈哈 ... ... 言归正传,开文~~~~


一、对存储设备的分区;

我们这里所指的存储设备主要是本地硬盘、移动硬盘(比如USB 和1394接口的硬盘);由于磁盘很大并且为了满足我们各种需要,所以把硬盘分成若干个分区;比如我们可以用这个分区来安装Linux系统,那个分区用来安装Windows系统... ... ;这点小事大家都明白;

至于如何在 Linux中进行硬盘分区操作,我们推荐您用 fdisk ,目前看来也是最好用的分区工具;其它工具比如parted 和cfdisk在某一方面有点优点,但这些优点可能为大家带来一些方便 ,比如 parted中的数据备份功能,这个功能对老手来说可能是优点,但对新手来说,的确是有风险的;所以我们还是推荐您用 fdisk 分区工具;

fdisk 的使用说明: 请参考:《实例解说 fdisk 使用方法》


二、存储设备进行格式化,即建立文件系统的过程;


1、文件系统的一点介绍

我们对存储设备分区还是远远不够的,我们还要对这些新增分区进行格式化;一个分区只有建立了某种文件系统后,这个分区才能使用;建立文件系统过程,就是用相应格式化工具格式化分区的过程,这个过程和我们在Windows中格式化某个分区为NTFS分区类似;没有什么高深的内容,只是所用的工具不一样罢了;

在Linux操作系统中,目前几乎支持目前主流的文件系统,比如NTFS(只读)、FAT(可读可写)、ext2、ext3、reiserfs、hfs (MAC 操作系统的文件系统)、swap 交换分区... ... 还有一些咱们不熟悉的操作系统的文件系统等;

在Linux中,我们常用的文件系统无非是上面例出的这些;如果您新增了一个硬盘,可能想格式化成 Linux的文件系统,最佳选择是 reiserfs 或ext3;目前ext2已被 ext3取代;我们不推荐用ext2文件系统,ext2的使用风险比较大;速度最快的文件系统,当属reiserfs;reiserfs 还有很多优点,比如更安全;ext3是Redhat认为最好的文件系统,所以在Fedora 4.0在安装时,特地为reiserfs 的选择弄出点麻烦;

相对来说reiserfs还是比ext3要优秀;如果想深入学习文件系统的,您可以到官方论坛找相应的资料,最好是实践实践;

2、格式化工具介绍和使用;

以fedora 4.0为例,我们常用的工具mkfs mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mkswap

提示:如果您不能创建reiserfs 文件系统,也就是说没有mkfs.reiserfs 或者mkreiserfs 命令,是您没有安装reiserfs-utils工具包,请参考:《让Fedora 支持创建reiserfs 文件系统,以及创建reiserfs文件系统的一点说明》


1)mkfs的使用;

使用方法:

[root@localhost beinan]# mkfs -t 文件系统 存储设备



注:
这里的文件系统是要指定的,比如 ext3 ;reiserfs ;ext2 ;fat32 ;msdos 等... ...
设备比如是一个硬盘的分区,软盘,光驱等.. ...

在格式化分区之前,您得懂得如何查看硬盘分区情况,并有针对性的格式化;比如用 fdisk -l 来查看;

请参考:《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》

比如我想格式化一个移动U盘中的一个分区;全景应该是:

[root@localhost beinan]# fdisk -l
Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 765 6144831 7 HPFS/NTFS
/dev/hda2 766 2805 16386300 c W95 FAT32 (LBA)
/dev/hda3 2806 9729 55617030 5 Extended
/dev/hda5 2806 3825 8193118+ 83 Linux
/dev/hda6 3826 5100 10241406 83 Linux
/dev/hda7 5101 5198 787153+ 82 Linux swap / Solaris
/dev/hda8 5199 6657 11719386 83 Linux
/dev/hda9 6658 7751 8787523+ 83 Linux
/dev/hda10 7752 9729 15888253+ 83 Linux
Disk /dev/sda: 1035 MB, 1035730944 bytes
256 heads, 63 sectors/track, 125 cylinders
Units = cylinders of 16128 * 512 = 8257536 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 25 201568+ 83 Linux
/dev/sda2 26 125 806400 5 Extended
/dev/sda5 26 50 201568+ 83 Linux
/dev/sda6 51 76 200781 83 Linux

我们可以看到有sda这个设备,所以可以用 fdisk -l /dev/sda专门来显示他的分区情况;比如我想格式化 /dev/sda6 分区为 ext3文件系统,则为:

[root@localhost beinan]# mkfs -t ext3 /dev/sda6
mke2fs 1.37 (21-Mar-2005)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
50200 inodes, 200780 blocks
10039 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
25 block groups
8192 blocks per group, 8192 fragments per group
2008 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: 注:在这里直接回车;
done
This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

这样就格式化好了,sda6现在就是ext3文件系统了;我们就可以用mount 加载这个分区,然后使用这个文件系统;

[root@localhost beinan]# mkdir /mnt/sda6
[root@localhost beinan]# chmod 777 /mnt/sda6
[root@localhost beinan]# mount /dev/sda6 /mnt/sda6

当然您也可以把分区格式化成其它的文件系统;比如我们把 /dev/sda6格式化为ext3 、ext2、reiserfs、fat32、msdos 文件系统,命令格式如下;

[root@localhost beinan]# mkfs -t ext3 /dev/sda6
[root@localhost beinan]# mkfs -t ext2 /dev/sda6
[root@localhost beinan]# mkfs -t reiserfs /dev/sda6
[root@localhost beinan]# mkfs -t fat32 /dev/sda6
[root@localhost beinan]# mkfs -t msdos /dev/sda6
... ...


2)mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkfs.msdos mkfs.vfat mke2fs 的介绍;

我们先说了一个mkfs 工具后,我们再来介绍 mkfs.ext3 mkfs.reiserfs mkfs.ext2 mkdosfs mkfs.msdos mkfs.vfat ,其实mkfs 在执行的命令的时候,也是调用的这个工具,这也是我先把mkfs介绍的主要原因;

通过文件名,我们就知道这些工具是支持什么文件系统;这些命令为我们提供了更多的方便;

[root@localhost beinan]# mkfs.ext3 /dev/sda6 注:把该设备格式化成ext3文件系统
[root@localhost beinan]# mke2fs -j /dev/sda6 注:把该设备格式化成ext3文件系统
[root@localhost beinan]# mkfs.ext2 /dev/sda6 注:把该设备格式化成ext2文件系统
root@localhost beinan]# mke2fs /dev/sda6 注:把该设备格式化成ext2文件系统
[root@localhost beinan]# mkfs.reiserfs /dev/sda6 注:把该设备格式化成reiserfs文件系统
[root@localhost beinan]# mkfs.vfat /dev/sda6 注:把该设备格式化成fat32文件系统
[root@localhost beinan]# mkfs.msdos /dev/sda6 注:把该设备格式化成fat16文件系统,msdos文件系统就是fat16;
[root@localhost beinan]# mkdosfs /dev/sda6 注:把该设备格式化成fat16文件系统,同mkfs.msdos
... ...



2)mkswap 把一个分区格式化成为swap交换区;

[root@localhost beinan]# mkswap /dev/sda6 注:创建此分区为swap 交换分区
[root@localhost beinan]# swapon /dev/sda6 注:加载交换分区;
[root@localhost beinan]# swapoff /dev/sda6 注:关闭交换分区;

我们查看系统已经加载的swap交换分区;

[root@localhost beinan]# swapon /dev/sda6 注:加载交换分区;
[root@localhost beinan]# swapon -s
Filename Type Size Used Priority
/dev/hda7 partition 787144 0 -1
/dev/sda6 partition 225144 0 -3

为什么我的系统有两个交换分区?因为我用移动U盘做的实验,主要是为写教程之用;sda6是我在U盘上建的swap分区;
如果让swap开机就加载,应该改 /etc/fstab文件,加类似如下一行;

/dev/sda6 swap swap defaults 0 0 注:把此行中的/dev/hda7 改为您的交换分区就行;

或者把命令行直接写入 /etc/rc.d/rc.local中也行;

swapon /dev/sda6

如果您的硬盘不能再分区,您可以创建一个swap文件

[root@localhost beinan]# dd if=/dev/zero of=/tmp/swap bs=1024 count=524288 注:创建一个大小为512M 的swap 文件,在/tmp目录中;您可以根据自己的需要的大小来创建swap 文件;
读入了 524288+0 个块
输出了 524288+0 个块
[root@localhost beinan]# mkswap /tmp/swap 注:把/tmp/swap 文件,创建成swap 交换区
Setting up swapspace version 1, size = 536866 kB
no label, UUID=d9d8645d-92cb-4d33-b36e-075bb0a2e278
[root@localhost beinan]# swapon /tmp/swap 注:挂载swap
[root@localhost beinan]# swapon -s
Filename Type Size Used Priority
/dev/hda7 partition 787144 888 -1
/tmp/swap file 524280 0 -2

注意:其实我们在安装系统的时候,就已经划分了交换分区;查看/etc/fstab,应该swap的行;如果您在安装系统时没有添加swap,可以通过这种办法来添加;


三、挂载文件系统;

挂载文件系统,目前有两种方法,一是通过 mount 来挂载,另一种方法是通过/etc/fstab文件来开机自动挂载;


1、通过mount 来挂载磁盘分区(或存储设备)

mount的用法其实也简单,我们说几个常用的;

挂载文件系统的命令格式:

[root@localhost beinan]# mount [-t 文件系统 ] [-o 选项] 设备 目录

注:

-t 通过这个参数,我们来指定文件系统的类型,一般的情况下不必指定有时也能识加,-t 后面跟 ext3 、ext2 、reiserfs、vfat 、ntfs 等,其中 vfat 是fat32和fat16分区文件系统所所用的参数;如果您忘记了文件系统,也可以在-t 后面加auto ;

-o 这个选项,主要选项有权限、用户、磁盘限额、语言编码等,但语言编码的选项,大多用于vfat和ntfs文件系统;由于选项太多,还是请您看看 man mount ;这里不多说;

设备 指存储设备,比如/dev/hda1, /dev/sda1 ,cdrom 等...至于您的系统中有哪些存储设备,主要通过 fdisk -l 或者查看 /etc/fstab 或 dmesg ;一般的情况下光驱设备是/dev/cdrom ;软驱设备是/dev/fd0 ;硬盘及移动硬盘以 fdisk -l 的输出为准;


1)对光驱和软驱的挂载;


举例:

[root@localhost beinan]# mount /dev/cdrom
[root@localhost beinan]# mount /dev/fd0

第一行是mount 光驱,至于mount 到哪了,我们可以通过查看 /etc/fstab来查看;同理软驱/dev/fd0设备也是如此;比如我们在/etc/fstab

/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0

我们可以肯定的是光盘被mount 到了 /media/cdrecorder 目录;

但我们也可以自己来指定cdrom 挂载的位置 ;比如 /mnt/cdrom ,所以我们也可以这样来挂载光驱;

[root@localhost beinan]#mkdir /mnt/cdrom
[root@localhost beinan]# mount /dev/cdrom /mnt/cdrom

我们先建一个目录,然后执行mount 命令,这样cdrom 就挂在 /mnt/cdrom 中了;我们就可以在/mnt/cdrom 中查看光盘中资料和文件;这个目录您想怎么建就怎么建。用什么目录不是最重要的。重要的是您知道自己在做什么就行了。比如我们也可以把这个目录建成 dvdrom ;然后用 mount /dev/cdrom /mnt/dvdrom 来挂载;

有时我们的设备是COMBO的,有支持dvd cd 还能支持刻录的;我们最好查一下光驱设备的,主要有两个方法,一是通过查看 /etc/fstab ,二是通过ls -l 来查看;比如我们在/etc/fstab中查看到类似下面的一行;

/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0

通过这个,我们能知道hdc 就是cdrom 也是dvdrom的设备 ,更是 cdrecorder的设备;为了验证我们的说法;请用ls -l 来列文件;

[root@localhost beinan]# ls -lh /dev/dvd*
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/dvd -> hdc
[root@localhost beinan]# ls -lh /dev/cdrom
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/cdrom -> hdc
[root@localhost beinan]# ls -lh /dev/cdwriter
lrwxrwxrwx 1 root root 3 2005-09-13 /dev/cdwriter -> hdc

这不一目了然了吗?dvd 、cdrom 、cdwriter 的文件名都链接到了hdc这个设备,所以光驱设备根源就是/dev/hdc ;所以我们也可以这样挂载光驱;

[root@localhost beinan]# mkdir /mnt/cdrom
[root@localhost beinan]# mount /dev/hdc /mnt/cdrom




2)挂载硬盘和移动硬盘的文件系统;

一个分区只有创建了文件系统后才能使用,前面我们说过了,我们在Linux大多用的是ext2 、ext3、reiserfs、fat32、msdos 、ntfs等;

[1]挂载Linux文件系统;

对于ext2 、ext3 、reiserfs 不需要指定文件系统的编码,其实mount 也没有这个功能;这些Linux文件系统,如果出现编码问题,一般是通过export LANG来指定;所以挂载这些文件系统比较简单;

首先我们得建一个文件系统挂载的目录;我们前面已经提到了;一个有文件系统的分区要挂到系统中,必须要有一个挂载点;这个挂载点就是一个目录;比如我们通过fdisk -l 得知hda5 是Linux分区,并且创建了文件系统,比如是reiserfs 文件系统吧;

[root@localhost beinan]# fdisk -l /dev/hda
Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 765 6144831 7 HPFS/NTFS
/dev/hda2 766 2805 16386300 c W95 FAT32 (LBA)
/dev/hda3 2806 9729 55617030 5 Extended
/dev/hda5 2806 3825 8193118+ 83 Linux
/dev/hda6 3826 5100 10241406 83 Linux
/dev/hda7 5101 5198 787153+ 82 Linux swap / Solaris
/dev/hda8 5199 6657 11719386 83 Linux
/dev/hda9 6658 7751 8787523+ 83 Linux
/dev/hda10 7752 9729 15888253+ 83 Linux

我们先用fdisk -l 来查看一下分区情况:我们想要挂载/dev/hda5分区,比如hda5分区创建的是reiserfs文件系统;

[root@localhost beinan]# mkdir /mnt/hda5/ 注:先创建一个挂载目录;
[root@localhost beinan]# chmod 777 /mnt/hda5/ 注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;
[root@localhost beinan]# mount -t reiserfs /dev/hda5 /mnt/hda5 注:通过-t reiserfs 来指定/dev/hda5是reiserfs 文件系统, 并且挂载到/mnt/hda5目录;
[root@localhost beinan]# mount -t auto /dev/hda5 /mnt/hda5 注:假如我们不知道hda5上reiserfs 文件系统,我们可以用 -t auto 让系统定夺,然后挂载到/mnt/hda5 ;
[root@localhost beinan]# mount /dev/hda5 /mnt/hda5 注:不加任何参数,直接 mount /dev/hda5 到/mnt/hda5;系统自动判断分区文件系统;

是不是被挂载了,我们通过df -lh 来查看;

[root@localhost beinan]# df -lh
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
/dev/hda5 7.9G 5.8G 2.1G 74% /mnt/hda5




[2]挂载Windows文件系统;

请参考: 《在Fedora core 4.0 加载NTFS和FAT32分区详述》


3)卸载文件系统umount ;


命令用法:

[root@localhost beinan]# umount 设备或挂载目录


举例:

[root@localhost beinan]# mount -t auto /dev/hda5 /mnt/hda5 注:挂载/dev/hda5;

[root@localhost beinan]# df -lh 注:查看/dev/hda5是否被挂载;
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10
/dev/hda5 7.9G 5.8G 2.1G 74% /mnt/hda5

[root@localhost beinan]# umount /dev/hda5 注:卸载/dev/hda5

[root@localhost beinan]# df -lh 注:看是否卸载了/dev/hda5;
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10

[root@localhost beinan]#umount /dev/cdrom 注:卸载cdrom ;
[root@localhost beinan]#umount /dev/fd0 注:卸载软驱;

... ...

再说一个查看分区是否被挂载了的命令,直接用 mount -s

[root@localhost beinan]# mount -s


2、通过/etc/fstab文件来开机自动挂载文件系统


1)理解fstab

上面我们说了mount挂载存储设备文件系统的办法;现在我们再来说一说在/etc/fstab 中实现开机自动挂载文件系统的办法;首先我们要查看 /etc/fstab ;主要看他的规划写法;

# This file is edited by fstab-sync - see 'man fstab-sync' for details
LABEL=/1 / ext3 defaults 1 1
/dev/devpts /dev/pts devpts gid=5,mode=620 0 0
/dev/shm /dev/shm tmpfs defaults 0 0
/dev/proc /proc proc defaults 0 0
/dev/sys /sys sysfs defaults 0 0
LABEL=SWAP-hda7 swap swap defaults 0 0
/dev/hdc /media/cdrecorder auto users,exec,noauto,managed 0 0

第一字段:设备名,在这里表示是文件系统; 有时我们把挂载文件系统也说成挂载分区; 在这个字段中也可以用分区标签;在例子中/LABEL=/1就是Fedora 系统安装分区的标签,至于是在哪个分区,可以用 df -lh 来查看;

[root@localhost beinan]# df -lh
Filesystem 容量 已用 可用 已用% 挂载点
/dev/hda8 11G 8.5G 1.9G 83% /
/dev/shm 236M 0 236M 0% /dev/shm
/dev/hda10 16G 6.9G 8.3G 46% /mnt/hda10

我们可以知道 LABEL=/1是/dev/hda8的标签;那我们用什么命令来创建硬盘分区的标签呢?

对于ext3和ext2文件系统,我们可以用 e2label 来设置

e2label device [newlabel]

比如我们想把文件系统为ext3 的分区/dev/hda5的标签设备为 /5 ,我们应该执行如下的命令:

[root@localhost beinan]# e2label /dev/hda5 /5
[root@localhost beinan]# mkdir /mnt/hda5 注:创建挂载/dev/hda5分区的目录;
[root@localhost beinan]# chmod 777 /mnt/hda5 注:打开权限,所有用户可读可写可执行;

然后我们要改/etc/fstab 中加一行

/5 /mnt/hda5 ext3 defaults 0 0

警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试;

如果是reiserfs文件系统,我们应该用

[root@localhost beinan]# reiserfstune -l 标签 设备

举例:比如我为reiserfs 文件系统 /dev/hda10设置标签为 /10 ;

[root@localhost beinan]# reiserfstune -l /10 /dev/hda10

我们在/etc/fstab中加入一行;

/10 /mnt/hda10 reiserfs defaults 0 0

警告: 请不要在您的Linux的安装分区(也就是Linux系统/ 所在的分区)实践,会导致您的Linux系统崩溃;如果想实践,请在其它分区测试;

第二字段:文件系统的挂载点;
第三字段:文件系统类型;
第四字段:mount 命令的选项,和mount 中的-o 同理;defaults包括这些选项 rw, suid, dev, exec, auto, nouser, async;通过实践,这个默认的还能满足我们的需要;至于这些选项的意思,请参看man mount ;

第五字段:表示文件系统是否需要dump 备份,是真假关系;1是需要,0 是不需要;
第六字段: 是否在系统启动时,通过fsck磁盘检测工具来检查文件系统,1是需要,0是不需要,2是跳过;

基于这些认识;比如我们要开机自动挂载/dev/hda5 ;我们可以如下做;

[root@localhost beinan]# mkdir /mnt/hda5/ 注:先创建一个挂载目录;
[root@localhost beinan]# chmod 777 /mnt/hda5/ 注:设置/mnt/hda5的权限为任何用户可写可读可执行;这样所有的用户都能在写入;

然后我们在/etc/fstab 中加如下的一行;

/dev/hda5 /mnt/hda5 reiserfs defaults 0 0

这样重启机器就能看到效果了;


四、对文件系统进行扫描fsck;

大家对Windows中的scandisk不寞生吧,在Linux中就有类似这样的工具fsck,不过fsck 可不仅仅是扫描,还能修正文件系统的一些问题。值得注意的是fsck 扫描文件系统时一定要在单用户模式、修复模式或把设备umount后进行。

警告:如果扫描正在运行中的系统,会造成系统文件损坏;如果您的系统是正常,请不要用扫描工具,她可能会把您的系统搞坏掉,fsck运行是有危险的;

以Fedora 为例,文件系统扫描工具有 fsck fsck.ext2 fsck.jfs fsck.msdos fsck.vfat fsck.ext3 fsck.reiserfs(reiserfsck)

其中fsck 默认支持文件系统ext2,如果想支持ext3文件系统的扫描,应该加-j 参数,最好是我们应该根据不同的文件系统来调用不同的扫描工具,比如 fsck.ext2,fsck.jfs,fsck.msdos,fsck.ext3,fsck.reiserfs(reiserfsck)等。我们也可以根据自己的文件系统选择不同的扫描工具;

举例:扫描/dev/hda10分区(基于reiserfs文件系统 );

[root@localhost beinan]# fsck.reiserfs /dev/hda10
reiserfsck 3.6.19 (2003 www.namesys.com)
*************************************************************
** If you are using the latest reiserfsprogs and it fails **
** please email bug reports to reiserfs-list@namesys.com, **
** providing as much information as possible -- your **
** hardware, kernel, patches, settings, all reiserfsck **
** messages (including version), the reiserfsck logfile, **
** check the syslog file for any related information. **
** If you would like advice on using this program, support **
** is available for $25 at www.namesys.com/support.html. **
*************************************************************
Will read-only check consistency of the filesystem on /dev/hda10
Will put log info to 'stdout'
Do you want to run this program?[N/Yes] (note need to type Yes if you do):Yes
###########
reiserfsck --check started at Wed Sep 14 08:54:17 2005
###########
Replaying journal..
Reiserfs journal '/dev/hda10' in blocks [18..8211]: 0 transactions replayed
Checking internal tree..finished
Comparing bitmaps..finished
Checking Semantic tree:
finished
No corruptions found 注:没有发现错误;
There are on the filesystem:
Leaves 2046
Internal nodes 15
Directories 130
Other files 2305
Data block pointers 1863657 (70565 of them are zero)
Safe links 0
###########
reiserfsck finished at Wed Sep 14 08:54:33 2005
###########

对于fsck.ext2和fsck.ext3常用的几个选项:

-p Automatic repair (no questions) 注:自动修复文件系统存在的问题;
-y Assume "yes" to all questions 注:如果文件系统有问题,会跳出提示是否修复,如果修复请按y;
-c Check for bad blocks and add them to the badblock list 注:对文件系统进行坏块检查;这是一个极为漫长的过程;
-n Make no changes to the filesystem 注:不对文件系统做任何改变,只要扫描,以检测是否有问题;

举例:比如 /dev/hda6 (文件系统是ext3的),我想扫描并自动修复;

[root@localhost beinan]# fsck.ext3 -p /dev/hda6

注意: 针对不同文件系统,最好用相应的工具;虽然有时fsck 在不加参数的情况下能识别不同的文件系统;

对于不同工具的最为详细的参数,请参看--help或者man ,谢谢。。


后记:

创建文件系统和加载文件系统就算写的差不多了;再高深的可能也不是我所能写的。为了写文件系统系统的挂载,我已经写过几篇文档。可能还得需补充几篇短小文档,以及还有一个总结性的文档;

比如Fedora Core 4.0 默认安装不支持创建reiserfs 文件系统,解决办法是安装reiserfs-utils ,这也是需要补充的;


附录:

《Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍》
《实例解说 fdisk 使用方法》
《在Fedora core 4.0 加载NTFS和FAT32分区详述》
《合理规划您的硬盘分区》
《系统引导过程及硬盘分区结构论述》
《Fedora Core 4.0 HAL配置即插即用移动存储(USB及1394)的实践》

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7104/viewspace-133952/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7104/viewspace-133952/

没有更多推荐了,返回首页