APUE 2 文件和目录

本文代码实现采用golang的syscall包,其通常会包装一层系统调用不过大体相似


1.文件属性结构 Stat_t

文件类型 描述
普通文件 可能是文本或二进制
目录文件 包含该目录内的文件名,和有关这些文件信息的指针
块特殊文件 提供对设备带缓冲的访问
字特殊文件 提供对设备不带缓冲的访问,每次访问长度可变
FIFO 命名管道,用于进程间通信
套接字 用于进程间的网络通信,也可用于同一台宿主机进程间非网络通信
符号链接 指向另一个文件

文件的类型

文件类型 描述
普通文件 可能是文本或二进制
目录文件 包含该目录内的文件名,和有关这些文件信息的指针
块特殊文件 提供对设备带缓冲的访问
字特殊文件 提供对设备不带缓冲的访问,每次访问长度可变
FIFO 命名管道,用于进程间通信
套接字 用于进程间的网络通信,也可用于同一台宿主机进程间非网络通信
符号链接 指向另一个文件

描述文件属性的结构体Stat_t

type Stat_t struct {
        Dev       uint64  //设备号,文件(以及i节点)在此文件系统中
        Ino       uint64 //inode号
        Nlink     uint64 //链接数
        Mode      uint32 //文件类型&访问权限
        Uid       uint32 //属主ID
        Gid       uint32 //属组ID
        X__pad0   int32
        Rdev      uint64 //实际设备号,只有块字特殊文件才有此值
        Size      int64 //文件大小,byte单位
        Blksize   int64 //最佳I/O块大小
        Blocks    int64 //已分配块数(512字节块或其他,根据不同系统可能不同)
        Atim      Timespec //访问时间
        Mtim      Timespec //修改内容时间
        Ctim      Timespec //修改文件属性时间
        X__unused [3]int64
}

type Timespec struct {
        Sec  int64 //秒
        Nsec int64 //纳秒
}

2.查看文件属性信息stat、fstat、lstat

func Stat(path string, stat *Stat_t) (err error)
func Fstat(fd int, stat *Stat_t) (err error)
func Lstat(path string, stat *Stat_t) (err error)

Stat函数根据传入的path,读取文件属性写至stat,注意Stat函数会追踪符号链接至真实文件
Fstat函数根据当前已打开的文件描述符,读取属性至stat
Lstat函数同Stat,但不会追踪链接文件,直接返回符号链接的属性

3.进程相关的ID

4.4
  • 实际ID:通常为登录会话时取自口令文件中的登陆项,超级用户进程有方法改变。表示当前的会话(如SHELL)属于哪个ID
  • 有效ID:用于文件访问权限的检测
  • 保存的设置ID:有效ID的副本 exec函数使用
  • 文件所有ID:文件Stat_t中的Uid Gid

通常情况下,启动一个进程时会将有效ID设置为实际ID
但是在文件Mode属性中存在特殊的位设置用户设置组,如若设置了该位置,启动一个进程时有效ID会被设置为文件所有ID

4.文件访问权限

所有类型的文件均具有访问权限设置,其值在Stat_t中的Mode


4.5

对于不同类型的文件,再此处做2类区分,文件和目录:

  • 文件
    • 对于文件进行有关的open write read操作时,根据具体的操作类型判断对应的访问权限(读 写)是否有效
    • 当文件为可执行文件时,若需要执行则执行位要有效
  • 目录
    • 目录的读权限,允许读某目录中的所有文件名列表
    • 目录的写权限,允许对某目录项的内容进行修改,如增减文件
    • 目录的执行权限,决定是否可以对该目录进行搜索操作,如想打开、执行。增加删除某一文件,则其所有父层级的目录均需要拥有执行权限。执行权限确定了是否允许找到这个文件(如CD到某一目录,需要拥有该目录的执行权限)

5.创建新文件和目录的所有权

新文件的用户ID设置为当前进程有效用户ID
组ID取决于其所属的目录的设置组ID是否有效,若有效则新创建的文件的组ID为该目录的组ID;否则为进程的有效组ID

6.访问权限测试 access和faccessat

func Access(path string, mode uint32) (err error)
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
//R_OK=4, W_OK=2, X_OK=1, F_OK=0   mode只可以为对应的整数值

注意:golang中的Access参数mode不可用C中的测试宏(R_OK等),等效可用对应的整数值。如上边的注释内容

如果想自行进行访问权限的检测,如通过实际ID来进行检测等
Access与Faccessat区别:

  • Faccessat的dirfd可以指定某目录fd,当fd=_AT_FDCWD时二者访问路径相同
  • flags=AT_EACCESS 通过进程有效ID检测,默认是使用实际ID检测

7.屏蔽字umask

func Umask(mask int) (oldmask int)
4-7

当创建文件时,将和umask进行与非操作(类似网络掩码),使创建的文件不含有某些权限

注意:修改进程的umask不会影响其父进程(通常为shell)

8.修改文件模式属性 Chmod、Fchmod、Fchmodat

func Chmod(path string, mode uint32) (err error)
func Fchmod(fd int, mode uint32) (err error)
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)

3个函数区别:

  • Fchmod可指定已打开的文件
  • Fchmodeat可指定文件夹描述符
  • 参数flags可指定AT_SYMLINK_NOFOLLOW以不追踪符号链接
  • 参数dirfd可指定为AT_FDCWD以使用相对路径

mode 常量

VTX

粘着位 S_ISVTX:

  • 设置文件:会保存程序正文副本保存至交换分区(目前流行操作系统无需此操作,意义不大)
  • 设置目录:只有满足下列要求的用户才可删除该目录下的文件
    • 拥有待删除文件
    • 拥有该目录
    • 是超级用户

9.修改文件属主(组) chown系列

func Chown(path string, uid int, gid int) (err error)
func Fchown(fd int, uid int, gid int) (err error)
func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
func Lchown(path string, uid int, gid int) (err error)

这四个函数与其他类似函数的变种概念相近
除了Fchown(根据打开的文件)其他的均可由Fchownat来包装形成
影响Fchownat行为的参数:

  • AT_SYMLINK_NOFOLLOW 不追踪符号链接
  • AT_FDCWD 相对路径

10.文件长度

文件属性中的Size描述了文件的长度

  • 针对普通文件通常是一个数(16或512)的整数倍
  • 针对符号链接,长度是在文件名的实际字符数

文件属性中的Blocks描述了文件所占512字节块(或其他)数目
关于产生文件空洞的现象(Size>>Blocks*N),空洞未分配实际磁盘空间,但使用Read函数会把空洞位读出0,既会读出Size个字符

11.文件截断

func Truncate(path string, length int64) (err error)
func Ftruncate(fd int, length int64) (err error)

根据指定的length将目标文件进行截断,使文件长度变成length,若原长度小于length的话将产生空洞

12.文件系统*

以Berkeley快速文件系统为例


123

磁盘可划分为多个分区,每个分区包含一个文件系统。本章值得注意的是i节点和数据块(含目录块)
i节点包含文件stat结构中的大多数信息
目录块含目录中各文件名和对应的i节点地址


i节点

当创建一个新目录testdir后文件系统内相关结构


结构

13.硬链接 link

func Link(oldpath string, newpath string) (err error)
func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Unlink(path string) error
func Unlinkat(dirfd int, path string, flags int) (err error)

如上文文件系统的描述,任何一个文件可以有多个目录项指向其i节点

创建硬链接(目录项)

  • Link和Linkat,会使文件属性的Nlink+1
  • linkat可以指定目录的文件描述符
  • flags可设置AT_SYMLINK_NOFOLLOW或AT_SYMLINK_FOLLOW来指定是否跟随符号链接

删除硬链接

  • Unlink和Unlinkat,会使文件属性的Nlink-1,当Nlink减少至0时,该文件可以被删除
    • 该操作需要有包含该目录项的目录具有写和执行权限,注意粘着位
    • 当关闭一个文件时内核会检查当前同时打开该文件的进程数,若为0再检查Nlink若也为0则删除该文件的内容
  • Unlinkat可以指定目录的文件描述符
  • Unlinkat的flags可以指定为AT_REMOVEDIR,以支持删除目录
  • 不会跟随符号链接

14 重命名 rename和renameat

func Rename(oldpath string, newpath string) (err error)
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)

针对待重命名文件的类型(文件或目录)有如下几种情况

  • 当oldpath为文件时且newpath存在时,删除newpath的目录项然后将oldpath重命名为newpath
  • 对其所包含的目录进程需要有写和执行权限
  • 当oldpath为目录时且newpath存在,则需要newpath为空目录,删除newpath再将oldpath重命名
  • newpath不能包含oldpath作为前缀

15 符号链接

一种特殊的文件类型,是类似于文件硬链接的文件间接指针,与硬链接不同:

  • 符号链接可以跨文件系统,而硬链接通常要求文件位于同一文件系统中
  • 任何用户都可以创建符号链接,而硬链接只可以是root操作

不同的系统调用对于符号链接是否跟随情况不一,如图


跟随情况

创建符号链接

func Symlink(oldpath string, newpath string) (err error)
func Symlinkat(oldpath string, newdirfd int, newpath string) (err error)

创建oldpath指向newpath的符号链接,Symlinkat的newdirfd为AT_FDCWD时两个函数相同

因为open函数会跟随符号链接,所以读取符号链接的内容存在独立的函数

func Readlink(path string, buf []byte) (n int, err error)
func Readlinkat(dirfd int, path string, buf []byte) (n int, err error)

函数会将符号链接的内容读入buf中,值为oldpath的路径名(不以null结尾)

16 文件的时间

Atim      Timespec //访问时间
Mtim      Timespec //修改内容时间
Ctim      Timespec //修改文件属性时间

type Timespec struct {
        Sec  int64 //秒
        Nsec int64 //纳秒
}

正如前文描述的文件属性

  • Atim为最近一次读取文件正文操作的时间
  • Mtim为最近一次修改文件正文操作的时间
  • Ctim为最近一次修改文件属性的时间
  • 修改文件属性就是修改关联i节点的值
  • 系统并不维护i节点最后访问的时间,所以access stat这些函数不会影响这三种时间

各种函数对文件时间的影响:

对时间影响

修改文件时间:

func Futimes(fd int, tv []Timeval) (err error) //打开的描述符
func Futimesat(dirfd int, path string, tv []Timeval) error //可指定目录描述符和path
func Utimes(path string, tv []Timeval) error //相对路径AT_FDCWD或绝对路径

type Timeval struct {
    Sec  int64
    Usec int64
}

17 创建目录


func Mkdir(path string, mode uint32) (err error)
func Mkdirat(dirfd int, path string, mode uint32) (err error)
func Rmdir(path string) error

注意创建目录时umask的影响,和是否支持设置组
Rmdir实际由Unlinkat实现:

func Rmdir(path string) error {
    return Unlinkat(AT_FDCWD, path, AT_REMOVEDIR)
}

18 更改(获取)当前工作目录 chdir fchdir getcwd

func Chdir(path string) (err error)
func Fchdir(fd int) (err error)
func Getcwd(buf []byte) (n int, err error)

19.文件访问权限小结

这里写图片描述
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,016评论 2 34
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,669评论 0 27
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 午夜时分,风儿时不时地摇动窗户,窗户发出呼呼的声音。除了这声音,这栋房子仿如死寂,再也没能弄出一点动静。 ...
    张翛燃阅读 498评论 0 1
  • 我曾经特别着迷飞人乔丹这个品牌的鞋子,虽然至今我仍然一双都没有拥有。但是,因为飞人乔丹,我花费了大量的无价时间。当...
    红颜江山阅读 230评论 0 1