与进程相关的文件系统

进程是通过文件描述符(file descriptor,fd)来访问文件的,每个进程最多能同时使用NR_OPEN个文件描述符,这个值在include/linux/limits.h中定义为1024。每一个进程用一个打开文件表files_struct来描述进程的文件描述符使用情况。每一个文件都有一个文件指针。

进程的task_struct中有文件系统相关的数据成员:

struct task_struct {

……

/* filesystem information */

      struct fs_struct *fs;

/* open file information */

      struct files_struct *files;

……

};

结构fs_struct给出了与进程相关的文件系统的信息,比如进程自己的当前工作目录,它的根目录等,这个结构的定义为:

---------------------------------------------------------------------

include/linux/fs_struct.h
struct fs_struct {

    int users;

    rwlock_t lock; /* 用于表中字段的读/写自旋锁 */

    int umask; /* 当打开文件设置文件权限时所使用的位掩码 */

    int in_exec;

    struct path root, pwd;

};

---------------------------------------------------------------------

其中path结构的root和pwd两个成员分别描述了进程最常用到的两个目录的信息,即根目录和当前目录,path结构定义如下:

---------------------------------------------------------------------

include/linux/path.h
struct path {

    struct vfsmount *mnt;

    struct dentry *dentry;

};

---------------------------------------------------------------------

mnt:描述目录所安装的文件系统对象

dentry:描述目录的目录项

还有一个表表示进程打开的文件,即task_struct结构的files_struct类型的files字段。它给出了所有的进程描述符的使用情况,其file结构指针数组成员给出了文件描述符的信息,其定义如下:

---------------------------------------------------------------------

include/linux/fdtable.h
struct files_struct {

  /*

   * read mostly part

   */

    atomic_t count; /* 共享该表的进程数目 */

    /* 文件描述符表 */

    struct fdtable *fdt;

    struct fdtable fdtab;

  /*

   * written part on a separate cache line in SMP

   */

    /* 用于表中字段的读/写自旋锁 */

    spinlock_t file_lock ____cacheline_aligned_in_smp;

    int next_fd; /* 所分配的最大文件描述符加1 */

    /* 执行exec() 时需要关闭的文件描述符的集合 */

    struct embedded_fd_set close_on_exec_init;

    /* 文件描述符的初始集合 */

    struct embedded_fd_set open_fds_init;

    /* 文件对象指针的初始化数组 */

    struct file * fd_array[NR_OPEN_DEFAULT];

};

---------------------------------------------------------------------

在新的管理文件描述符的无锁模型中,锁机制是基于RCU的。文件描述表包含多个成员——fd sets(open_fds 和 close_on_exec, 文件指针数组, 文件描述符集和文件指针数组的大小)。为了使更新在一个无锁的读者看来是原子的,则文件描述符表的所有元素被放在一个单独的结构——struct fdtable中。

即,fdtable结构是进程的文件描述符表,其定义如下:

---------------------------------------------------------------------

include/linux/fdtable.h
struct fdtable {

    unsigned int max_fds;

    struct file ** fd;      /* current fd array */

    fd_set *close_on_exec;

    fd_set *open_fds;

    struct rcu_head rcu;

    struct fdtable *next;

};

---------------------------------------------------------------------

fd字段指向文件对象指针数组。该数组的长度存放在max_fds中。通常,fd字段指向files_struct的fd_array字段,该字段包含32个文件对象指针。如果进程打开的文件数目多于32个,内核就分配一个新的、更大的文件指针数组,并将其地址放在fd中,内核也同时更新max_fds字段的值。

对于在fd数组中有元素的每个文件来说,数组的索引就是文件描述符。Unix进程将文件描述符作为主文件标识符。两个文件描述符可以指向同一个打开的文件。

进程不能使用多于NR_OPEN个文件描述符。open_fds字段最初包含open_fds_init字段的地址,open_fds_init表示当前已打开文件描述符的位图。max_fds字段存放位图中的位数。

 

fd_set结构是文件描述符集,它将同一种情况下的多个文件描述符放在一起。在include/linux/types.h有中定义:

typedef __kernel_fd_set     fd_set;

__kernel_fd_set结构在include/linux/posix_types.h中定义:

typedef struct {

   unsigned long fds_bits [__FDSET_LONGS];

} __kernel_fd_set;

其中与__FDSET_LONGS有关的一些宏:

#define __NFDBITS  (8 * sizeof(unsigned long))

#undef __FD_SETSIZE

#define __FD_SETSIZE  1024

#undef __FDSET_LONGS

#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)

embedded_fd_set结构是小的文件描述符集,它将同一情况下的文件描述符放在一起,只能存放unsigned long类型位数个文件描述符,不过,这对于许多进程已经足够了。

/*

 * The embedded_fd_set is a small fd_set,

 * suitable for most tasks (which open <= BITS_PER_LONG files)

 */

struct embedded_fd_set {

   unsigned long fds_bits[1];

};

  根文件系统首先是一种文件系统,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所mount的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。

  我们首先从主机上所安装的Linux操作系统中了解一些根文件系统的信息。比如在笔者工作的Linux桌面系统中可以得到下面的结果:

  # mount

  /dev/hda2 on / type ext3 (rw)

  none on /proc type proc (rw)

  /dev/hda1 on /boot type ext3 (rw)

  none on /dev/pts type devpts (rw,gid=5,mode=620)

  none on /dev/shm type tmpfs (rw)

  # df

  Filesystem           1K-blocks      Used Available Use% Mounted on

  /dev/hda2             16216016   5667*   9724600  37% /

  /dev/hda1               101089      9321     8*9  10% /boot

  none                     63028         0     63028   0% /dev/shm

  从上面的mount命令我们可以看到,在桌面Linux中,根文件系统”/”被mount到/dev/hda2设备上,文件系统类型为ext3,属性为rw即可读写。从df命令则可以得到更多根文件系统使用空间的相关信息。

  根文件系统一直以来都是所有类Unix操作系统的一个重要组成部分,也可以认为是嵌入式Linux系统区别于其他一些传统嵌入式操作系统的重要特征,它给Linux带来了许多强大和灵活的功能,同时也带来了一些复杂性。我们需要清楚的了解根文件系统的基本结构,以及细心的选择所需要的系统库、内核模块和应用程序等,并配置好各种初始化脚本文件,以及选择合适的文件系统类型并把它放到实际的存储设备的合适位置。

  根文件系统的基本目录结构

  Linux的根文件系统以树型结构组织,包含内核和系统管理所需要的各种文件和程序,一般说来根目录”/”下的顶层目录都有一些比较固定命名和用途。

  下面列出了一个Linux根文件系统中的比较常见的目录结构:

  /bin 存放二进制可执行命令的目录

  /dev 存放设备文件的目录

  /etc 存放系统管理和配置文件的目录

  /home 用户主目录,比如用户user的主目录就是/home/user,可以用~user表示

  /lib 存放动态链接共享库的目录

  /sbin存放系统管理员使用的管理程序的目录

  /tmp 公用的临时文件存储点

  /root 系统管理员的主目录

  /mnt 系统提供这个目录是让用户临时挂载其他的文件系统。

  /proc 虚拟文件系统,可直接访问这个目录来获取系统信息。

  /var 某些大文件的溢出区

  /usr 最庞大的目录,要用到的应用程序和文件几乎都在这个目录。

  对于经常使用Linux系统的读者来说,这些目录大部分应该很熟悉了。不过有几个目录对初学者来说容易混淆,如/bin,/sbin,/usr/bin和/usr/sbin。这里简单介绍一下它们的区别:/bin目录一般存放对于用户和系统来说都是必须的二进制文件,而/sbin目录要存放的是只针对系统管理的二进制文件,该目录的文件将不会被普通用户使用。相反,那些不是必要的用户二进制文件存放在/usr/bin下面,那些不是非常必要的系统管理工具放在/usr/sbin下。此外,对于一些本地的库也非常类似,对于那些要求启动系统和运行的必须命令要存放在/lib目录下,而对于其他不是必须的库存放在/usr/lib目录就可以。

  对于嵌入式Linux系统的根文件系统来说,一般可能没有上面所列出的那么复杂,比如嵌入式系统通常都不是针对多用户的,所以/home这个目录在一般嵌入式Linux中可能就很少用到,而/boot这个目录则取决于你所使用的BootLoader是否能够重新获得内核映象从你的根文件系统在内核启动之前。一般说来,只有/bin,/dev,/etc,/lib,/proc,/var,/usr这些需要的,而其他都是可选的。

简单的来说,根文件系统包括虚拟根文件系统和真实根文件系统。在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。

原文地址:https://www.cnblogs.com/alantu2018/p/8447332.html

时间: 2024-10-16 14:45:53

与进程相关的文件系统的相关文章

Linux进程相关的内容及命令小结(一)

概念:进程,一个活动的程序实体的副本,拥有生命周期,一个进程可能包含一个或多个执行流: 进程的创建进程:  每个进程的组织结构是一致的:  内核在正常启动并且全面接管硬件资源之后,会创建一个Init的进程:而这个名叫init的进程负责用户空间的进程管理:  CentOS5及以前:SysV Init,Classic Init  在启动系统时,Init通过写脚本的方式来创建各个子进程:利用shell来实现,因此其执行速度非常慢:导致系统的启动速度和进程的创建速度都非常慢:  CentOS6:upst

linux内核中与进程相关的数据结构(基于linux-mainline-rc4)

1.进程描述符    struct task_struct {  volatile long state; ....... struct list_head tasks; ....... struct mm_struct *mm, *active_mm; ....... struct vm_area_struct *vmacache[VMACACHE_SIZE]; ...... pid_t pid; pid_t tgid; .......   }所在文件:include/linux/sched.

linux下多进程的文件拷贝与进程相关的一些基础知识

之前实现了用文件IO的方式可以实现文件的拷贝,那么对于进程而言,我们是否也可以实现呢? 答案是肯定的. 进程资源: 首先我们先回顾一下,进程的运行需要哪些资源呢?其资源包括CPU资源,内存资源,当然还有时间片资源,我们都知道进程是有 栈, 堆,  只读数据段,  数据段(已初始化的全局变量静态变量),bss段(未初始化的),   代码段还有一组寄存器值. 进程命令: 另外我们也可以通过 ps  -ef |grep 进程名命令来查看进程号(PID)和父进程号(PPID),之后还可以通过 ps au

APUE: 进程相关的系统调用和库函数

进程正常终止5种方式: 1.main函数返回 2.调用exit库函数 3.调用_exit或_Exit系统调用 4.最后一个线程从其启动例程返回 5.最后一个线程调用pthread_exit库函数 进程异常终止3种方式: 1.调用abort库函数,产生abort信号. 2.接到一个信号并终止 3.最后一个线程对取消请求做出响应 init进程:pid=1的进程,如果父进程先于子进程终止,子进程就被init进程收养. 孤儿进程:父进程先于子进程退出,子进程被init进程收养,这个子进程就是孤儿进程.

获取 窗口 进程 相关信息

GameHwnd:= FindWindow(nil,'对对碰角色版'); //得到进程ID GetWindowThreadProcessId(GameHwnd,GamePid); //得到进程句柄 GameProcess:= OpenProcess(PROCESS_VM_READ or PROCESS_VM_WRITE,False,GamePid); //读取进程内存 ReadProcessMemory(GameProcess,Pointer($0048F128),@sitnum,4,readb

关于linux操作系统中进程相关问题的学习笔记

关于linux操作系统中进程相关问题的学习笔记 1.摘要   进程的经典定义是一个执行中程序的实例.系统中的每个程序都运行在某个进程的上下文中(contest)中.上下文是由程序运行正确运行所需的状态组成的.这个状态包括存放在内存中的程序的代码和数据,它的栈.通用目的寄存器的内容.程序计数器.环境变量以及打开文件描述符合的集合.在本次学习笔记中,我是以linux为例,学习了以下三个方面的知识:操作系统如何组织进程.进程状态如何转换以及进程是如何调度的.在最后我还谈了下自己对操作系统进程模型的一些

跟结束进程相关的那些信号

前言 项目中在使用kube-keepalived-vip时遇到了keepalived相关的Bug, 原本计划测试最新版的keepalived看是否存在同样的问题. 在将keepalived升级到当前最新版本v2.0.7之后发现每次执行kubectl delete pod <kube-keepalived-vip pod>都会出现segfault的内核错误, 且较大概率会连带出现keepalived的僵尸进程, 但对比发现通过手动执行kill -9结束keepalived进程却没有这个问题. 翻

在Linux 中如何从进程相关的文件描述中恢复数据

在Linux中误删除了某个文件,但是 ps-ef|grep 文件名 发现某个进程还在使用该文件,那么可以通 过以下方式恢复文件. 例如:创建一个简单文件/tmp/test.txt, 随便向里面写点内容 两个client模拟,client1 负责打开文件less /tmp/test.txt(模拟占用线程) client2 负责恢复文件,恢复步骤(均在client2上执行) 1. 查看/tp/test.txt被占用的进程id [[email protected] tmp]# ps -ef|grep

统计 Linux 进程相关数量信息

#!/bin/bash # 统计 Linux 进程相关数量信息 running=0 sleeping=0 stoped=0 zombie=0 # 在 proc 目录下所有以数字开始的都是当前计算机正在运行的进程的进程 PID # 每个 PID 编号的目录下记录有该进程相关的信息 for pid in /proc/[1‐9]* do procs=$[procs+1] stat=$(awk '{print $3}' $pid/stat) # 每个 pid 目录下都有一个 stat 文件,该文件的第