[Linux]---系统编程之基础IO

基础IO

  • 标准库I/O
  • 系统调用I/O
  • 认识文件描述符且理解重定向
  • 文件系统基本认识
  • 文件的软硬链接

⭐标准库I/O

  • fopen :打开文件
  • fclose:关闭文件
  • fwrite:向文件写入数据
  • fread:从文件读出数据
  • fseek:跳转读写位置

函数原型:FILE *fopen(const char *path, const char *mode);

参数解释:
path:文件路径
mode:(打开方式)

  • r:以只读方式打开文件;在起始位置读数据,文件不存在,则报错;
  • r+:以可读可写方式打开;在起始位置读写数据;文件不存在,则报错;
  • w:以只写方式打开文件;从起始位置写入数据;若存在该文件,则清空,若不存在,则创建;
  • w+:以可读可写方式打开;从起始位置读写数据;若存在,则清空,若不存在,则创建;
  • a:以追加只写方式打开;在文件末尾写数据;文件不存在,则创建;
  • a+:以可读,写追加方式打开;读数据在起始位置,写从末尾开始;文件不存在,则创建。

返回值:
打开失败时,文件流指针返回NULL;成功时,返回文件流指针,做为操作文件的操作句柄.

int fclose(FILE *stream);

参数解释:
stream:文件流指针
补充:
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

参数解释:
ptr:是指向要被写入的元素数组的指针(要写入的内容)。
size:是要被写入的块的大小,以字节为单位。
nmemb:是块的个数
stream:表示是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流(要写入的文件)。
返回值:
如果成功,则返回块的个数。失败或者到达文件末尾,则返回0
补充:
当块个数为1,写入的数据不足块的大小,返回值为0,为了防止这种情况,则可以将第二个参数写1,第三个参数写成一个数组的实际大小,则返回得是实际写入的字符串的长度。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数解释:
ptr:用于接收数据的内存地址
size:要读的每个块的字节数,单位是字节
nmemb:块的个数
stream:这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流(要读出的文件)。
返回值:
如果成功,则返回块的个数。失败或者到达文件末尾,则返回0

int fseek(FILE *stream, long offset, int whence);

参数解释:
stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset:这是相对 whence 的偏移量,以字节为单位。
whence:3种情况

  • SEEK_SET:从文件的起始位置偏移
  • SEEK_CUR :从当前读写位置偏移
  • SEEK_END:从文件末尾偏移作用:

该函数的作用:可以向后任意跳转文件的当前读写位置,即使文件没有数据也可以跳转读写位置

c++中的标准库的输入输出:
他们都是FILE*结构体(文件流指针)

标准输入 标准输出 标准错误
文件描述符 0 1 2
宏定义 STDIN_FILENO STDOUT_FILENO STDERR_FILENO

标准库IO接口的操作句柄是:FILE*------文件流指针

⭐系统调用I/O

  • open:打开文件
  • write:向文件中写入数据
  • read:从文件中读取数据
  • lseek:跳转文件中的读写位置
  • close:关闭文件

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)

这是一个不定参函数,当第二个参数为O_CREAT,则必须给出文件的权限,也就是第三个参数(八进制)
参数解释:
pathname:文件路径名
mode :当使用O_CREAT的时候有可能新建文件,因此需要指定文件的权限
mode & (~umask) =实际最终得到的文件权限
flags:选项标志
必选选项(并且只能选择其一):

  • O_RDONLY ----只读
  • O_WRONLY----- 只写
  • O_RDWR------可读可写

可选选项:

  • O_CREAT:若文件不存在则创建。存在则打开
  • O_EXCL :与O_CREAT一起使用,若文件存在则报错,单独是不起作用的
  • O_APPEND:写入数据使用追加写方式
  • O_TRUNC :打开文件的时候清空原有数据

例如:
w+:O_RDWR | O_CREAT |O_TRUNC
a: O_RDWR | O_APPEND | O_CREAT

返回值: 错误返回-1;成功返回一个非负整数—文件描述符—打开的文件的操作句柄

ssize_t write(int fd, const void *buf, size_t count);

参数解释:
fd:open返回的文件描述符—文件的操作句柄—通过这个fd指定要往哪个文件写入数据;
buf:要写入文件的数据的首地址;
count:要写入文件的数据长度;
返回值:成功返回实际写入文件的数据字节长度 失败返回:-1

sszie_t read(int fd,void *buf,szie_t count)

参数解释:
fd:open返回的文件描述符;
buf:一块缓冲区,从文件中读取的数据的放置位置,同时文件的当前读写位置向后移;count:想要读取的数据长度。
返回值:
(1)如果成功,返回读取的字节数;
(2)如果出错,返回-1并设置errno;
(3)如果在调read函数之前已是文件末尾,则返回0

off_t lseek(int fd,off_t offset,int whence)

参数解释:
fd:打开文件所返回的文件描述符;
offset:偏移量;
whence:偏移位置,从哪里开始偏移,有3种情况:

  • SEEK_SET—文件起始位置
  • SEEK_CUR—文件当前读写位置
  • SEEK_END—文件末尾返回值:

返回值:成功时返回当前位置相对于起始位置的偏移量;失败时返回-1

int close(int fd):

作用:通过文件描述符关闭文件,释放资源
fd:文件描述符
返回值:成功返回0,失败时返回-1

⭐认识文件描述符且理解重定向

文件描述符

文件描述符:是一个非负整数,是操作文件的句柄。是内核中一个进程打开的文件描述信息表的下标–通过这个下标可以在内核中找到相应的文件描述信息,通过这个描述信息可以实现文件的操作。

文件描述符操作的原理(文件描述符有个分配规则:最小未使用)
[Linux]---系统编程之基础IO_第1张图片

为什么打开一个文件,如果不操作了一定要关闭,释放资源?
因为文件描述符实际是有限的,若不关闭文件,文件描述符用光,则在进程中就打不开新文件了.

一个程序运行起来,进程中会默认打开三个文件:

  • 标准输入—0
  • 标准输出—1
  • 标准错误—2

重定向

概念:将数据不再写入原本的文件,而是写入新的指定的文件中—实现方式就是替换这个描述符对应的文件描述信息,使文件描述符指向新的文件描述信息。

原理:实际是描述符的重定向,改变描述符所指向的文件,就改变了数据的流向

实现该功能的函数:int dup2(int oldfd,int newfd)
功能:让newfd这个描述符也指向odlfd所指向的文件,这时oldfd和newfd都能够操作oldfd所指向的文件。

文件描述符与文件流指针的关系:
文件描述符:非负整数—系统调用的IO接口
文件流指针:FILE结构体—typedef struct _IO_FILE FILE—库函数IO接口的操作句柄
[Linux]---系统编程之基础IO_第2张图片
问题来了:为什么多此一举封装fd?
请感受系统调用接口和库函数的区别:
[Linux]---系统编程之基础IO_第3张图片
那么问题又来了:缓冲区在什么地方?
在文件流指针的结构体中定义了缓冲区,这个缓冲区通常被称为用户态缓冲区

⭐文件系统基本认识-软硬连接

文件系统:就是磁盘上管理文件的系统
以linux下的ext2文件系统为例:
[Linux]---系统编程之基础IO_第4张图片
文件的存储流程:
通过超级块找到inode位图/数据块位图,通过数据块位图快速找到空闲的磁盘块存储文件数据,通过inode位图快速找到空闲的inode节点存储文件的元信息;—文件数据存储完毕。

获取文件的数据流程:
通过文件名打开一个文件,在所在目录文件中通过文件名找到这个文件的inode节点号;在磁盘超级块中找到inode节点区域,根据inode节点号,快速找到inode节点,得到数据存储的磁盘块号,取出数据。

每一个文件都有一个唯一的inode节点 ;
ls -i:可以看到文件的inode节点号;

⭐文件的软硬链接

软链接 / 硬连接:可以通过软链接文件或者硬链接文件操作源文件

如何创建软链接文件以及硬链接文件:(源文件:test.txt)
为源文件创建一个硬链接文件:ln test.txt test.hard
为源文件创建一个软链接文件:ln -s test.txt test.soft

软链接文件与硬链接文件的区别:

  • 本质区别:软链接文件是一个独立的文件,类似于文件的快捷方式,有自己的inode节点硬链接文件是一个文件的目录项,类似于一个文件的别名,与源文件指向相同的一个inode节点
  • 操作方式的不同:软链接文件通过存储的源文件路径找到源文件inode,进而访问文件数据;硬链接文件直接通过自己的inode节点号直接访问文件数据
  • 删除源文件:软链接失效,硬连接仅仅是链接数-1,依然可以访问
  • 软链接可以跨分区建立,但是硬链接不可以
  • 软链接可以对目录创建,但是硬链接不可以

OK,今天笔者先总结到这里。如有问题或者疑惑,欢迎各位小伙伴们指出。我们一起交流,一起进步!

你可能感兴趣的:(Linux,linux)