系统编程概念与文件属性

本文是作者阅读TLPI(The Linux Programer Interface的总结),为了突出重点,避免一刀砍,我不会过多的去介绍基本的概念和用法,我重点会去介绍原理和细节。因此对于本文的读者,至少要求读过APUE,或者是实际有写过相关代码的程序员,因为知识有点零散,所以我会尽可能以FAQ的形式呈现给读者。

系统编程概念

什么是udev机制?

我们都知道在Linux中一切都是文件,添加的设备都会在/dev/目录下游一个唯一的文件与之对应,在Linux的早期版本中/dev包含了系统所有可能的条目,即使某些设备实际并未与系统连接,这意味着/dev会包含数以千计的未使用设备项,从未导致了两个缺点,其一,对于需要扫描该目录内容的应用而言,降低了程序的执行速度;其二,根据该目录下的内容无法发现系统实际存在哪些设备。Linux2.6运用udev程序解决了上述问题,udev 以守护进程的形式运行,通过侦听内核发出来的uevent来管理 /dev目录下的设备文件,可以动态的创建设备文件,还可以自定义设备的命名规则。

能否在多个挂载点挂载相同的设备?

内核版本在2.4之前,一个文件系统只能挂载于单个挂载点,从内核版本2.4开始,可以将一个文件系统挂载于文件系统内的多个位置。由于每个挂载点下的目录子树内容都相同,在一个挂载点下对目录子树所做的改变,同样见诸于其它挂载点。

[[email protected] data]# mkdir /data/mnt1
[[email protected] data]# mkdir /data/mnt2
[[email protected] data]# mount /dev/sdb1 /data/mnt1/
[[email protected] data]# mount /dev/sdb1 /data/mnt2/
[[email protected] data]# ls /data/mnt1/
1.c  data  ls  new_data
[[email protected] data]# ls /data/mnt2
1.c  data  ls  new_data
[[email protected] data]# touch /data/mnt1/test
[[email protected] data]# ls /data/mnt2
1.c  data  ls  new_data  test

什么是绑定挂载?

始于内核版本2.4,Linux支持了创建绑定挂载,绑定挂载是指在文件系统层级的另一处挂载目录或文件,这将导致文件或目录在两处同时可见,绑定挂载类似于硬链接,但是存在两个方面的差异:

  • 绑定挂碍可以跨越多个文件系统挂载点
  • 可针对目录执行绑定挂载
[root@localhost bind]# mkdir mnt1 mnt2
[root@localhost bind]# touch mnt1/zzz
[root@localhost bind]# mount --bind mnt1 mnt2           //进行目录的绑定挂载
[root@localhost bind]# ls mnt2/
zzz

[root@localhost bind]# touch test1 test2
[root@localhost bind]# echo "1111" > test1
[root@localhost bind]# mount --bind test1 test2         //进行文件的绑定挂载
[root@localhost bind]# cat test2
1111

什么是共享子树(shared subtree)的概念?

自Linux版本2.4.19以后,内核支持针对每个进程的挂载命名空间,这意味着每个进程都可能拥有属于自己的一组文件系统挂载点。这意味着每个进程都可能拥有属于自己的一组文件系统挂载点。比如在进程A的视角下,只能看到/dev/sda1挂载到/根目录下,在进程B的视角下,只能看到/dev/sda2挂载到/home根目录下。在支持了这个特性后就需要考虑下面一个场景:一个进程想要有自己的挂载命名空间,但是仍然想访问CD-ROM所在的挂载点,这个挂载点是在初始的挂载空间中的。其它的挂载空间是看不到这个挂载点的,因此共享子树语义提供了必要的机制来完成上面的这个场景。共享子树提供了四个不同的挂载标志来支持。

  • shared mount MS_SHARED

    shared mount挂载可以将一个挂载点复制多份,并且后续在任何拷贝的挂载点中再次挂载都会被传播到其他副本。

[[email protected] ~]# mount --make-shared /data/              //设置/data挂载点为shared mount
[[email protected] ~]# mkdir /tmp/data
[[email protected] ~]# mount --bind /data/ /tmp/data/          //进行复制
[[email protected] ~]# ls /data/
test1  test2
[[email protected] ~]# ls /tmp/data/
test1  test2
[[email protected] ~]# touch /data/aaa                         //两个挂载点共享同一份内容,相互影响
[[email protected] ~]# ls /tmp/data/
aaa  test1  test2
[[email protected] ~]# mkdir /tmp/data/mnt                     //创建一个新的目录
[[email protected] ~]# mount /dev/sdb1 /tmp/data/mnt/          //创建新的挂载点
[[email protected] ~]# ls /tmp/data/mnt/
1.c  data  ls  new_data
[[email protected] ~]# ls /data/mnt/                           //发现后续新创建的挂载点也会变成shared mount
1.c  data  ls  new_data
  • slave mount MS_SLAVE

    slave mount挂载可以将一个挂载点复制多份,但是后续在任何拷贝的挂载点中再次挂载不会被传播到其他副本。并且卸载事件也不会传播到其他挂载点,但是如果是在master挂载点上进行挂载,那么这个事件会被传播到所有的slave mount。

[[email protected] /]# mount --make-shared /data/              //slave mount需要有一个master mount,并且master必须是shared mount
[[email protected] /]# mount --bind /data/ /tmp/data/
[[email protected] /]# mount --make-slave /tmp/data/           //设置为slave mount
[[email protected] /]# mount /dev/sdb1 /tmp/data/mnt/          //挂载事件并不传播
[[email protected] /]# ls /tmp/data/mnt/
1.c  data  ls  new_data
[[email protected] /]# ls /data/mnt/
[[email protected] /]# touch /data/zzz                         //共享同一份数据
[[email protected] /]# ls /tmp/data/
aaa  mnt  test1  test2  zzz
[[email protected] data]# unmount /tmp/data/mn1                //卸载
[[email protected] data]# mount /dev/sdb1 /data/mnt/           //在master mount进行挂载
[[email protected] data]# ls /data/mnt/
1.c  data  ls  new_data
[[email protected] data]# ls /tmp/data/mnt/                    //发现会传播到slave mount
1.c  data  ls  new_data
  • private mount MS_PRIVATE

    private mount挂载,这和早期的mount是一样的,也是某些系统的默认挂载类型,可以进行绑定挂载,但是无论在哪个挂载点再次挂载,都不会进行挂载事件的转发和传播。

[[email protected] data]# mount --make-private /data/          //设置private mount
[[email protected] data]# mount --bind /data/ /tmp/data/       //进行绑定挂载
[[email protected] data]# mount /dev/sdb1 /data/mnt/           //再次挂载
[[email protected] data]# ls /data/mnt/
1.c  data  ls  new_data
[[email protected] data]# ls /tmp/data/mnt/                    //没有传播到其他的挂载点
[[email protected] data]# 
  • unbindable mount MS_UNBINDABLE

    无法进行绑定挂载,一个设备只能挂载到一个挂载点。

注: 更多的内容详见Documentation/sharedsubtree.txt

如何获取文件系统相关的信息?

       #include <sys/statvfs.h>
       int statvfs(const char *path, struct statvfs *buf);
       int fstatvfs(int fd, struct statvfs *buf);

指定一个路径,或者一个fd,会返回这个文件所在的文件系统的相关属性信息,使用statvfs这个结构体来表示,该结构体组成如下:

           struct statvfs {
               unsigned long  f_bsize;    /* file system block size */
               unsigned long  f_frsize;   /* fragment size */
               fsblkcnt_t     f_blocks;   /* size of fs in f_frsize units */
               fsblkcnt_t     f_bfree;    /* # free blocks */
               fsblkcnt_t     f_bavail;   /* # free blocks for unprivileged users */
               fsfilcnt_t     f_files;    /* # inodes */
               fsfilcnt_t     f_ffree;    /* # free inodes */
               fsfilcnt_t     f_favail;   /* # free inodes for unprivileged users */
               unsigned long  f_fsid;     /* file system ID */
               unsigned long  f_flag;     /* mount flags */
               unsigned long  f_namemax;  /* maximum filename length */
           };

文件属性

atime,ctime,mtime的区别?

  • atime 文件读取和文件的执行都会导致atime的变化。
  • ctime 只要文件的inode信息发生了变化,ctime随之也会发生变化,因此atime变化通常也会导致ctime变化,因为atime是inode的组成之一
  • mtime 文件内容发生了变化会导致mtime更新,通常mtime的更新会导致ctime发生变化,因为mtime变化说明文件的大小发生了变化,而文件的大小属于inode的组成之一

注: 每次文件的访问和写入,都会影响上述几个时间的变化,inode的信息最终会保存在本地磁盘,因此如果关闭上述几个时间的更新操作的话,那么势必会减少磁盘的操作次数减少不必要的性能开销。在打开文件的时候指定O_NOATIME即可关闭对atime的更新操作,也可以在挂载文件系统的时候指定相关的选项来关闭时间的更新操作。具体可以查询mount的man文档。

目录权限的rwx的含义?

  • 读权限 可以列出目录之下内容(也就是都目录的内容,目录中内容就是文件名和对应inode的信息),但是
  • 写权限 在目录内创建,删除文件(注: 删除一个文件对文件本身无需要任何权限)
  • 可执行权限 可访问目录中的文件,可以切换到该目录,可以配合写权限在目录中添加或删除文件。

拥有对目录的读权限,仅仅只能列出目录中的内容,要想访问目录中这些文件的i节点信息,还需要有目录的执行权限才可以。

拥有对目录的可执行权限,而无读权限,只要知道目录内的文件名称,仍可以直接对其访问,

要想在目录中添加或删除文件,需要同时拥有对该目录的执行和写权限,被删除文件本身的权限不起作用

时间: 2024-08-11 03:38:32

系统编程概念与文件属性的相关文章

Linux系统编程之访问文件夹及其文件属性

1. 文件夹操作:opendir, readdir, closedir 2. 文件属性:lstat 3. 实现功能:获取指定文件夹下所有的文件(使用递归),因此就能计算所有文件大小之类的啦... 代码示例如下: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/stat

《Linux/Unix系统编程手册》读书笔记9(文件属性)

<Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有更深入的研究一定会写出来. 下图为磁盘分区与文件系统的关系 文件系统中的文件(目录)在i-node表上都有唯一的记录(i-node).i-node通过数据块指针指向数据块,这些数据块就是该i-node对应的文件的数据. i-node与数据块的关系如下: 因为Linux支持很多类型的文件系统,但是每种文件系统的

嵌入式 Linux系统编程(四)——文件属性

嵌入式 Linux系统编程(四)--文件属性 一.文件属性概述 Linux 文件的属性主要包括:文件的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.文件属性示例如下: 多个文件属性查看: ls -lih 1341714 -rw-r--r-- 1 root root 2.5K May 28 10:24 bit_marco.c 1341718 -rw-r--r-- 1 root root 2.1K May 28 09:08 bit_marco.c~ 1341706

Linux系统编程_3_文件属性

1.Linux中stat结构体包含了一个文件的各种属性. struct stat { dev_t         st_dev;       //文件的设备编号 ino_t         st_ino;       //节点 mode_t        st_mode;      //文件的类型和存取的权限 nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1 uid_t         st_uid;       //用户ID gid_t  

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

Linux系统编程【转】

转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准C库.系统调用封装.线程库.基本应用工具 gcc: 1.2 模块接口 API:应用程序编程接口,源代码级别,能通过编译,由标准C语言定义,libc来实现 ABI:应用程序二进制接口,二进制级别,能正常运行,关注调用约定.字节序.寄存器使用.系统调用.链接.二进制格式等,很难实现 1.3 错误处理 <

黑马程序员-----面向对象编程概念

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ----- 第一讲   面向对象编程概念 本小节知识点: 1.[了解]编程的实质是什么? 2.[掌握]面向对象的基本概念 类    包    接口      继承      多态 ( 面向过程是强调我们要做一件事情有哪些步骤, 面向对象是强调我们做一件事

系统编程是什么

目录(?)[+] 部分摘自<Linux System Programming >作者: Robert Love 刘建文略译(http://blog.csdn.net/keminlau) KEY:系统论 系统编程 System Programming 过去的Unix编程是没有系统不系统之分的.即便是开发 X Window也是在系统级(system-level)编程,看到系统的所有API.现代的操作系统编程有所谓[系统级编程],使用与[应用编程]不同的API(System programming

浅谈C语言嵌入式系统编程注意事项

C语言嵌入式系统编程注意事项之背景篇 本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具体的C语言编程技巧 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言开发过程的复杂性,它并不是嵌入式系统开发的一般选择.而与之相比,C语言--一种"高级的低级"语言,则成为嵌入式系统开发的最佳选择.笔者在嵌入式系统项目的开发过程中,一次又一次感受到C语言的精妙,沉