IO系统-文件与目录操作

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 调用函数

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

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

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

1 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是存放文件属性的结构体

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

6.1 文件属性操作函数

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 int stat(const char *pathname, struct stat *buf);
4 int fstat(int fd, struct stat *buf);
5 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函数

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

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

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

参数:pathname:文件路径;

mode:文件访问权限:

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

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

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

F_OK:判断文件是否存在。

(2)umask函数

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

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

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

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

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

(3)chmod和fchmod函数

1 #include <sys/stat.h>
2 int chmod(const char * pathname, mode_t mode);
3 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函数

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

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

功能:文件截断

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

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

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

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

7. Linux文件系统结构

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

目录结构(目录项)

索引节点(i节点)

文件的数据

(1)link和unlink函数

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

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

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

1 int unlink(const char *pathname);

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

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

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

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

(2)remove和rename函数

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

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

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

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

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

功能:文件或目录更名

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

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

(3)symlink和readlink函数

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

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

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

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函数

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

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

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

1 struct utimebuf{
2     time_t actime; //access time
3     time_t modtime; //modification time
4 };

参数times:

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

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

utime操作会自动更新st_ctime值。

9. 目录函数

(1)mkdir和rmdir函数

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 int mkdir(const char * pathname, mode_t mode);

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

功能:创建目录

1 int rmdir(const char * pathname);

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

功能:删除目录

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

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

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

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

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

功能:打开目录

1 struct dirent * readdir(DIR *dp);

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

功能:读取目录

1 void rewinddir(DIR *dp);

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

1 int closedir(DIR *dp);

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

功能:关闭目录

1 struct dirent{
2     ino_t d_ino; //i-node number
3     char d_name[NAME_MAX+1]; //null-terminated filename
4 };

(3)chdir、fchdir和getcwd函数

1 #include <unistd.h>
2 int chdir(const char * pathname);
3 int fchdir(int fd);

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

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

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

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

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

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

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

不会影响。

10. 设备特殊文件

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

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

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

原文地址:https://www.cnblogs.com/mrlayfolk/p/12019753.html

时间: 2024-11-05 23:37:51

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

第四天 文件和目录操作

7.1 linux 文件系统 linux文件不靠后缀名 内置标识 1.普通文件 - 开头代表 普通文件 文本文件 二进制程序 音频 视频 2.目录文件 d 开头代表 目录文件 3.设备文件 特殊类型文件 /dev (device) ll /dev/rc.d ll /dev/sd* [[email protected] ~]# ll /dev|grep s brw-rw----. 1 root disk 8, 0 Jul 17 20:33 sda brw-rw----. 1 root disk 8

计算机程序的思维逻辑 (59) - 文件和目录操作

前面两节我们介绍了如何通过流的方式读写文件内容,本节我们介绍文件元数据和目录的一些操作. 文件和目录操作最终是与操作系统和文件系统相关的,不同系统的实现是不一样的,但Java中的java.io.File类提供了统一的接口,底层它会通过本地方法调用操作系统和文件系统的具体实现,本节,我们就来介绍File类. File类中的操作大概可以分为三类: 文件元数据 文件操作 目录操作 在介绍这些操作之前,我们先来看下File的构造方法. 构造方法 File既可以表示文件,也可以表示目录,它的主要构造方法有

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

文件及目录操作 - ls.cd 1.ls:列出目录的内容及其内容属性信息 ls命令的功能说明 ls命令用于列出目录的内容及其内容属性信息. ls命令的语法格式 ls [OPTION]... [FILE]...ls [参数选项] [文件或目录] ls命令的选项说明 ls 选项很多,表1为ls命令的参数及说明: 表1:ls命令的参数及说明 参数选项 解释说明(带*的为重点) -l 长格式显示文件属性* -a 显示所有字目录和文件(包含隐藏文件)* -d 只显示目录* -i 显示Inode号 -h 人

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

前面两节我们介绍了如何通过流的方式读写文件内容,本节我们介绍文件元数据和目录的一些操作. 文件和目录操作最终是与操作系统和文件系统相关的,不同系统的实现是不一样的,但Java中的java.io.File类提供了统一的接口,底层它会通过本地方法调用操作系统和文件系统的具体实现,本节,我们就来介绍File类. File类中的操作大概可以分为三类: 文件元数据 文件操作 目录操作 在介绍这些操作之前,我们先来看下File的构造方法. 构造方法 File既可以表示文件,也可以表示目录,它的主要构造方法有

【Linux命令详解】2、文件和目录操作管理

2.文件和目录操作管理 本节主要学习在Linux下如何使用命令对文件和目录进行操作,这些命令pwd.cd.ls等. 2.1 pwd:显示工作目录路径 使用pwd命令可以显示当前用户所处的工作目录的绝对路径. 2.1.1命令语法: pwd[选项] 2.1.2参数选项: 选项 选项含义 -L 目录链接时,输出链接路径 -P 输出物理路径 2.1.3实例: 例1:显示用户当前工作目录路径. [[email protected] ~]# pwd /root //用户当前的工作路径是root 例2:显示用

c++Builder 下的文件及目录操作

转自 http://blog.csdn.net/ktcserver/article/details/936329 一.判断目录是否存在:           C++   Builder中提供了检查文件是否存在的函数FileExists,indows   程序实现如下:           设char   *Dir为带判断的目录       bool   Exist;   //   最后结果,表示目录是否存在       if(Dir[strlen(Dir)]=='//')Dir[strlen(D

python文件和目录操作函数小结

本文主要介绍python文件和目录操作函数小结,主要涉及到os模块和shutil模块的一些方法. python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()返回指定目录下的所有文件和目录名:os.listdir()函数用来删除一个文件:os.remove()删除多个目录:os.removedirs(r"c:\python")检验给出的路径是否是一个文件:os.path.isf

python文件和目录操作函数总结

有关python文件和目录操作函数小结,主要涉及到os模块和shutil模块的一些方法. python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()返回指定目录下的所有文件和目录名:os.listdir()函数用来删除一个文件:os.remove()删除多个目录:os.removedirs(r“c:\python”)检验给出的路径是否是一个文件:os.path.isfile()检验给出

Python文件和目录操作实例代码

对于文件和目录的处理,虽然可以通过操作系统命令来完成,但是Python语言为了便于开发人员以编程的方式处理相关工作,提供了许多处理文件和目录的内置函数.重要的是,这些函数无论是在Unix.Windows还是Macintosh平台上,它们的使用方式是完全一致的. 本文将详细解释这些函数的使用方法.首先,介绍Python语言中类似于Windows系统的dir命令的列出文件功能,然后描述如何测试一个文件名对应的是一个标准文件.目录还是链接,以及提取文件大小和日期的方法.之后,还将介绍如何删除文件和目录