前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >unix环境高级编程(上)-文件篇

unix环境高级编程(上)-文件篇

作者头像
kinnylee
发布2020-10-15 10:09:36
1.5K0
发布2020-10-15 10:09:36
举报
文章被收录于专栏:kinnylee钻研技术

目录

前言

unix基础知识

unix标准化和实现

unix提供的文件IO

文件和目录

标准IO

系统数据文件

前言

笔者将《unix环境高级编程》主要内容总结为三篇:文件篇进程篇高级io和进程间通信三大板块。本文是unix环境高级编程系列文章第一篇:文件篇。该篇主要包括:

unix基础知识

介绍了unix的体系结构,以及unix中的文件和目录,输入输出,程序和进程,信号等基本概念

unix标准与实现

标准包括C语言的标准和操作系统标准,实现包括BSD,FreeBSD,Linux,Solari,Mac os等

unix内核提供的文件io函数

包括文件描述符,对文件的打开,关闭,定位,读,写,改变文件属性操作。内核IO调用基于文件描述符。还介绍了文件的底层数据结构,了解数据结构之后就能理解文件是如何支持共享的

文件和目录

主要介绍文件的属性和属性对应的数据结构,以及各个字段控制的问访问权限,文件类型等。unix中一切皆文件,这些文件包括:普通文件,目录文件,块特殊文件,字符特殊文件,FIFO,套接字和符号链接。最后结束UFS文件系统。

标准IO函数

标准io解决了内核io的很多细节问题,包括缓冲区分配。所有操作基于流和File对象

系统数据文件

最后介绍系统提供的一些数据文件,包括口令文件,阴影文件,朱文杰,登录账号文件,服务数据文件,协议数据文件,网络数据文件等

一. unix基础知识

1. unix体系结构

  • 操作系统是一种特殊的软件,它控制计算机硬件资源,提供程序运行环境
  • 此软件称为内核,它相对较小,位于环境的中心
  • 内核的接口被称为系统调用
  • 公共函数库构建在系统调用接口上
  • 系统调用一般比普通函数调用需要花费更多时间
  • 应用软件可以调用公共函数库或者使用系统调用

2. 文件和目录

  • 文件系统是目录和文件组成的一种层次结构
  • 目录的起点称为根,名称为/符号
  • 目录是包含很多目录项的文件
  • 逻辑上可认为每个目录项都包含文件名和文件属性。物理上是不包含的,因为一个文件可被多次硬链接
  • 文件属性包括:类型(普通文件,目录),大小,所有者,权限,修改时间等。state和fstate函数返回文件属性。

3. 输入和输出

3.1 文件描述符

通常是一个小的非负整数,内核用它标识一个特定进程正在访问的文件

3.2 标准输入,标准输出,标准出错

每当运行一个新程序时,shell都为其打开三个文件描述符:

说明

文件描述符

头文件

标准输入

0

STDIN_FILENO

标准输出

1

STDOUT_FILENO

标准出错

2

STDERR_FILENO

3.3 不用缓冲的io

  • 函数open,read,write,lseek,close提供了不用缓冲的io
  • 这些函数都使用文件描述符
  • 头文件为

3.4 标准io

  • 标准io提供一种带缓冲io的接口
  • 使用标准io无需担心如何选取最佳缓冲区大小,且简化了堆输入行的处理
  • 标准io头文件为

4. 程序和进程

4.1 程序

  • 存放在磁盘,处于某个目录中的可执行文件
  • exec函数执行时,内核将程序读入存储器并执行

4.2 进程

  • 程序的执行实例被称为进程
  • 每个进程都有一个唯一的数字标识,称为进程ID

4.3 进程控制

进程控制的主要函数:fork,exec和waitpid

4.4 线程

  • 进程内所有线程共享同一个地址空间,文件描述符,栈,进程相关属性
  • 线程访问共享数据时需要采取同步措施避免不一致性
  • 线程也用ID标识,但是只在它所属进程内起作用

5. 信号

  • 信号是通知进程已发生某种情况的一种技术
  • 进程如何处理信号有三种选择:
    • 忽略该信号
    • 按系统默认方式处理
    • 捕捉该信号:提供一个函数,信号发生时调用该函数。调用signal函数,第一个参数为信号名称,第二个参数为处理函数

6. 时间值

unix系统一直使用两种不同的时间值

  • 日历时间:UTC时间,用time_t表示。记录自1970年1月1日以来锁经过的秒数
  • 进程时间:cpu时间,用clock_t表示。已时钟滴答计算

二. unix标准化和实现

1. unix标准化

  • ISO c:c语言国际化标准
  • POSIX:可移植的操作系统接口(protable operating system interface)

2. unix实现

  • SVR4:AT&T的UNIX系统实验室产品,初版了系统V接口定义
  • BSD:加州伯克利分校研究和开发的,含有AT&T许可证的代码
  • FreeBSD:BSD去除AT&T许可证代码后,完全免费的版本
  • Linux:1991年Linux开发的一款被目前广泛使用的unix操作系统
  • Mac OS:核心系统是Darwin,基于Mach内核和FreeBSD的组合
  • Solaris:sun公司开发的unix系统版本

三. unix提供的文件IO

1. 文件描述符

  • 内核中,所有打开的文件都通过文件描述符引用
  • 打开,新建时,内核向进程返回一个文件描述符
  • 读写文件时,将文件描述符传给read和write

2. open

  • 作用:创建或打开一个文件
  • pathname参数:文件名字
  • flag参数:由以下值进行“或”组成
    • O_RDONLY:只读
    • O_WRONLY:只写
    • O_RDWR:读写
    • O_APPEND:追加到末尾
    • O_CREATE:文件不存在就创建
    • O_EXCL:同时指定O_CREATE时,如果文件存在,就会出错。使测试和创建成为原子操作
    • O_TRUNC:将文件长度截短为0
    • O_NOCTTY:控制终端相关
    • O_NONBLOCK:非阻塞模式
  • mode参数:文件访问权限,仅新建文件时使用该参数

3. create

  • 作用:创建文件
  • 等价于open(pathname, O_WRONLY|O_CREATE|O_TRUNC, mode)

4. close

  • 作用:关闭文件
  • 关闭会释放加在该文件上的所有记录锁
  • 进程终止时,内核自动关闭它打开的文件,故可以不用显示调用close

5. lseek

  • 作用:设置打开文件的偏移量
  • 默认偏移量为0,如果设置O_APPEND属性,默认偏移量为文件末尾
  • whence的取值:
    • SEEK_SET:设置文件偏移为pos值
    • SEEK_CUR:设置文件偏移为当前位置+pos
    • SEEK_END:设置文件偏移为文件长度+pos

6. read

  • 作用:从打开的文件中读数据
  • 读取成功,返回读到的字节数。读到末尾,返回0。
  • 导致读到的字节数小于要求读字节数的情况:
    • 普通文件:读到达到要求字节数时,已经读到文件结尾了
    • 终端设备文件:一次最多读一行
    • 网络数据:缓存区大小小于要读字节
    • 管道文件:管道包含的字节小于要读字节

7. write

  • 作用:向打开文件中写数据
  • 返回值通常与nbyte相同,否则出错
  • 写成功后,文件偏移量增加写入字节数量

9. 文件共享

9.1 打开文件的内核数据结构

unix支持在不同进程间共享打开的文件,unix内核使用什么数据结构来支持这种共享呢?

  • 进程表记录来所有的进程
  • 每个进程都有一个记录项,用来记录打开文件的文件描述表
  • 文件描述符的每一项包括:
    • 文件描述符标识
    • 指向文件表项的指针
  • 文件表项由内核维护,每一项包括:
    • 文件状态标识(读,写,同步,阻塞等)
    • 当前文件偏移量
    • 指向该文件v节点表项的指针
  • 每个打开文件都有v节点(v-node)结构,这些信息是打开文件时从磁盘读入内存的。包括:
    • 文件类型
    • 对此文件进行各种操作的指针
    • i节点信息(索引信息):包括长度,所有者,所在设备,磁盘位置指针等

9.2 两个独立进程各自打开同一文件

  • 给定的文件,只有一个v节点表项
  • 每个进程都有自己的文件表项,以使自己有独立的文件偏移量

9.3 两个独立进程共享同一个文件表项

  • 使用dup和fork函数时,父子进程对于每一个文件描述符,都共享同一个文件表项,达到文件共享的目的

9.4 创建共享文件的函数

  • dup:返回的文件描述符为可用的最小值
  • dup2:返回fieldes2指定的描述符。如果fieldes2已经打开,就关闭。如果fieldes=fieldes2,不关闭,直接返回。
  • fcntl:也可以创建共享文件

10. 原子操作

  • 原子操作:指多步组成的操作,
  • 任何一个需要调用多个函数的操作都不可能是原子操作,因为中间可能会挂起该进程
  • unix提供了一些函数,使多个操作成为一个“原子操作”
  • O_APPEND标识:lseek和write的原子操作
  • pread:lseek和read的原子操作
  • pwrite:lseek和write的原子操作
  • 调用open时,通过制定O_CREAT和O_EXCL参数,将创建文件作为原子操作

11. sync, fsync, fdatasync函数

这几个函数出现的背景:unix提供的延时写功能,通过提供缓冲区以减少磁盘读写次数,但是降低了文件内容更新速度,这几个函数用于保证缓冲区内容与文件内容的同步,保证一致性。

  • sync:将修改的快缓冲区排入写队列,立马返回,不等待真正写磁盘
  • fsync:针对指定的文件描述符起作用,且等待磁盘写完才返回。同步内容包括数据和文件属性。适用于数据库系统。
  • fdatasync:包括fsync的功能,但是只同步数据,不同步文件属性。

12. fcntl函数

  • 作用:改变已打开文件的性质
  • 参数cmd的取值和作用:
    • F_DUPFD:复制一个现有的文件描述符
    • F_GETFD: 设置文件描述符标记
    • F_SETFD: 获得文件描述符标记
    • F_GETFL: 设置文件状态标记:读,写,追加,阻塞等。
    • F_SETFL: 获得文件状态标记
    • F_GETOWN: 设置异步io所有权
    • F_SEGOWN: 获得异步io所有权
    • F_GETLK:获得记录锁
    • F_SETLK:设置记录锁
    • F_SETLKW:设置记录锁

四. 文件和目录

1. 文件属性

1.1 表示文件属性的数据结构:struct stat

代码语言:javascript
复制

struct stat {

代码语言:txt
复制
mode_t     st_mode;       //文件模式,包含文件类型,用户id,组id,访问权限(9种)等信息
代码语言:txt
复制
ino_t      st_ino;       //inode节点号
代码语言:txt
复制
dev_t      st_dev;        //设备号码
代码语言:txt
复制
dev_t      st_rdev;       //特殊设备号码
代码语言:txt
复制
nlink_t    st_nlink;      //文件的连接数
代码语言:txt
复制
uid_t      st_uid;        //文件所有者
代码语言:txt
复制
gid_t      st_gid;        //文件所有者对应的组
代码语言:txt
复制
off_t      st_size;       //普通文件,对应的文件字节数
代码语言:txt
复制
time_t     st_atime;      //文件数据最后被访问的时间
代码语言:txt
复制
time_t     st_mtime;      //文件数据最后被修改的时间
代码语言:txt
复制
time_t     st_ctime;      //文件状态(i节点状态)的最后修改时间
代码语言:txt
复制
blksize_t st_blksize;    //文件内容对应的块大小
代码语言:txt
复制
blkcnt_t   st_blocks;     //伟建内容对应的块数量

};

代码语言:txt
复制

1.2 如何获取文件属性

  • state:根据文件名获取属性
  • fstate:根据描述符获取属性
  • lstate:返回符号链接的属性

1.3 修改属性的部分方法

  • 访问时间和修改时间: utime函数,参数为struct utimbuf,每一项都是utc时间
  • 文件用户id和组id:chown,fchown,lchown

2. 文件类型:

2.1 st_mode字段控制的文件类型

  • S_ISREG:普通文件。文本或二进制;可执行文件有固定的可被内核识别的格式。
  • S_ISDIR:目录文件。包含其他文件的名字以及指向与这些文件有关信息的指针。
  • S_ISBLK:块特殊文件。提供堆设备(如磁盘)带缓冲的访问,访问长度固定。
  • S_ISCHR:字符特殊文件。提供堆设备(如磁盘)不带缓冲的访问,访问长度不固定。
  • S_ISFIFO:FIFO,命名管道。用于进程间通信
  • S_ISSOCK:套接字。用于网络间进程通信
  • S_ISLINK:符号链接。指向另一个文件

2.2 stat结构体本身控制的文件类型

  • S_TYPEISMQ:消息队列
  • S_TYPEISSEM:信号量
  • S_TYPEISSHM:共享存储对象

3. 文件访问权限

  • 权限位保存在st_mode属性中
  • 9个访问权限位对应的值为:
  • 更改文件访问权限的函数:chmod和fchmod

4. UFS文件系统

4.1 磁盘,分区和文件系统图

  • 一个磁盘分为多个分区,每个分区可以包含一个文件系统
  • i节点是固定长度的记录项

4.2 详细的柱面组的i节点和数据块

  • 每个柱面包括:i节点数组,数据库,目录块
  • 每个i节点包含文件的大部分信息:文件类型,访问权限,长度,占用的实际数据库。(stat结构大多数信息取自i节点)
  • 每个目录块包括:目录名称,i节点号
  • 同一个i节点,可以被不同的目录指向,i节点的链接计数统计指向的数量
  • 文件改名时,实际内容并未移动,只是构造一个新目录项,指向现有的节点,并解除旧记录项的链接

5. 硬链接

硬链接直接指向文件的i节点

5.1 创建一个指向现有文件的链接:link方法

  • 如果newpath已经存在,返回出错
  • 只能创建newpath中最后一个分量,路径中其他部分必须已经存在
  • 很多文件系统不允许堆目录创建硬链接
  • 超级用户能直接创建目录硬链接

5.2 删除一个现有的链接项:unlink方法

  • 将path所引用的文件的链接数减1
  • 只有当连接技术为0,该文件的内容才被删除
  • 对于文件,可以使用remove功能,和unlink一样
  • 对于目录,可以使用rmdir功能,和unlink一样

6. 符号链接

符号链接是指向一个文件的间接指针。

6.1 符号链接是为了避开硬链接的一些限制

  • 硬链接要求链接和文件位于同一文件系统中
  • 只有超级用户才能创建指向目录的硬链接

6.2 使用符号链接需要注意的事情

  • 当调用某个函数时,需要注意函数处理的是链接的文件,还是链接本身

6.3 符号链接相关的函数

  • 创建符号链接: symlink
  • 打开符号链接:readlink

7. 目录

  • 创建目录:mkdir
  • 删除目录:rmdir。入炉链接计数为0,且没有进程打开次目录,释放目录空间。
  • 读取目录:
  • 更改当前工作目录:chdir,fchdir

五. 标准IO

  • 标准io库不仅在unix上,很多操作系统上都实现了。
  • 标准io处理很多细节,例如:缓冲区分配,优化长度执行io等。便于用户使用。
  • 使用的头文件为。
  • 标准io的底层调用了前面介绍的unix内核io。
  • 标准io的缺点是效率低。这与它需要复制的数据量有关

1. 流和File对象

  • unix内核io提供的io函数都是针对文件描述符的
  • 但是标准io的操作是针对流进行的
  • 标准io文件流可用于单字节或宽字节字符集,由流定向决定(fwide函数)。
  • 标准io打开一个文件(fopen函数)时,返回一个FILE的指针,它包含了实际io的文件描述符,指向用于该流缓冲区的指针,缓冲区长度,缓冲区当前字符数,出错标志,文件结束标志等信息
  • 每个进程预定义三个流:标准输入,标准输出,标准出错

2. 缓冲

2.1 缓冲类型

标准io提供三种类型的缓冲

  • 全缓冲:填满标准io缓冲区后才进行实际的io操作(malloc申请缓冲区,flush执行写操作)。
  • 行缓冲:输入输出中遇到换行符时进行实际的io操作。涉及终端设备时,通常用行缓冲。
  • 不带缓冲:不对字符进行缓冲存储。标准出错流通常不带缓冲。

2.2 设置缓冲类型

  • setbuf
  • setvbuf:第三个参数:
    • _IOFBF:全缓冲
    • _IOLBF: 行缓冲
    • _IONBF:无缓冲

3. 打开流

  • fopen:打开一个指定的文件
  • freopen:将一个文件读到一个指定的流。如果流已经打开,就先关闭,已经定向,就先清除定向。
  • fdopen:通过文件描述符打开文件。因为管道和网络通信等特殊文件不能用标准io函数fopen打开,所以用到该函数。
  • type:指定文件的打开方式

4. 读和写流

读写流有三种不同的方式

  • 每次读写一个字符:
    • 读:getc,fgetc,getchar
    • 写:putc,fputc,putchar

不带f前缀的从标准输入流读取数据,带f前缀的从指定流读取数据。不带f前缀的函数不推荐使用,因为它不指定缓冲区大小,会导致溢出。

  • 每次读写一行:
    • 读:gets,fgets
    • 写:puts,fputs
  • 每次读写一定数量的对象(直接io,二进制io):
    • 读:fread,需要指定要读取的元素个数和每个元素的大小
    • 写:fwrite
    • 缺点:不同系统间,交换二进制数据会编译期和计算机体系结构不同而有差异,所以必须用更高级的协议。

5. 定位流

定位标准io流有三种不同的方式

  • ftell(获取),fseek(设置):long类型的文件位置
  • ftello和fseeko:off_t类型的文件位置
  • fgetpos和fsetpos:fpos_t的抽象数据类型表示文件位置

6. 格式化io

6.1 格式化输出

  • printf:格式化数据写到标准输出
  • fprintf:格式化数据到指定流
  • sprintf:格式化的数据送入数组buf中,尾部自动加入null。可能会导致缓冲区溢出,需调用者自己保证
  • 转换说明以%开始

6.2 格式化输入

六. 系统数据文件

1. 口令文件

  • 存放目录:/etc/passwd
  • 数据结构:中的passwd结构体
  • 查看指定用户口令的函数接口:
  • 查看所有用户口令的函数接口:

2. 阴影文件(加密口令)

  • 存放目录:/etc/shadow
  • 查看的接口:

3. 组文件

  • 存放目录:/etc/group
  • 数据结构:中的group
  • 查看指定组:
  • 查看所有组:

4. 其他数据文件

  • 服务器提供服务的数据文件:/etc/services
  • 记录协议信息的数据文件:/etc/protocols
  • 记录网络信息的数据文件:/etc/networks

5. 登陆账号文件

  • 当前登陆进系统的用户:/var/run/utmp
  • 跟踪登陆和注销信息:/var/log/wtmp

6. 获取系统信息

  • 获取主机与操作系统相关信息
  • 只获取主机名

7. 时间格式

  • 日历时间(UTC时间)
  • 更高精度的时间
  • 各种时间的转化关系
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 前言
    • unix基础知识
      • unix标准化和实现
        • unix提供的文件IO
          • 文件和目录
            • 标准IO
              • 系统数据文件
              • 前言
                • unix基础知识
                  • unix标准与实现
                    • unix内核提供的文件io函数
                      • 文件和目录
                        • 标准IO函数
                          • 系统数据文件
                          • 一. unix基础知识
                            • 1. unix体系结构
                              • 2. 文件和目录
                                • 3. 输入和输出
                                  • 3.1 文件描述符
                                  • 3.2 标准输入,标准输出,标准出错
                                  • 3.3 不用缓冲的io
                                  • 3.4 标准io
                                • 4. 程序和进程
                                  • 4.1 程序
                                  • 4.2 进程
                                  • 4.3 进程控制
                                  • 4.4 线程
                                • 5. 信号
                                  • 6. 时间值
                                  • 二. unix标准化和实现
                                    • 1. unix标准化
                                      • 2. unix实现
                                      • 三. unix提供的文件IO
                                        • 1. 文件描述符
                                          • 2. open
                                            • 3. create
                                              • 4. close
                                                • 5. lseek
                                                  • 6. read
                                                    • 7. write
                                                      • 9. 文件共享
                                                        • 9.1 打开文件的内核数据结构
                                                        • 9.2 两个独立进程各自打开同一文件
                                                        • 9.3 两个独立进程共享同一个文件表项
                                                        • 9.4 创建共享文件的函数
                                                      • 10. 原子操作
                                                        • 11. sync, fsync, fdatasync函数
                                                          • 12. fcntl函数
                                                          • 四. 文件和目录
                                                            • 1. 文件属性
                                                              • 1.1 表示文件属性的数据结构:struct stat
                                                              • 1.2 如何获取文件属性
                                                              • 1.3 修改属性的部分方法
                                                            • 2. 文件类型:
                                                              • 2.1 st_mode字段控制的文件类型
                                                              • 2.2 stat结构体本身控制的文件类型
                                                            • 3. 文件访问权限
                                                              • 4. UFS文件系统
                                                                • 4.1 磁盘,分区和文件系统图
                                                                • 4.2 详细的柱面组的i节点和数据块
                                                              • 5. 硬链接
                                                                • 5.1 创建一个指向现有文件的链接:link方法
                                                                • 5.2 删除一个现有的链接项:unlink方法
                                                              • 6. 符号链接
                                                                • 6.1 符号链接是为了避开硬链接的一些限制
                                                                • 6.2 使用符号链接需要注意的事情
                                                                • 6.3 符号链接相关的函数
                                                              • 7. 目录
                                                              • 五. 标准IO
                                                                • 1. 流和File对象
                                                                  • 2. 缓冲
                                                                    • 2.1 缓冲类型
                                                                    • 2.2 设置缓冲类型
                                                                  • 3. 打开流
                                                                    • 4. 读和写流
                                                                      • 5. 定位流
                                                                        • 6. 格式化io
                                                                          • 6.1 格式化输出
                                                                          • 6.2 格式化输入
                                                                      • 六. 系统数据文件
                                                                        • 1. 口令文件
                                                                          • 2. 阴影文件(加密口令)
                                                                            • 3. 组文件
                                                                              • 4. 其他数据文件
                                                                                • 5. 登陆账号文件
                                                                                  • 6. 获取系统信息
                                                                                    • 7. 时间格式
                                                                                    相关产品与服务
                                                                                    领券
                                                                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档