linux 文件系统

linux的文件系统是一个广义的文件系统,可以认为linux系统对任何设备和对象的操作都是等价于对文件的操作。

linux系统对所有可操作对象进行了高度的抽象,将其归纳为这么几类:

  1. 普通文件:就是狭义概念上的存储在磁盘中的文件,是纯粹的存储数据的文件,例如文本文件,图片文件,可执行文件等;

  2. 字符设备文件:通常指输入输出终端,键盘,串口等,通常可以用操作文件的方式来操作字符设备文件,因为对这类设备的读写其实是读写的字符流;

  3. 块设备文件:有硬盘,软盘和RAM等,块设备文件通常公国内存缓冲区读写数据,支持块数据读取和随机读取,读写性能更好;

  4. socket文件:网络通信的文件描述符,支持像操作普通文件一样操作网络数据的读写;

linux提供了虚拟文件系统架构,要求所有设备都提供一致的文件操作接口,方便用户像操作文件一样操作所有设备,因此可以说linux系统下,一切操作的都是文件。

文件描述符

文件描述符是对一个操作文件的抽象标识,它被用户空间和内核空间的枢纽共同使用。当用户空间对一个文件描述符进行操作时,例如对一个文件描述符进行操作时,当内核进行系统调用时,将根据该文件描述符找到对应的真实设备进行操作,并将结果返回用户空间。

文件描述符通常是一个整数标识,因此它根据系统不同,有一个上线值(通常是0-OPNE_MAX)。所以,我们在使用完一个文件后,应该尽快释放它(通常调用close函数)。

1. 打开文件和创建文件

头文件:sys/types.h sys/stat.h fcntl.h

int open(const char* filepath, int flags);

int create(const char* filepath, int flags, mode_t mode);

打开和创建成功返回一个文件描述符,失败返回-1。通常filepath的字符长度也会有限制,如果超出长度会被截断。

flags的选项:

  O_RDONLY (0 只读)

  O_WRONLY (1 只写)

  O_RDWR (2 读写)  

  O_APPEND (写操作追加到末尾)

  O_CREATE (如果文件不存在,创建一个,需要mode来设置权限)

  O_EXCL (查看文件是否存在。如果同时指定O_CREATE,并且文件已经存在,会返回错误)

  O_TRUNC (将文件长度截断为0)

mode的选项:

  S_IRWXU 用户有读写和执行权限

  S_IRUSR 用户有读权限

  S_IWUSR 用户有写权限

  S_IXUSR 用户有执行权限

  S_IRWXG 组用户有读写和执行的权限

  S_IRGRP 组用户有读权限

  S_IWGRP 组用户有写权限

  S_IXGRP 组用户有执行权限

  S_IRWXO 其他用户有读写和执行权限

  S_IROTH 其他用户有读权限

  S_IWOTH 其他用户有写权限

  S_IXOTH 其他用户有执行权限

对文件的操作默认都是阻塞的,即必须等到文件操作返回才能继续。

2. 关闭文件

int close(int fd);

如果成功返回0,失败返回-1。在关闭文件后,系统可以再次使用该文件描述符,如果使用后不关闭,进程也会在退出时关闭所有打开的文件描述符,但是可能造成文件描述符不够用的情况,导致无法再打开新的文件。

3. 读取文件

头文件:unistd.h

ssize_t read(int fd, void* buf, size_t count);

从文件fd读取count字节的字节流并存到buf指向的内存地址中。读取成功返回读取成功的字节数,如果返回0标识读取到文件末尾,读取失败返回-1。ssize_t的定义是依赖平台,可能是long或者int。实际情况返回的字节数可能小于count指定的大小,表示无法读取到count大小的字节,已经将文件中当前剩余的所有字节全部读取出来。

4. 写文件

头文件:unistd.h

ssize_t write(int fd, const void* buf, size_t count);

向文件fd中写入指定count大小的数据,数据来自buf指向的内存地中的字节流。如果成功返回写入成功的字节数,失败返回-1。

5. 文件偏移

头文件:sys/types.h unistd.h

off_t lseek(int fd, off_t offset, int whence);

文件偏移量:文件操作的当前位置,所有文件操作都是从文件偏移量开始的。如果在打开文件的时候,指定了O_APPEND,文件偏移量就是文件的长度,即末尾处,否则偏移量为0,即文件起始位置。

lseek函数可以更新文件fd的偏移量,offset可为整数或负数,表示相对whence的偏移大小。

whence选项:

  SEEK_SET:文件的开始位置;

  SEEK_CUR:文件的当前位置;

  SEEK_END:文件的结尾位置;  

如果函数执行成功返回偏移量的值,可能为负数,失败返回-1。

当向文件写数据时,如果使用lseek设置偏移量超出了文件大小,当继续向文件写入数据时,中间的空白字节会用‘\0‘填充。

6. 获取文件状态

头文件 sys/types.h sys/stat.h unistd.h

int stat(const char* path, struct stat* buf);

int fstat(int fd, struct stat* buf);

int lstat(const char* path, struct stat* buf);

如果获取成功返回0,失败返回-1。文件状态的数据写入buf指向的数据结构中。

7. 文件空间映射

头文件:sys/mman.h

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

该函数将文件映射到内存中,然后就可以采用内存操作,不必再使用read和write函数,性能更好。

start:内存的开始地址,但是通常不需要指定,设置为NULL,表示由系统决定映射的地址,在返回值中体现;

length:表示映射的地址长度,即从文件映射到内存中的数据大小;

prot:映射区域的保护方式,可以由多个值进行组合;

  PROT_EXEC 可执行区域

  PROT_READ 可读取区域

  PROT_WRITE 可写区域

flags:设定映射区域的类型,选项和对映射区域是否可以操作,可以由多个值进行组合;

  MAP_FIXED 如果参数start指定的地址无法建立映射,映射会失败,通常不指定该值,将start设置为NULL,由系统选定映射地址;

  MAP_SHARED:映射区域是多进程共享的,对映射区域的操作都会影响原来的文件;

  MAP_PRIVATE:映射区域的写操作都会产生一个副本,并且写操作不会影响原来的文件;

  MAP_DENYWRITE:对文件的写入操作被禁止,只能通过对映射区域的操作来实现对文件的操作;

  MAP_LOCKED:将映射区域锁定,不会被虚拟内存重置;

int munmap(void* start, size_t length);

取消文件映射,通常在映射区域操作完成后调用,然后关闭文件;

 1 int fd = open("leo.txt", O_RDWR | O_CREAT, S_IRWXU);
 2         if (fd == -1) {
 3                 printf("create file failed.");
 4         }
 5         else {
 6                 char buf[] = "leo is me!";
 7                 write(fd, buf, strlen(buf));
 8
 9                 char* ptr = (char*)mmap(NULL, strlen(buf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
10                 if ((char*)-1 == ptr) {
11                         printf("mmap failed.");
12                 }
13                 else {
14                         memcpy(ptr, "123", 3);
15                         munmap(ptr, strlen(buf));
16                         close(fd);
17                 }
18         }

8. 文件属性操作

头文件:unistd.h fcntl.h

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd, struct flock* lock);

对文件的属性进行修改,失败返回-1。

fcntl的功能:

  复制文件描述符:cmd = F_DUPFD,返回值是新的文件描述符。新的文件描述符是大于或等于第三个参数的尚未使用的文件描述符中的最小值;

  获取或设置文件描述符:cmd = F_GETFD/F_SETFD;

  获取或设置文件状态值:cmd = F_GETFL/F_SETFL;

    文件状态值:

    O_RDONLY 只读

    O_WRONLY 只写

    O_RDWR 读写

    O_APPEND 将写入添加到末尾

    O_NONBLOCK 非阻塞方式

    O_SYNC 异步方式

    O_ASYNC 同步方式

    正确获得O_RDONLY,O_WRONLY和O_RDWR标志位的方法是和O_ACCMODE进行与操作才能获得;

int fd = open("leo.txt", O_RDWR | O_CREAT, S_IRWXU);
if (fd == -1) {
  printf("create file failed.");
}
else {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) {
    printf("get flags failed123333.");
  }
  else {
    int accmode = flags & O_ACCMODE;
    if (accmode == O_RDONLY) {
      printf("file only read. \n");
    }
    else if (accmode == O_WRONLY) {
      printf("file only write \n");
    }
    else if (accmode == O_RDWR) {
      printf("file can be read and write. \n");
  }
  else
  {
    printf("accmode invalid. \n");
  }


  flags |= O_APPEND;
  int result = fcntl(fd, F_SETFL, &flags);
  if (result < 0) {
    printf("set file flag failed. \n");
  }


  int newflags = fcntl(fd, F_GETFL, 0);
  if (newflags & O_APPEND) {
    printf("file append. \n");
  }
  if (newflags & O_NONBLOCK) {
    printf("file non block. \n");
  }


    close(fd);
  }
}

  获取或设置文件信号的发送对象:cmd = F_GETTOWN/F_SETTOWN/F_GETSIG/F_SETSIG;

int uid = fcntl(fd, F_GETOWN); // 获取接受信号SIGIO和SIGURG的进程id
int uid = fcntl(fd, F_SETOWN, 10000); // 将接受信号SIGIO和SIGURG的进程设置为id为10000的进程

  获取或设置记录锁:cmd = F_GETLK/F_SETLK/F_SETLKW;

  获取或设置文件租约:cmd = F_GETLEASE/F_SETLEASE;

9. 文件输入输出控制

头文件:sys/iotl.h

int ioctl(int device, int request, ...);

通过向设备发送命令来控制设备,失败返回-1。device为一个打开的设备号,其他参数根据设备驱动程序来决定。

#include "stdlib.h"
#include "stdio.h"
#include <unistd.h>
#include <fcntl.h>
#include <linux/cdrom.h>
#include <sys/ioctl.h>

int main(void)
{int fd = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
    if (fd > 0) {
        if (!ioctl(fd, CDROMEJECT, NULL)) {
            printf("ok \n");
        }
        else {
            printf("fail \n");
        }
    }

    getchar();

    return 0;
}
时间: 2025-01-17 02:36:33

linux 文件系统的相关文章

linux 文件系统笔记

文件格式: windows:PE linux:  ELF 文件系统: rootfs FHS:规定linux应该创建哪些目录 /下的目录结构: /boot: 系统启动相关的文件,如内核,initrd,以及 grub(bootloader) /dev :设备文件(例如:光盘,cdrom) 类型: 块设备:随机访问, 数据块 字符设备:线性访问, 以字节为单位 设备号:主设备号(major),次设备号(minor) /etc:  配置文件(绝大多数为纯文本格式) /home: 用户的家目录,默认为/h

【转】LINUX文件系统剖析

引自:http://www.ibm.com/developerworks/cn/linux/l-linux-filesystem/   在文件系统方面,Linux? 可以算得上操作系统中的 "瑞士军刀".Linux 支持许多种文件系统,从日志型文件系统到集群文件系统和加密文件系统.对于使用标准的和比较奇特的文件系统以及开发文件系统来说,Linux 是极好的平台.本文讨论 Linux 内核中的虚拟文件系统(VFS,有时候称为虚拟文件系统交换器),然后介绍将文件系统连接在一起的主要结构.

Linux文件系统

文件系统与目录结构 文件系统 1.文件和目录被组织成一个单根倒置数结构 2.文件系统从根目录下开始,用"/"表示 3.根文件系统(rootfs):root filesystem 4.文件名称区分大小写 5.以.开头的文件为隐藏文件 6.路径分隔符:/ 7.文件的两类数据: 元数据(metadata)和 数据(data) 8.文件系统分层结构:LSB (Linux Standard Base) 9.FHS(Filesystem Hierarchy System) 文件名规则 1.文件名最

linux文件系统索引节点浅析

索引节点,Inode是Index Node的缩写,存储于文件系统上的任何文件都可以用索引节点来表示,所以也可以说索引节点是整个linux文件系统的基础.操作系统在读取硬盘的时候不是一个块一个块的来读取信息,因为这样做的话效率太低,文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者.文件的创建日期.文件的大小等等.这种储存文件元信息的区域就叫做inode,中文译名为"索引节点". 在Linux系统中,文件系统主要分为两部分,

嵌入式 Linux根文件系统移植(一)——Linux文件系统简介

嵌入式 Linux根文件系统移植(一)--Linux文件系统简介 本文对文件系统分析的代码来源于linux 2.6.35.7版本. 一.文件系统的体系结构 文件系统是对存储设备上的数据和元数据进行组织的机制,便于用户和操作系统的交互.Linux支持多种文件系统,文件系统接口实现为分层的体系结构,将用户接口层.文件系统实现和操作存储设备的驱动程序分隔开.Linux文件系统的体系结构如下: 用户空间包含一些应用程序(例如,文件系统的使用者)和 GNU C库(glibc),为文件系统调用(打开.读取.

linux --&gt; 文件系统十问

文件系统十问 参考:http://djt.qq.com/article/view/620 关于Linux文件系统相关的问题: 1.机械磁盘随机读写时速度非常慢,操作系统是采用什么技巧来提高随机读写的性能的? 2.touch一个新的空文件占用磁盘空间吗? 占用的话占用多少? 3.新建一个空目录占用磁盘空间吗?占用多少?和新建一个文件相比,哪个占用的更大? 4.你知道文件名是记录在磁盘的什么地方吗? 5.文件名最长多长?受什么制约? 6.文件名太长了会影响系统性能吗?为什么会产生影响? 7.一个目录

linux文件系统学习总结

linux最优秀的特点在于它是多用户多任务的环境,而且对于linux来讲一切皆文件,提到文件这个概念就免不了提文件相关的权限与属性的概念,那相关文件的属性记录在硬盘的哪个地方呢?这就需要了解linux的文件系统是如何记录文件,如何读取文件. 大家都知道硬盘作为存储介质,如果要使用硬盘存储数据需要对硬盘进行分区,格式化之后才可以存储数据.那为什么要对硬盘进行分区呢?因为我们必须要告诉操作系统:"这块硬盘可以访问的区域是有A柱面到B柱面",只有这样,操作系统才能控制硬盘磁头去A~B范围内的

Vim,find,bash,Linux文件系统的特殊权限2015.8.30作业

一   Vim 1.vim的使用方法 1.1 三种模式化 编辑模式.输入模式.末行模式 1.2 模式转换 编辑模式 --> 输入模式: i:在当前光标所在字符的前面,转为输入模式 a:在当前光标所在字符的后面,转为输入模式 o:在当前光标所在行的下方,新建一行,并转为输入模式 I:在当前光标所在行的行首,转为输入模式 A:在当前光标所在行的行尾,转为输入模式 O:在当前光标所在行的上方,新建一行,并转为输入模式 输入模式 --> 编辑模式:ESC 编辑模式 --> 末行模式:: 末行模式

攻城狮在路上(叁)Linux(二十六)--- linux文件系统的特殊查看与操作

一.boot sector 与 super block的关系: 1.boot sector用于存放引导装载程序,占用1024个字节. 2.super block的大小也为1024字节. 3.若block大小为1k,则boot sector和super block各占一个block. 4.若block大于1K(2K/4K)时,则两者都位于第一个block中. 二.磁盘空间的浪费问题:暂不考虑. 三.利用GUN的parted命令进行分区行为: 因为fdisk不支持高于2TB的分区. 命令格式: pa

操作系统——linux文件系统初实现——为fileSystem添加驱动,让linux可以识别。

0.我的理解,所为驱动,就是用户可以通过自己的应用程序访问你的文件系统.而我恰恰相反. 1.我是谢了字符驱动,让我的fileSystem去做应用程序,同样可以被linux系统识别. 2.其实我对驱动理解也不深,暂且贴代码. 3.驱动程序: /*chardev.c 驱动程序*/ #include <linux/kernel.h> #include <linux/fs.h>/*for file-f_op*/ #include <linux/module.h> #includ