1.文件内核数据结构

一个打开的文件在内核中使用三种数据结构表示:

(1)文件描述符表

文件描述符标志

文件表项指针

(2)文件表项:

文件状态标志:读、写、追加、同步和非阻塞等状态标志

当前文件偏移量

i节点表项指针

引用计数器

(3)i节点

文件类型和对该文件的操作函数指针

当前文件长度

文件所有者

文件所在的设备、文件访问权限

指向文件数据在磁盘上所在位置的指针等。

2. 原子操作

(1)文件追加

打开文件时使用O_APPEND标志,进程对文件偏移量调整和数据追加成为原子操作。

O_APPEND

write(){    //write成为一个原子操作

1)从i节点中读取文件长度作为当前偏移量

2)往文件中写入数据

3)修改i节点中文件长度

}

内核每次对文件写之前,都将进程的当前偏移量设置为该文件的尾端,这样不再需要lseek来调整偏移量。

(2)文件创建:

对open函数的O_CREAT和O_EXCL的使用,若该文件存在,open将失败,否则创建该文件,并且使得文件是否存在的判定和创建过程成为原子操作。

3. I/O处理方式

3.1 I/O处理的五种模型

阻塞I/O模型:若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回,如:终端、网络设备的访问。

非阻塞模型:当请求的I/O操作不能完成时,则不让进行进程休眠,而且返回一个错误。如:open、read、write访问。

I/O多路转接模型:如果请求的I/O操作阻塞,且它不是真正的阻塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作,如:select函数。

信号驱动I/O函数:在这种模式下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。

异步I/O模型:在这种模式下,当一个描述符已准备好,可以启动I/O时,进程会通知内核,由内核进行后续处理,这种用法现在较少。

3.2 非阻塞I/O

低速系统调用时,进程可能会阻塞

非阻塞I/O确定操作(read、open、write)不阻塞,如果操作不能完成,则出错返回。

设定非阻塞的方式:1、使用open打开文件,设置O_NONBLOCK标志;2、如果一个文件已经打开,则使用fcntl修改文件状态标志。

4. 高级文件操作-文件锁

当多个用户共同使用、操作一个文件的时候,Linux通常采用的方法是给文件上锁,来避免共享资源产生竞争的状态。

文件锁按功能分为:1、共享读锁:文件描述符必须读打开;一个文件上了读锁,其他进程也可以上读锁进行读取。2、独占写锁:1、文件描述符必须写打开;一个进程上了写锁,其它进程就不能上写锁和读锁进行写操作。

文件锁按类型分为建议锁和强制性锁。建议锁要求上锁文件的进程都要检测是否有锁存在,并尊重已有的锁。强制性锁由内核和系统执行的锁。

fcntl不仅可以实施建议锁而且可以实施强制性锁。

4.1 加锁和解锁区域的注意点

该区域可以在当前文件尾端处开始或越过其尾端处开始,但是不能在文件起始位置之前开始或越过该起始位置。

如若l_len为0,则表示锁的区域从其起点(由l_start和l_whence决定)开始直至最大可能位置为止。也就是不管添写到该文件中多少数据,它都处于锁的范围。

为了锁整个文件,通常的方法是将l_start设置为0,l_whence设置为SEEK_SET,l_len设置为0。

4.2 锁的继承和释放

一个进程终止,它所建立的锁全部释放;

关闭一个文件描述符,此进程对应该文件的所有的锁都释放;

子进程不继承父进程的锁;

执行exec以后,新进程可以选择是否继承原来执行进程的锁。

5. 存储映射

存储映射是一个磁盘文件与存储空间的一个缓存相映射,对缓存数据的读写就相应的完成了文件的读写。

5.1 调用函数

 #include <sys/types.h>
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int port, int flags, int fd, off_t offset);

返回:若成功则为映射区的起始地址,若出错则为-1

功能:I/O使一个磁盘文件与存储空间中的一个缓存相映射。

 int munmap(void *addr, size_t length);

返回:成功返回0,出错返回-1

功能:解除映射

mmap函数从缓存中获取数据,就相当于读文件中的相应字节,与其类似,将数据存入缓存,则相应字节就自动地写入文件,这样就可以在不使用read和write的情况下执行I/O。

子进程继承父进程的存储映射区。

参数:

addr:存储映射区的起始地址,通常设为0,让系统分配。

length:需要映射的字节数

offset:映射字节在文件中的偏移量

prot:PROT_READ映射区可读、PROT_WRITE映射区可写、PROT_EXEC映射区可执行、PROT_NONE:映射区不可访问

flags:MAP_FIXD返回地址必须等于addr,不推荐使用、MAP_SHARED存储操作立刻修改映射文件内容、MAP_PRIVATE存储操作导致创建映射文件的副本,并对副本读写。

6. 文件属性

struct stat是存放文件属性的结构体

 struct stat{
mode_t st_mode; //file type & permission
ino_t st_ino; //i-node number
dev_t st_dev; //device number(file system)
dev_t st_rdev; //device number for special files
nlink_t st_nlink; //number of links
uid_t st_uid; //user ID of owner
gid_t st_gid; //group ID of owner
off_t st_size; //size in bytes
time_t st_atime; //time of last access
time_t st_mtime; //time of last modification
time_t st_ctime; //time of last file status change
blksize_t st_blksize; //best I/O block size最佳块大小
blkcnt_t st_blocks; //number of disk blocks allocated
};  

6.1 文件属性操作函数

 #include <sys/types.h>
#include <sys/stat.h>
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);

返回:若成功返回0,若出错则为-1

功能:返回一个与pathname或fd执行的文件属性信息,存储在结构体buf中。

参数:pathname:文件路径名称;buf:struct stat结构体指针。

lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。

6.2 文件类型

文件类型 判别函数

普通文件(regular file) S_ISREG()

目录文件(directory file) S_ISDIR()

块特殊文件(block special file) S_ISBLK()

字符特殊文件(character special file) S_ISCHR()

FIFO(named pipe) S_ISFIFO()

套接字(socket) S_ISSOCK()

符号链接(symbolic link) S_ISLNK()

6.3 文件权限

9种文件访问权限:

用户权限:S_IRUSR、S_IWUSR、S_IXUSR

组权限:S_IRGRP、S_IWGRP、S_IXGRP

其它权限:S_IROTH、S_IWOTH、S_IXOTH

文件权限通过按位或方式构造。

6.4 文件权限相关函数

(1)access函数 
 #include <unistd.h>
int access(const char *pathname, int mode);

返回:成功执行返回0,若出错为-1

功能:检查是否可以对指定文件进行某种操作

参数:pathname:文件路径;

mode:文件访问权限:

R_OK:判断文件是否有读权限;

W_OK:判断文件是否有写权限;

X_OK:判断文件是否有可执行权限;

F_OK:判断文件是否存在。

(2)umask函数

 #include <sys/types.h>
#include <sys/stat.h>
mode_t umask (mode_t mode);

返回:以前的文件模式创建屏蔽字(掩码)

功能:为进程设置文件方式创建屏蔽字,并返回以前的值

参数:mode:文件权限常量(如:S_IRGRP、S_IWGRP等)

被umask设置过的权限不能再使用在创建文件的权限上。

(3)chmod和fchmod函数

 #include <sys/stat.h>
int chmod(const char * pathname, mode_t mode);
int fchmod(int fd, mode_t mode);

返回:成功返回0,出错返回-1

功能:更改现存文件的权限。chmod函数在指定的文件上进行操作,而fchmod函数对已打开的文件进行操作。

参数:pathname:文件路径名字

mode:文件权限(按位或操作)

S_ISUID、S_ISGID、S_ISVTX

S_IRWXU、S_IRUSR、S_IWUSR、S_IXUSR

S_IRWXG、S_IRGRP、S_IWGRP、S_IXGRP

S_IRWXO、S_IROTH、S_IWOTH、S_IXOTH

想要改变一个文件的权限位,需满足条件:进程的有效用户ID必须等于文件的所有者ID或者进程具有超级用户权限。

(4)truncate和ftruncate函数

 #include <sys/types.h>
#include <unistd.h>
int truncate(const char * pathname, off_t length);
int ftruncate(int fd, off_t length);

返回:成功返回0,出错返回-1

功能:文件截断

参数:pathname:文件路径名字;length:文件截断后的长度。

在文件尾端处截去一些数据以缩短文件。

将一个文件的长度截短为0是一个特例,用O_TRUNC标志可以做到这一点。

如果该文件以前的长度大于length,则超过length以外的数据就不再能存取。如果以前的长度短于length,则其后果与系统有关。

7. Linux文件系统结构

文件操作相关的最基本元素是:目录元素、索引节点和文件的数据本身。

目录结构(目录项)

索引节点(i节点)

文件的数据

(1)link和unlink函数

 #include <unistd.h>
int link(const char *exitingpath, const char *newpath);

返回:成功返回0,出错返回-1

功能:创建一个指向现存文件连接(硬链接)

 int unlink(const char *pathname);

返回:成功返回0,出错返回-1

功能:删除pathname指定的硬链接,并将由pathname所引用的文件链接计数-1

硬链接创建条件:针对文件创建链接,必须是同一个分区,只有超级用户才能对目录建立链接。

文件删除条件:链接计数为0,无其它进程打开该文件。

(2)remove和rename函数

 #include <unistd.h>
int remove(const char * pathname);

返回:成功返回0,出错返回-1

功能:解除对一个文件或目录的链接

 int rename(const char * oldname, const char * newname);

返回:成功返回0,出错返回-1

功能:文件或目录更名

对于文件,remove的功能和unlink相同

对于目录,remove的功能和rmdir相同

(3)symlink和readlink函数

 #include <unistd.h>
int symlink(const char * actualpath, const char * sympath);

返回:成功返回0,出错返回-1

功能:创建一个符号链接(软链接)

 int readlink(const char * restrict_pathname, char * restrict buf, size_t bufsize);

返回:成功返回读到的字节数,出错返回-1

功能:打开该链接本身,并读该链接中的名字

符号链接创建并不要求actualpath存在,可以跨文件系统建立符号链接,软链接也可以针对目录创建。

8. 文件时间

字段

说明

例子

ls选项

st_atime

文件数据最后访问时间

Read

-u

st_mtime

文件数据最后修改时间

Write

默认

st_ctime

i节点最后更改时间

chmod、chown

-c

(1)utime函数

 #include <sys/types.h>
#include <utime.h>
int utime(const char * pathname, const struct utimebuf * times);

返回:成功返回0,出错返回-1

功能:更改文件的存取时间和修改时间

 struct utimebuf{
time_t actime; //access time
time_t modtime; //modification time
};

参数times:

空指针则读取当前时间:进程的有效用户ID必须等于文件的所有者ID,或者进程对该文件具有写权限

非空取times结构体中的时间:进程有效用户ID等于该文件的所有者的ID,或者进程是超级用户进程。

utime操作会自动更新st_ctime值。

9. 目录函数

(1)mkdir和rmdir函数
 #include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char * pathname, mode_t mode);

返回:成功返回0,出错返回-1

功能:创建目录

 int rmdir(const char * pathname);

返回:成功返回0,出错返回-1

功能:删除目录

创建目录:创建一个新的空目录,.和..目录项是自动创建的。创建目录时,至少指定一个执行权限位。

目录删除条件:该目录的链接计数为2(只包含.和..),无其它进程打开目录。

(2)opendir、readdir、rewinddir和closedir函数

 #include <sys/types.h>
#include <dirent.h>
DIR * opendir(const char * pathname);

返回:成功返回目录指针,出错返回NULL

功能:打开目录

 struct dirent * readdir(DIR *dp);

返回:成功返回指针,若在目录结尾或者出错返回NULL

功能:读取目录

 void rewinddir(DIR *dp);

功能:重新定位从头开始读取

 int closedir(DIR *dp);

返回:成功返回0,出错返回-1

功能:关闭目录

 struct dirent{
ino_t d_ino; //i-node number
char d_name[NAME_MAX+]; //null-terminated filename
};
(3)chdir、fchdir和getcwd函数
 #include <unistd.h>
int chdir(const char * pathname);
int fchdir(int fd);

返回:成功返回0,出错返回01

功能:分别用pathname或fd来指定新的当前工作目录

 char *getcwd(char *buf, size_t size);

返回:成功返回buf,出错返回NULL

功能:获取当前工作目录的绝对路径名

当前工作目录是一个进程的属性,所以它只影响调用chdir的进程本身,而不影响其它进程。

问题:改变了路径是否会影响shell的当前路径?

不会影响。

10. 设备特殊文件

每个文件系统所在的存储设备都由主、次设备号表示;

major和minor宏可用来得到主、次设备号;

只有字符特殊文件和块特殊文件才有st_rdev值。

IO系统-文件与目录操作的更多相关文章

  1. Python之文件与目录操作及压缩模块(os、shutil、zipfile、tarfile)

    Python中可以用于对文件和目录进行操作的内置模块包括: 模块/函数名称 功能描述 open()函数 文件读取或写入 os.path模块 文件路径操作 os模块 文件和目录简单操作 zipfile模 ...

  2. Shell命令-文件及目录操作之ls、cd

    文件及目录操作 - ls.cd 1.ls:列出目录的内容及其内容属性信息 ls命令的功能说明 ls命令用于列出目录的内容及其内容属性信息. ls命令的语法格式 ls [OPTION]... [FILE ...

  3. 【转】Python之文件与目录操作(os、zipfile、tarfile、shutil)

    [转]Python之文件与目录操作(os.zipfile.tarfile.shutil) Python中可以用于对文件和目录进行操作的内置模块包括: 模块/函数名称 功能描述 open()函数 文件读 ...

  4. Python之文件与目录操作(os、zipfile、tarfile、shutil)

    Python中可以用于对文件和目录进行操作的内置模块包括: 模块/函数名称 功能描述 open()函数 文件读取或写入 os.path模块 文件路径操作 os模块 文件和目录简单操作 zipfile模 ...

  5. Java编程的逻辑 (59) - 文件和目录操作

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  6. Python::OS 模块 -- 文件和目录操作

    os模块的简介参看 Python::OS 模块 -- 简介 os模块的进程管理 Python::OS 模块 -- 进程管理 os模块的进程参数 Python::OS 模块 -- 进程参数 os模块中包 ...

  7. 零基础学Python--------第10章 文件及目录操作

    第10章 文件及目录操作 10.1 基本文件操作 在Python中,内置了文件(File)对象.在使用文件对象时,首先需要通过内置的open() 方法创建一个文件对象,然后通过对象提供的方法进行一些基 ...

  8. Shell命令-文件及目录操作之cp、find

    文件及目录操作 - cp.find 1.cp:复制文件或目录 cp命令的功能说明 cp命令用于复制文件或目录. cp命令的语法格式 cp [OPTION]... SOURCE... DIRECTORY ...

  9. Shell命令-文件及目录操作之mkdir、mv

    文件及目录操作 - mkdir.mv 1.mkdir:创建目录 mkdir命令的功能说明 mkdir命令用于创建目录,默认情况下,要创建的目录已存在,会提示文件存在,不会继续创建目录. mkdir命令 ...

随机推荐

  1. Linux 内核 低级 sysfs 操作

    kobject 是在 sysfs 虚拟文件系统之后的机制. 对每个在 sysfs 中发现的目录, 有一个 kobject 潜伏在内核某处. 每个感兴趣的 kobject 也输出一个或多个属性, 它出现 ...

  2. CountDownLatch 部分加载和同时并发业务。

    按顺序部分加载: import java.util.concurrent.CountDownLatch; /** * @Title: ThreadCountDownTest.java * @Descr ...

  3. 学习Java第二周

    这是学习java的第二周,又这样不知不觉的结束了 上周想要学习的这一周也都做到了,可是觉得进度有些慢了,学习了: 1. 接口和抽象类: 2. 集合与数组: 3. 方法的定义: 4. 递归算法: 5.对 ...

  4. mysql:数据库与实例的区别

    题记:最近想更深入的了解mysql,所以买了一些书在学习,趁着这个机会开个坑,整理一下一些我认为重要的知识点. 刚工作那会经常能听到组长提到实例这个词,一开始我以为是服务器... 数据库(databa ...

  5. $Loj10157$ 皇宫看守 树形$DP$

    loj Description 有一些宫殿,它们呈树形结构,相邻的宫殿之间可以互相望见.在一些宫殿设立士兵,使得所有的宫殿都有士兵或是被士兵望见.求最小士兵数. Sol 状态: f[x][0] 表示结 ...

  6. 使用宝塔搭建nextcloud的过程(搭建、优化、问题)

    宝塔部署教程 参考网址: 使用NextCloud来搭建我们的私有网盘.并结合Redis优化性能(宝塔) https://www.moerats.com/archives/175/ 宝塔面板下nextc ...

  7. 洛谷P1638 逛画展 题解 尺取法/双指针/队列

    题目链接:https://www.luogu.com.cn/problem/P1638 题目大意: 给你一个长度为 \(n (\le 10^6)\) 的数组,数组中每个元素的范围在 \(1\) 至 \ ...

  8. Python 植物大战僵尸代码实现: 图片加载和显示切换

    游戏介绍以前很火的植物大战僵尸游戏, 本想在网上找个python版本游戏学习下,无奈没有发现比较完整的,那就自己来写一个把.图片资源是从github上下载的,因为图片资源有限,只能实现几种植物和僵尸. ...

  9. wrk性能测试(详解)

    一.简介 wrk 是一款针对 Http 协议的基准测试工具,它能够在单机多核 CPU 的条件下,使用系统自带的高性能 I/O 机制,如 epoll,kqueue 等,通过多线程和事件模式,对目标机器产 ...

  10. HBase学习笔记(四)—— 架构模型

    在逻辑上,HBase 的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列. 但从 HBase 的底层物理存储结构(K-V)来看,HBase 更像是一个 multi-dimensional m ...