第四课文件系统(下)

author author     2022-08-22     687

关键词:

====================
第四课 文件系统(下)
====================

一、sync/fsync/fdatasync
------------------------

1. 大多数磁盘I/O都通过缓冲进行,
写入文件其实只是写入缓冲区,直到缓冲区满,
才将其排入写队列。

2. 延迟写降低了写操作的次数,提高了写操作的效率,
但可能导致磁盘文件与缓冲区数据不同步。

3. sync/fsync/fdatasync用于强制磁盘文件与缓冲区同步。

4. sync将所有被修改过的缓冲区排入写队列即返回,
不等待写磁盘操作完成。

5. fsync只针对一个文件,且直到写磁盘操作完成才返回。

6. fdatasync只同步文件数据,不同步文件属性。

#include <unistd.h>

void sync (void);

int fsync (
int fd
);

成功返回0,失败返回-1。

int fdatasync (
int fd
);

成功返回0,失败返回-1。

+-fwrite-> 标准库缓冲 -fflush-+ sync
应用程序内存 -+ +-> 内核缓冲 -fdatasync-> 磁盘(缓冲)
+------------write------------+ fsync

二、fcntl
---------

#include <fcntl.h>

int fcntl (
int fd, // 文件描述符
int cmd, // 操作指令
... // 可变参数,因操作指令而异
);

对fd文件执行cmd操作,某些操作需要提供参数。

1. 常用形式
~~~~~~~~~~~

#include <fcntl.h>

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

成功返回值因cmd而异,失败返回-1。

cmd取值:

F_DUPFD - 复制fd为不小于arg的文件描述符。
若arg文件描述符已用,
该函数会选择比arg大的最小未用值,
而非如dup2函数那样关闭之。

F_GETFD - 获取文件描述符标志。

F_SETFD - 设置文件描述符标志。
arg只能取FD_CLOEXEC
(调用exec族函数后关闭该fd)。

F_GETFL - 获取文件模式。
不能获取O_CREAT、O_EXCL和O_TRUNC。

F_SETFL - 追加文件模式。
arg只能取O_APPEND和O_NONBLOCK。

范例:dup.c、flags.c

2. 文件锁
~~~~~~~~~

#include <fcntl.h>

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

其中:

struct flock {
short int l_type; // 锁的类型:
// F_RDLCK/F_WRLCK/F_UNLCK
// (读锁/写锁/解锁)
short int l_whence; // 偏移起点:
// SEEK_SET/SEEK_CUR/SEEK_END
// (文件头/当前位置/文件尾)
off_t l_start; // 锁区偏移,从l_whence开始
off_t l_len; // 锁区长度,0表示锁到文件尾
pid_t l_pid; // 加锁进程,-1表示自动设置
};

cmd取值:

F_GETLK - 测试lock所表示的锁是否可加。
若可加则将lock.l_type置为F_UNLCK,
否则通过lock返回当前锁的信息。

F_SETLK - 设置锁定状态为lock.l_type,
成功返回0,失败返回-1。
若因其它进程持有锁而导致失败,
则errno为EACCES或EAGAIN。

F_SETLKW - 设置锁定状态为lock.l_type,
成功返回0,否则一直等待,
除非被信号打断返回-1。

1) 既可以锁定整个文件,也可以锁定特定区域。

2) 读锁(共享锁)、写锁(独占锁/排它锁)、解锁。

图示:rwlock.bmp、flock.bmp

3) 文件描述符被关闭(进程结束)时,自动解锁。

4) 劝谏锁(协议锁)、强制锁。

范例:lock1.c、lock2.c

5) 文件锁仅在不同进程间起作用。

6) 通过锁同步多个进程对同一个文件的读写访问。

范例:wlock.c、rlock.c

# wlock 达内科技 | # wlock 有限公司
wlock.txt
<乱码>

# wlock 达内科技 -l | # wlock 有限公司 -l
wlock.txt
达内科技有限公司

-----------------------------------------

# wlock 达内科技有限公司 | # rlock
<乱码>

# wlock 达内科技有限公司 -l | # rlock -l
达内科技有限公司

三、stat/fstat/lstat
--------------------

获取文件属性。

#include <sys/stat.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。

stat函数跟踪软链接,lstat函数不跟踪软链接。

struct stat {
dev_t st_dev; // 设备ID
ino_t st_ino; // i节点号
mode_t st_mode; // 文件类型和权限
nlink_t st_nlink; // 硬链接数
uid_t st_uid; // 属主ID
gid_t st_gid; // 属组ID
dev_t st_rdev; // 特殊设备ID
off_t st_size; // 总字节数
blksize_t st_blksize; // I/O块字节数
blkcnt_t st_blocks; // 占用块(512字节)数
time_t st_atime; // 最后访问时间
time_t st_mtime; // 最后修改时间
time_t st_ctime; // 最后状态改变时间
};

st_mode(0TTSUGO)为以下值的位或:

S_IFDIR - 目录
S_IFREG - 普通文件 |
S_IFLNK - 软链接 |
S_IFBLK - 块设备 > TT (S_IFMT)
S_IFCHR - 字符设备 |
S_IFSOCK - Unix域套接字 |
S_IFIFO - 有名管道 /
--------------------------------
S_ISUID - 设置用户ID
S_ISGID - 设置组ID > S
S_ISVTX - 粘滞 /
--------------------------------
S_IRUSR(S_IREAD) - 属主可读
S_IWUSR(S_IWRITE) - 属主可写 > U (S_IRWXU)
S_IXUSR(S_IEXEC) - 属主可执行 /
--------------------------------
S_IRGRP - 属组可读
S_IWGRP - 属组可写 > G (S_IRWXG)
S_IXGRP - 属组可执行 /
--------------------------------
S_IROTH - 其它可读
S_IWOTH - 其它可写 > O (S_IRWXO)
S_IXOTH - 其它可执行 /

常用以下宏辅助分析st_mode:

S_ISDIR() - 是否目录
S_ISREG() - 是否普通文件
S_ISLNK() - 是否软链接
S_ISBLK() - 是否块设备
S_ISCHR() - 是否字符设备
S_ISSOCK() - 是否Unix域套接字
S_ISFIFO() - 是否有名管道

范例:stat.c

四、access
----------

#include <unistd.h>

int access (
const char* pathname, // 文件路径
int mode // 访问模式
);

1. 按实际用户ID和实际组ID(而非有效用户ID和有效组ID),
进行访问模式测试。

2. 成功返回0,失败返回-1。

3. mode取R_OK/W_OK/X_OK的位或,
测试执行调用进程的用户对该文件,
是否可读/可写/可执行,
或者取F_OK,测试该文件是否存在。

范例:access.c

五、umask
---------

可以用umask命令查看/修改当前shell的文件权限屏蔽字:

# umask
0022

# umask 0033
# umask
0033

#include <sys/stat.h>

mode_t umask (
mode_t cmask // 屏蔽字
);

1. 为进程设置文件权限屏蔽字,并返回以前的值,
此函数永远成功。

2. cmask由9个权限宏位或组成(直接写八进制整数形式亦可,
如022 - 屏蔽属组和其它用户的写权限):

S_IRUSR(S_IREAD) - 属主可读
S_IWUSR(S_IWRITE) - 属主可写
S_IXUSR(S_IEXEC) - 属主可执行
------------------------------
S_IRGRP - 属组可读
S_IWGRP - 属组可写
S_IXGRP - 属组可执行
------------------------------
S_IROTH - 其它可读
S_IWOTH - 其它可写
S_IXOTH - 其它可执行

3. 设上屏蔽字以后,此进程所创建的文件,
都不会有屏蔽字所包含的权限。

范例:umask.c

六、chmod/fchmod
----------------

修改文件的权限。

#include <sys/stat.h>

int chmod (
const char* path, // 文件路径
mode_t mode // 文件权限
);

int fchmod (
int fd, // 文件路径
mode_t mode // 文件权限
);

成功返回0,失败返回-1。

mode为以下值的位或(直接写八进制整数形式亦可,
如07654 - rwSr-sr-T):

S_ISUID - 设置用户ID
S_ISGID - 设置组ID
S_ISVTX - 粘滞
------------------------------
S_IRUSR(S_IREAD) - 属主可读
S_IWUSR(S_IWRITE) - 属主可写
S_IXUSR(S_IEXEC) - 属主可执行
------------------------------
S_IRGRP - 属组可读
S_IWGRP - 属组可写
S_IXGRP - 属组可执行
------------------------------
S_IROTH - 其它可读
S_IWOTH - 其它可写
S_IXOTH - 其它可执行

范例:chmod.c

七、chown/fchown/lchown
-----------------------

# chown <uid>:<gid> <file>

修改文件的属主和属组。

#include <unistd.h>

int chown (
const char* path, // 文件路径
uid_t owner, // 属主ID
gid_t group // 属组ID
);

int fchown (
int fildes, // 文件描述符
uid_t owner, // 属主ID
gid_t group // 属组ID
);

int lchown (
const char* path, // 文件路径(不跟踪软链接)
uid_t owner, // 属主ID
gid_t group // 属组ID
);

成功返回0,失败返回-1。

注意:

1. 属主和属组ID取-1表示不修改。

2. 超级用户进程可以修改文件的属主和属组,
普通进程必须拥有该文件才可以修改其属主和属组。

八、truncate/ftruncate
----------------------

修改文件的长度,截短丢弃,加长添零。

#include <unistd.h>

int truncate (
const char* path, // 文件路径
off_t length // 文件长度
);

int ftruncate (
int fd, // 文件描述符
off_t length // 文件长度
);

成功返回0,失败返回-1。

范例:trunc.c、mmap.c

注意:对于文件映射,
私有映射(MAP_PRIVATE)将数据写到缓冲区而非文件中,
只有自己可以访问。
而对于内存映射,
私有(MAP_PRIVATE)和公有(MAP_SHARED)没有区别,
都是仅自己可以访问。

九、link/unlink/remove/rename
-----------------------------

link: 创建文件的硬链接(目录条目)。

unlink: 删除文件的硬链接(目录条目)。
只有当文件的硬链接数降为0时,文件才会真正被删除。
若该文件正在被某个进程打开,
其内容直到该文件被关闭才会被真正删除。

remove: 对文件同unlink,
对目录同rmdir (不能删非空目录)。

rename: 修改文件/目录名。

#include <unistd.h>

int link (
const char* path1, // 文件路径
const char* path2 // 链接路径
);

int unlink (
const char* path // 链接路径
);

#include <stdio.h>

int remove (
const char* pathname // 文件/目录路径
);

int rename (
const char* old, // 原路径名
const char* new // 新路径名
);

成功返回0,失败返回-1。

注意:硬链接只是一个文件名,即目录中的一个条目。
软链接则是一个独立的文件,
其内容是另一个文件的路径信息。

十、symlink/readlink
--------------------

symlink: 创建软链接。目标文件可以不存在,
也可以位于另一个文件系统中。

readlink: 获取软链接文件本身(而非其目标)的内容。
open不能打开软链接文件本身。

#include <unistd.h>

int symlink (
const char* oldpath, // 文件路径(可以不存在)
const char* newpath // 链接路径
);

成功返回0,失败返回-1。

ssize_t readlink (
const char* restrict path, // 软链接文件路径
char* restrict buf, // 缓冲区
size_t bufsize // 缓冲区大小
);

成功返回实际拷入缓冲区buf中软链接文件内容的字节数,
失败返回-1。

范例:slink.c

十一、mkdir/rmdir
-----------------

mkdir: 创建一个空目录。

rmdir: 删除一个空目录。

#include <sys/stat.h>

int mkdir (
const char* path, // 目录路径
mode_t mode // 访问权限,
// 目录的执行权限(x)表示可进入
);

#include <unistd.h>

int rmdir (
const char* path // 目录路径
);

成功返回0,失败返回-1。

十二、chdir/fchdir/getcwd
-------------------------

chdir/fchdir: 更改当前工作目录。
工作目录是进程的属性,只影响调用进程本身。

getcwd: 获取当前工作目录。

#include <unistd.h>

int chdir (
const char* path // 工作目录路径
);

int fchdir (
int fildes // 工作目录描述符(由open函数返回)
);

成功返回0,失败返回-1。

char* getcwd (
char* buf, // 缓冲区
size_t size // 缓冲区大小
);

成功返回当前工作目录字符串指针,失败返回NULL。

范例:dir.c

十三、opendir/fdopendir/closedir/readdir/rewinddir/telldir/seekdir
------------------------------------------------------------------

opendir/fdopendir: 打开目录流。

closedir: 关闭目录流。

readdir: 读取目录流。

rewinddir: 复位目录流。

telldir: 获取目录流当前位置。

seekdir: 设置目录流当前位置。

#include <sys/types.h>
#include <dirent.h>

DIR* opendir (
const char* name // 目录路径
);

DIR* fdopendir (
int fd // 目录描述符(由open函数返回)
);

成功返回目录流指针,失败返回NULL。

int closedir (
DIR* dirp // 目录流指针
);

成功返回0,失败返回-1。

struct dirent* readdir (
DIR* dirp // 目录流指针
);

成功返回下一个目录条目结构体的指针,
到达目录尾(不置errno)或失败(设置errno)返回NULL。

struct dirent {
ino_t d_ino; // i节点号
off_t d_off; // 下一个条目的偏移量
unsigned short d_reclen; // 记录长度
unsigned char d_type; // 文件类型
char d_name[256]; // 文件名
};

d_type取值:

DT_DIR - 目录
DT_REG - 普通文件
DT_LNK - 软链接
DT_BLK - 块设备
DT_CHR - 字符设备
DT_SOCK - Unix域套接字
DT_FIFO - 有名管道
DT_UNKNOWN - 未知

范例:list.c

练习:打印给定路径下的目录树。

代码:tree.c

void rewinddir (
DIR* dirp // 目录流指针
);

long telldir (
DIR* dirp // 目录流指针
);

成功返回目录流的当前位置,失败返回-1。

void seekdir (
DIR* dirp, // 目录流指针
long offset // 位置偏移量
);

+-----------------------+ +-----------------------+
| v | v
+-------+---|---+-----+-------+ +-------+---|---+-----+-------+ +-------
| d_ino | d_off | ... | a.txt | ... | d_ino | d_off | ... | b.txt | ... | d_ino
+-------+-------+-----+-------+ +-------+-------+-----+-------+ +-------
^ ^
| -- readdir() -> |

范例:seek.c

第四课4ros客户端

ROS客户端提供一些列库文件用于用户开发。ROSCPP客户端(c++客户端)首先新建一个包然后catkin_make一下在新建的包目录下,建立一个消息文件msg然后需要生成消息foo.h以便以后我们可以调用,我们进入package.xml里面去修改,然后再... 查看详情

scrapy学习第四课(代码片段)

python爬虫框架scrapy学习第四课任务:爬取凤凰网导航下所有一级、二级和具体新闻数据执行:爬虫实例结果:爬取结果展示任务:爬取凤凰网导航下所有一级、二级和具体新闻数据凤凰网导航一级标题:二级... 查看详情

css第四课

学习内容:1.标签的margin值:用来控制标签的外边距,分别控制上、右、下、左的外边距1#d1{2width:500px;3height:300px;4background-color:red;5margin:50px;6}当只输入一项数值时,所有方向上的外边距被统一设定,而输入两个值时,则分别控制... 查看详情

spring第四课spring框架以及jdbctemplate的使用

概念本文结合前面所讲授的Spring框架的知识点基础上,教授JDBCTemplate的使用。项目创建步骤创建项目,在WEB-INF文件夹下新建lib文件夹,将以下jar包导入,并关联至项目在项目中新建resources资源文件夹将applicationCont... 查看详情

第四十四课发送自定义事件(下)

一、自定义事件对象1、Qt可以自定义新的事件类(1)、自定义的事件类必须继承自QEvent(2)、自定义的事件类必须拥有全局唯一的Type值(event->type()可以获得事件的类型)(3)、程序中必须提供处理自定义事件的方法2、自定... 查看详情

电脑小白学习第四课---卸载程序(qq为例)

程序的卸载,大多数都可通过在控制面板里面去操作。点击“卸载程序”选择需要卸载的程序,点击卸载即可。系统会调用程序的卸载程序,自动卸载。稍等一会,完成卸载。有些特殊的程序,在控制面板--程序里面找不到,可... 查看详情

qt第四课搭建工程环境

1添加第三方库头文件添加json第三方库.pro文件中添加:INCLUDEPATH+=/root/jsoncpp-master/include测试是否成功#include<QCoreApplication>#include"json/reader.h"intmain(intargc,char*argv[]){  QCoreApplicationa(argc,argv 查看详情

嵌入式第四课-c文件操作(代码片段)

1.c语言文件操作函数fopen/fclose/fread/fwrite/fseek1).fopen:FILE*fopen(constchar*filename,constchar*mode);函数功能:打开一个文件参数filename:文件路径参数mode   :打开方式返回值 :打开成功返回一个标准数据指针 失败返回NULLmode参... 查看详情

第四课补充01——数据库系统的立体视图

数据库系统架构一、数据库系统的分类:面向对象型、关系型、对象关系型1、面向对象型数据库(OODBS)(1)面向对象型数据库系统是一种持久的、可共享对象库的存储器和管理器;是基于OO的思想,因此这类数据库也有封装、... 查看详情

cmu15-445数据库课程第四课文字版-存储2(代码片段)

熟肉视频地址:CMU数据库管理系统课程[熟肉]4.数据库存储结构2(上)CMU数据库管理系统课程[熟肉]4.数据库存储结构2(下)1.面向日志的存储上节课我们讲完了面向元组的存储,这节课从面向日志的存储设计开始。在这里,... 查看详情

第四课helloqt

一、进入QT的世界1、QT是什么(1)、QT是一套跨平台的开发库(2)、QT是一套c++集成开发环境(3)、QT是一套开源的殿堂级架构技术教程2、第一个QT程序3、通过命令行的方式编译QT程序(1)、启动QT命令行(2)、进入源码所在的... 查看详情

docker学习第四课(代码片段)

搭建php-fpmapachenginx环境docker-compose.yml文件networks:net:driver:bridgeipam:config:-subnet:192.138.0.0/16services:apache:container_name:php-apacheimage:"httpd:2.4-alpine"networks:net:ipv4_address:"192.13 查看详情

opengl学习进程第四课:点边和图形点

   本节是OpenGL学习的第四个课时,下面介绍OpenGL点的相关知识:   (1)点的概念:   数学上的点,只有位置,没有大小。但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点。一般... 查看详情

第四课:socket

一.InetAddress类packageinetAddress;importjava.io.*;importjava.net.*;publicclassInetAddressTestpublicstaticvoidmain(String[]args)throwsIOExceptionif(args.length>0)Stringhost=args[0];InetAddressadd 查看详情

法语学习笔记--第四课(家庭)

 第四课Lafamille--------------您---------------------vous您,你们是 êtrejesuis  noussommestues  vous êtesilest  ilssontelleest  ellessont----------------- 查看详情

swift第四课

项目中经常遇到按钮改变文字和图片位置的情况,所以尝试写一个button的分类importFoundationimportUIKit/*枚举设置图片的位置*/enumButtonImagePosition:Int{casePositionTop=0casePositionleftcasePositionBottomcasePositionRight}extensionUIButton{/**imag 查看详情

django第四课基于django超市订单管理系统开发(代码片段)

概念本文在上一文之上,针对管理员,经理,普通员工身份的用户操作订单管理模块功能。功能实现该功能也是业务功能模块,管理员不具备操作权限,普通员工需要对超市所合作的供应商进行进货,因此... 查看详情

第四课tp5框架配置详解

4.1为什么需要配置文件通常在框架当中很多的固定的参数,初始化参数,并不是我们直接在使用时添加,一些通用的参数,需要固定的位置存放,然后调用时到固定的地方获取,而不是重复的定义4.2有哪些配置文件惯例配置:核... 查看详情