Linux基础IO


前言

基础IO:文件的输入输出操作–回顾标准库的IO接口/学习linux下系统调用IO接口/文件描述符的理解/重定向的理解/文件系统/库文件

一、回顾标准库的IO接口

fopen/fwrite/fread/fseek/fclose stdin/stdout/stderr
FILE fopen(charfilename,char mode);(文件名称,打开方式)
打开方式:“r-只读 r±读写 w-只写 w±读写 a-追加写 a±追加读写 b-二进制操作"
追加写:每次写入数据总是写入到文件末尾
r+的读写和w+的读写有什么区别??:r+读写打开文件;若文件不存在则报错/w+读写打开文件,若不存在则创建,若存在清空原有内容
a-不仅仅是追加写,并且文件不存在还会创建新文件
b-默认清空如果不指定b,则认为文件是文本操作,加上b则认为是二进制操作;区别在于-有时候一个特殊字符,只是一个字符但是占据两个字节的内存(读取一个100字节大小的文件,文本操作最终读取出来的数据,不一定是100字节)
返回值:返回一个FILE
的文件流指针作为文件的操作句柄;失败返回NULL

size_t fread(char buf,size_t block_size,size_t block_count,FILEfp);(缓冲区,块大小,块个数,文件流指针)
size_t fwrite(char* data,size_t block_size,size_t block_count,FILE*fp):(数据首地址,块大小,块个数,文件流指针);

注意:fread/fwrite 操作的数据实际大小是块大小*块个数; 块大小=10.块个数=2; 意味着要写入/读取20个字节的数据;
返回值:返回实际操作的块个数
例如:读取一个文件size=10;count=2;
如果文件大小足够则返回2
但是若文件大小只有16字节,则会返回1,因为第二块没有读满
fread如果读到了文件末尾会返回0;若读取1000个字节块个数为1,文件大小只有512字节,虽然读取了512数据,但是依然会返回0;

int fseek(FILE*fp,long offset,int whence);(将文件的读写指针从whence位置偏移offset个字节)–跳转文件读写位置
SEEK_SET-从文件起始偏移
SEEK_CUR-从当前读写位置开始偏移
SEEK_END-从文件末尾偏移

int fclose(FILE *fp):关闭文件流指针,释放资源
fread/fwrite比较推荐块大小为1,块个数是想要操作的数据长度
fseek:文件没有数据也可以跳转读写位置;可以向后任意跳转文件的当前读写位置
对文件数据进行字符串操作的时候要注意文件数据中的\0这种数据
打开文件一定不要忘了关闭文件

在这里插入图片描述
在这里插入图片描述

二、系统调用IO接口的学习

标准库中的IO接口–都是库函数–而库函数就是对系统调用接口的一层封装
系统调用IO接口的学习:open/read/write/lseek/close

1. int open(char* filename,int flag,mode_t mode)

#include<fcntl.h>头文件
filename:要打开的文件名称
flag:选项参数–文件的打开方式 必选项/可选项
必选项:O_RDONLY-只读 /O_WRONLY-只写 / O_RDWR-读写 不选的话默认只读
可选项:O_CREAT-文件存在则打开,不存在则创建;O_EXCL与O_CREAT同时使用,文件存在则报错;O_TRUNC-打开文件的同时清空原有内容;O-APPEND-追加写,总是将数据写入到文件末尾
mode:权限—如果使用了O_CREAT有可能创建新文件,就一定要指定文件权限(一定要通过第三个参数指定文件的权限(mode&~ umask)-----umask(0),八进制数字形式
返回值:一个非负整数—文件描述符—文件的操作句柄;失败返回-1;

2.ssize_t write(int fd,char *buf,size_t count);

fd:open返回的文件描述--文件操作句柄
buf:要写入文件的数据的空间首地址
count:要写入的数据大小
返回值:返回实际写入文件的数据字节长度;失败返回-1;

ssize_t write(int fd,char* data,size_t len);
fd:open返回的文件描述—文件的操作句柄–通过这个fd指定要往哪个文件写入数据 data:要写入文件的数据的首地址
len:要写入文件的数据长度
返回值:返回实际写入文件的数据字节长度,错误返回-1;

3.ssize_t read(int fd,char *buf,size_t len);

fd:open返回的文件描述符
buf:从文件中读取数据放到哪块缓冲区中的首地址
len:想要读取的数据长度,注意这个len不能大于缓冲区的大小
返回值:返回的是实际读取到的数据字节长度,错误返回-1;

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

fd:open返回的文件描述符
offset:偏移量
whence:从哪里开始偏移  SEEK_SET-文件起始位置 SEEK_CUR-文件当前读写位置  SEEK_END-文件末尾    返回值:成功返回当前位置相当于起始位置的偏移量;失败返回-1;

5.int close(int fd);—通过文件描述符关闭文件,释放资源;

三、文件描述符

文件描述符:是一个非负整数–操作文件的句柄
在这里插入图片描述

  其实就是内核中一个进程打开的文件描述信息表的**下标**--通过这个下标可以在内核中找到相应的文件描述信息,通过这个描述信息可以实现文件的操作
 **为什么打开一个文件,如果不操作了一定要关闭,释放资源?
    文件描述符实际是有限的;若不关闭文件,文件描述符用光,则在进程中就打不开新文件了**

一个程序运行起来,进程中会默认打开三个文件:标准输入-0-stdin/标准输出-1-stdout/标准错误-2-stderr
文件描述符有个分配规则:最小未使用;
在这里插入图片描述

printf打印数据到标准输出,close(1),就是把标准输出关闭了;打开新文件后,printf并没有把数据打印出来,而是在刷新缓冲区fflush(stdout)后,将数据写入到了文件中。
printf并非真的一定要把数据写入标准输出文件,而是因为printf函数中操作文件的时候操作的描述符是1,原本向1中写入数据,就是向标准输出写入,然后当1指向了新的文件后,这时候printf就会将数据写入到制定新的文件中。(重定向原理)

重定向:将数据不在写入原本的文件,而是写入新的指定的文件中–实现方式就是替换这个描述符对应的文件描述信息
int dup2(int oldfd,int newfd)—描述符重定向
例:dup2(fd,1);//将1重定向到test.txt这个文件

四、在minishell中实现> / >> 标准输出重定向;

ls -l >a.txt
ls -l --依然使用之前的解析方案

清空重定向 open(O_CREAT|O_TRUNC)

追加重定向 open(O_CREAT|O_APPEND)
a.txt fd=open(a.txt); dup2(fd,1); 子进程在运行指令的时候ls本身要将数据写入标准输出

文件描述符与文件流指针的关系:
文件描述符:是一个非负整数----系统调用的IO接口
文件流指针:FILE结构体–typedef struct _IO_FILE FILE --库函数IO接口的操作句柄
通过文件流指针进行最终文件操作的时候,依然还要能够找到文件对应的文件描述符才可以,文件流指针是一个结构体,结构体中有很多成员变量,其中就有一个叫_fileno–这就是文件描述符
代码链接: 添加重定向的minishell.

向文件写入数据,并不会直接写入文件,而是先写入缓冲区中,刷新缓冲区的时候才会写入文件;
系统调用接口是直接将数据写入文件的,系统调用接口是没有这个缓冲区的,只有库函数才存在这个缓冲区

举例:exit退出会刷新缓冲区/_exit退出时不会刷新缓冲区

总结

在这里插入图片描述

<think>好的,我现在需要帮助用户了解Linux下的基础IO操作教程。根据用户提供的引用内容,我需要整合这些信息,并按照系统级指令的要求来组织回答。首先,用户提到引用了四个不同的来源,其中引用了Linux基础IO、进程控制、文件操作以及标准IO和系统调用IO的区别等内容。 首先,我需要确保回答结构清晰,分步骤解释Linux基础IO操作。根据引用[2],Linux中一切皆文件,包括标准输入输出和硬件外设,所以应该从文件描述符和文件操作的系统调用开始。然后,引用[3]和[4]提到了标准IO和系统调用IO的区别,需要详细说明两者的不同以及使用场景。用户可能对如何打开、读写文件,以及文件描述符的管理感兴趣。 接下来,按照系统级指令,所有行内数学表达式需要用$...$格式,但在这个问题中可能数学公式较少,更多是代码和命令。独立公式如果需要的话用$$...$$,不过可能这里不需要。需要检查LaTeX语法是否正确,使用中文回答,并生成相关问题。 然后,根据用户提供的引用内容,需要将相关知识组织成教程。例如,文件描述符的概念、系统调用如open、read、write、close的使用,标准库函数如fopen、fread、fwrite,以及两者的区别和选择。此外,可能需要提到文件权限、缓冲机制等。 还要注意引用标识的正确添加,例如在提到一切皆文件时引用[^2],在标准IO和系统调用IO的区别时引用[^3],在提到fwrite参数时引用[^4]。同时,用户的问题是关于基础IO操作的教程,因此需要涵盖基本操作步骤、常用函数和示例代码。 最后,生成相关问题,可能需要包括系统调用与标准库函数的比较、文件描述符的管理、缓冲机制的影响等。 现在需要将这些内容整合成一个结构清晰的中文回答,符合用户指定的格式,包括代码块和引用标注,最后生成相关问题列表。</think>### Linux 基础 IO 操作教程 #### 一、文件描述符与“一切皆文件”原理 在 Linux 中,所有硬件设备(如键盘、显示器)和软件资源(如普通文件)均被视为**文件对象**。操作系统通过统一的接口(读方法、写方法)驱动这些对象,并使用文件描述符(`fd`)进行管理。例如,标准输入(键盘)对应 `fd=0`,标准输出(显示器)对应 `fd=1`,标准错误对应 `fd=2`[^2]。 #### 二、系统调用 IO 操作 1. **打开文件** 使用 `open` 函数: ```c #include <fcntl.h> int fd = open("test.txt", O_RDWR | O_CREAT, 0644); // 权限模式 0644 ``` - 参数:文件名、标志位(如 `O_RDONLY` 只读)、权限 - 返回值:成功返回文件描述符,失败返回 -1 2. **读写文件** - `read` 函数: ```c ssize_t num = read(fd, buffer, sizeof(buffer)); // 返回实际读取字节数 ``` - `write` 函数: ```c ssize_t num = write(fd, "Hello", 5); // 返回实际写入字节数 ``` 3. **关闭文件** ```c close(fd); // 释放文件描述符 ``` #### 三、标准 IO 库函数 标准 IO(如 `fopen`)通过**用户空间缓冲区**提升效率,适合高频小数据操作[^3]。 1. **打开文件** ```c FILE* fp = fopen("test.txt", "r+"); // 模式包括 "r"(读)、"w"(写) ``` 2. **读写操作** - `fread`: ```c size_t count = fread(buffer, sizeof(char), 100, fp); // 读取100个char类型数据 ``` - `fwrite`: ```c fwrite("Data", 1, 4, fp); // 参数:数据指针、块大小、块数量、文件指针 ``` 3. **关闭文件** ```c fclose(fp); // 刷新缓冲区并关闭 ``` #### 四、系统调用 IO 与标准 IO 的选择 | **场景** | **推荐方法** | **原因** | |------------------------|-------------------|-----------------------------| | 高频小数据读写 | 标准 IO(如 `fprintf`) | 缓冲区减少系统调用次数 | | 直接访问硬件驱动程序 | 系统调用 IO | 绕过缓冲区,直接操作底层 | #### 五、关键概念解析 - **文件描述符表**:每个进程独立维护,通过 `fd` 索引内核中的文件对象。 - **缓冲机制**:标准 IO 的三种缓冲模式(全缓冲、行缓冲、无缓冲)通过 `setvbuf` 设置。 ```c // 示例:复制文件内容(系统调用 IO) #include <unistd.h> #include <fcntl.h> int main() { int src_fd = open("src.txt", O_RDONLY); int dest_fd = open("dest.txt", O_WRONLY | O_CREAT, 0644); char buf[1024]; ssize_t num; while ((num = read(src_fd, buf, sizeof(buf))) > 0) { write(dest_fd, buf, num); } close(src_fd); close(dest_fd); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值