《Liunx编程》第4章 输入输出与文件系统笔记 (上)

概念

文件系统是操作系统中负责存储管理信息的模板,用同一方式管理用户系统信息的存储、检索、更新、共享和保护,为用户提供文件使用操作方法。

4.1 文件系统层次结构
4.1.1 文件系统层次结构

常见外存磁盘:有两个特点给用户是用户不能像操作内 存数据结构一样来读写磁盘:一是磁盘属于外部设备,外设编程难度极大;二是内存与磁盘 之间只能以数据块而不是以字节为单位来传递数据,数据块大小通常为磁盘块大小,通常为 512B~4KB

为实现对磁盘的高效便捷的操作,操作系统通过文件系统来存储、定位、提取数据。为驾驭系统复杂性,通常将文件系统设计成多层结构
Linux文件管理系统结构

4.1.2文件I/O库函数

标准 I/O 库是 C 语言规范 ANSI C 支持的文件操作函数 I/O 库。它将一个打开的文件模 型化为一个流,流是一个指向 FILE 类型的结构的指针。一般支持C语言的环境都支持标准I/O库,包括Linux C和Windows C环境。

RIO库为弥补系统I/O在读文本行和处理不足值设计的,在用户 态设置缓冲区,自动处理read/write函数不足值,支持以文本行为单位读取数据。

在这里插入图片描述


4.2 系统I/O概念与文件操作编程
4.2.1 UNIX I/O

一个UNIX文件就是一个m个字节的序列。所有的I/O设备均模块化为文件,而所有的输入和输出都被当做 对相应文件的读和写来执行。UNIX内核引出一个UNIX I/O 接口提供方式来执行所有输入输出,读写时不管数据内容,只管指定数量的字节。

UNIX I/O包括以下几个系统调用函数:

  • open/close 打开/关闭文件函数

每个进程开始时都有三个打开的文件:标准输入 (描述符为0)、标准输出(描述符为1)和标准错误输出(描述符为2)。头文件<unistd.h> 定义了三个宏STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,用来代 替文件描述符值0、1、2。

  • read/write 读写文件
  • lseek 改变当前文件位置
4.2.2 打开和关闭函数
  1. 打开函数
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 
int fd = open(char* filename, int flags, mode_t mode); 
//返回: 若成功返回新文件描述符,若出错为-1。open函数将filename(文件名)转换为一个文件描述符,并且返回描述符数字。

(1)flags

  • O_RDONLY//只读(read only?)
  • O_WRONLY//只写(write only?) 写入内容替换写入位置数据。
  • O_RDWR//可读可写,写入内容替换写入位置数据。
    上述三种是互斥的, 不可同时使用, 但可与下列的旗标利用OR(|)运算符组合.
  • O_CREAT//文件不存在的话,会建立一个新文件
  • O_TRUNC//清空文件内容。
  • O_APPEND//以添加方式打开文件,在每次写操作前,设置文件读写指针到文件的结尾处。(说白了就是追加吧)
fd = open("foo.txt" , O_WRONLY|O_APPEND , 0);//追加输入
fd = open("foo.txt" , O_WRONLY|O_TRUNC , 0);//清空输入

(2)mode

调用open函数打开已存在文件,参数mode一般设置为0。但若打开一个不存在的文件,open就会创建一个新文件,这时mode参数就会指定新文件的访问权限位,否则文件 访问权限为全0,mode参数值可以是一个3位的八进制数值。

mode权限

掩码umask变量中为1的位是不允许新创建文件拥有的权限位,因此使用带mode 参数的open 函数调用来创建一个新文件时,应从mode参数指定的权限位中去除umask中权限位,文件的实际访问权限位被设置为mode-umask。(文件实际权限=mode-umask)。

很多Linux系统中umask的缺省值设置为八进制数 0022(以0开始的数为八进制数),表示同组用户和其他用户都没有写操作,这样可以保护 用户创建的文件被他人有意或无意修改、删除。
2. 关闭函数

#include <unistd.h> 
int close(int fd); //返回: 若成功则为0. 若出错为-1.
4.2.3 文件读写编程与读写性能改进方法
#include <unistd.h> 
ssize_t read(int fd , void *buf , size_t n); 
//read函数从描述符为fd的当前读写位置拷贝最多n个字节数据到存储器位置buf
//返回:若成功则为读出的字节数,若遇EOF 则为0. 若出错为-1. 
ssize_t write(int fd , const void *buf, size_t n); /
//write函数从缓冲区buf拷贝至多n个字节数据到文件fd的当前读写位置
//返回:若成功则为写入的字节数,若出错则为-1.

在这里插入图片描述
注:与基本的运算操作相比,I/O函数开销很大,在应用开发中进行优化有时会使运行速度呈倍甚至呈数量级提高。因此,一次write或read调用传输的字节数不宜太少,否则会严重文件读写速度,一般安 排每次读写几个KB就可使文件读写获得高性能。但每次读写字节数也不要太大,否则会带 来较大的内存开销

4.2.4 文件定位与文件内容随机读取

lseek系统调用函数对文件描述符的读写指针进行调整

#include <unistd.h> 
#include <sys/types.h> //offset定义在头文件sys/types.h中
off_set lseek(int fd, off_ t offset , int whence); 
//返回值:成功时调整后的读写位置,lseek返回从文件头到文件指针被设置处的字节偏移值,失败时返回-1。

其中,offset参数用来指定位置,而whence参数定义该偏移量的用法,whence可取下列值之 一:

  • SEEK_SET:从文件起始位置移动,结果读写指针位置为:offset
  • SEEK_CUR:从当前位置移动,结果为:当前读写指针值+offset
  • SEEK_END:从文件末尾位置移动,结果为:文件长度+offset
    注:若位置计算结果小于0,则lseek执行失败,读写指针不移动,函数返回值为-1;若位置计算 结果超过文件长度,则将文件大小按指针值进行扩展。
4.2.5 任意类型数据的文件读写

read、write函数在内存和文件之间传输一个数据块内容,这个数据块在内存中的地址为buf,在文件中位置为pos。这个数据块位于内存中时,其内容可以是任何类型,如整型、浮点型、字符串、数组、结构体、联合体,因此,UNIX I/O可以实现任意类型数据的文件读写功能。

假设我们用T var定义了一个类型为T的变量var,则该变量所在内存块的地址为&var, 可将其转换成void 指针类型(void )&var,该内存块长度为sizeof(T),所以将变量var的值写入文件fd当前位置的write函数调用为write(fd,(void)&var,sizeof(T))。同样,将保存在文件当前位置的变量var的值读回内存的read函数调用应为read(fd,(void)&v, sizeof(T))。

4.2.6 用读写函数操作设备

Linux系统将设备看成文件,可以用UNIX I/O函数打开设备获得文件描述符,然后通过文件描述符从设备读数据,或向设备写数据。

注:读写每个进程专用的标准输入设备(键盘输入)、标准输出设备(终端窗口)、标准错误输出设备(终端窗口),这三个设备文件已经在程序启动时由系统打开,文件描述符分别为0、1、2,相应的宏为 STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。
Linux系统的每个命令终端窗口都有一个设备文件名,打开两个命令终端窗口, 可用tty命令查看各自的设备名。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值