美文网首页
Linux 文件与目录

Linux 文件与目录

作者: 404Not_Found | 来源:发表于2021-06-24 07:41 被阅读0次
  • 作者: 雪山肥鱼
  • 时间:20210625 06:39
  • 目的:I/O device
# 文件与目录
# 相关API介绍
  ## 创建文件
  ## 读写文件
  ## 读写文件,不按顺序
  ## fsync() 强行写入
  ## 

文件 与 目录

每个文件在底层都会有一个 low - level 名字 即 inode number。从OS的角度来看是不知道你存储的文件格式的,是视频?音频? 还是代码?并不关心。读数据就完事儿了

目录与文件相似,也有 low-level 的名字。但是low-level的内容比较特殊。是一个pairs

  • 目录名
  • inode
    比如有目录 foo,则 ("foo", 10) 影射了目录名与inode.

目录中的每一项要么是文件,要么是其他目录。通过目录套目录的方式,可以构建目录树,存放了文件与目录。


目录树.png

相关API 介绍

创建文件

int fd = open("foo", O_CREAT|O_WRONLY|O_TRUNC, SIRUSR|S_IWUSR);

文件描述符 fd file descriptor.
fd 是一个整数,每个进程独有,在linux中用fd去访问文件资源。一个文件被打开,只要你获得许可,就可以利用fd去读写文件。

  • 这就让fd成为了一种能力或者说权限
  • 也可以将fd认为一个指针,指向文件句柄,即吻技安资源。

读写文件

利用strace 去追踪函数的系统调用

strace cat foo
图片.png

实际的输出要比上图多很多。

大文件的拷贝可以 尝试 dd

strace dd if=a.out of=b.out //以块大小拷贝文件

读写文件,不按顺序

通常的读写文件都是从第一行读到最后一行。但是也会有业务需求从中间,或者文件的某个位置开始操作。
比如,在文本中构建了索引,并利用它来寻找特定的单词。

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

参数 whence,搜索执行的方式

  • SEEK_SET
    the offset is set to offset bytes, 设置到 offset
  • SEEK_CUR
    the offset is set to its current location plus offset bytes, 当前位置+offset
  • SEEK_END
    the offset is set to the size of file plus offset bytes, 文件结尾处 + offset 位置

lseek 不会 导致磁盘I/O的自动发生
lseek只是修改内存中的变,这个变量代跟踪了(即返回值 offset)进程,下一个读取或写入的偏移量。lseek 肯定会导致在即将进行的读取或写入中进行搜索。但不会导致任何磁盘I/O 的发生。**也就是说 只是纯粹的定位功能,并不代表主动向disk提出I/O请求。

当发送给disk 的读写 与上次读写不在同一个磁道上,才会出现磁盘寻道,磁头才会移动。

fsync() 强行写入

调用write() 只是告诉文件系统,请在将来的某个时刻,将数据写进磁盘。并不会立即写入,只是将内容写在buffer中。何时写入 由OS决定。所以会有丢掉数据的风险。
但是类似数据库这种系统,需要将文件内容立即写入

int fd = open("/root/.../foo", O_CREAT|O_WRONLY|O_TRUNC);
assert(fd > -1);
int rc = wirte(fd, buffer, size);
assert(rc == size);
rc = fsync(fd);
assert(rc == 0);

在某些情况,fsync还需要包含绝对路径,因为同时也要修改目录信息。细节的忽略,会导致应用程序级别的错误。

文件的重命名

mv 操作实际上调用的是 系统api: rename(char * old, char * new) 。
是一种原子操作。

获取文件信息

除了访问文件的内容,文件也有自己的信息。这些信息就是文件的 metadata 元数据。可以使用state or fstate命令你个查看

sturct stat {
  dev_t     st_dev; //所处设备
  ino_t      st_ino; // inode number
  mode_t   st_mode; //权限
  nlink_t     st_nlink;; //numbers of hardlinks
  uid_t        st_uid; //user ID of owner
  gid_t        st_gid; //group id
  dev_t      st_rdev; //device id
  off_t        st_size;//total size, in bytes
  blksize_t  st_blksize;// file system I/O 中 block 大小(扇区组成的大小)
  blkcnt_t    st_blocks;  //分配了多少个 blocks
  time_t      st_atime  // 最后一次访问的时间
  time_t       st_mtime; //最后一次修改的时间
  time_t      st_ctime; //最后一次状态修改的时间
}
metadata of a file.png

每个文件系统都有 inode, inode number 指向一片文件资源信息。所以metadata中,我觉得最重要的就是这个信息。

创建目录

目录你是不能直接写的,因为目录的内容是 metadata. 你只能间接的去更新目录。比如在目录下新增文件。就会间接的更新目录。
mkdir创建目录会默认的隐藏两个文件

  • . 当前文件
  • .. 父目录

读目录

int main( int argc, char **argv) {
  DIR * dp = opendir(".");
  assert(dp != NULL);
  struct dirent *d;
  while((d = readdir(dp)) != NULL) {
    printf("%lu %s\n", (unsigned log) d-> d_ino, d->d_name);
  }
  closedir(dp);
  return 0;
  }
}

struct dirent {
char d_name[256]; //file name
ino_t d_ino; // inode number
off_t d_off; // offset to the next dirent
unsigned short d_reclen; // length of this record
unsigned char d_type
}

Hard link & Symbol link

Hard link

当执行 link(old file , new file) 的时候。 类似下图。


图片.png

其实几个文件同时hard linke 到文件资源。三者指向同一处。当file 的 内容更改了,三个文件同时更改。


hard link file.png

硬链接所创建出来的文件是 regular file。

所以 linux 的删除文件采用的时 unlink 的系统调用,当links内容

Symbol link

Symbol link

ln -s file.old file.new
  1. Symbol link 不会增加 links 的 count ,所以就不是一个 regular file
  2. Symbol link 的 类型是 l 我们把他想象成 windows上的 快捷方式就行
  3. 当把连接 指向的文件删除后会出现以下情况


    灰色了.png
  4. 软连接的大小 与 文件长度有关


    4b.png
    15b.png

挂载文件系统

制作文件系统
mkfs 创建 文件系统。 比如 ext3,
a. 已知设备的一个分区 /dev/sda1
b. 制作文件系统
c. mount 挂在文件系统

假设有一个未挂载的ext3 文件系统,存储在设备分区/dev/sda1 中。它的内容包括 根目录 和 两个子目录 a 和 b。每个子目录里都有一个 foo的文件。假设文件向挂在 /home/user 上。则:

mount  -t ext3 /dev/sda1 /home/users

然后可以访问 /home/users/a/foo

文件系统树上可以挂在很多不同的文件系统

  • ext3/4 (标准的基于磁盘的文件系统)
  • proc (用于访问当前进程信息的文件系统)
  • AFS (分布式文件系统)

相关文章

网友评论

      本文标题:Linux 文件与目录

      本文链接:https://www.haomeiwen.com/subject/hdsnyltx.html