Linux IO系统

本文深入解析Linux下的IO操作,涵盖标准库和系统调用两大方面。详细介绍了fopen、fclose、fgetc、fputc、fgets、fputs、fread、fwrite、fprintf、fscanf、rewind、fseek、ftell等API的使用方法及示例代码,同时对比了标准库与系统调用的特性。此外,还探讨了open、creat、close、read、write、lseek等系统调用API,以及errno错误处理机制,最后提及了非阻塞模式设置、文件权限管理、文件结构等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标准库 和 系统调用

Linux C IO学习脑图

标准库

遵守ISO标准,基于流的IO,对文件指针进行操作

系统调用

兼容POSIX标准,基于文件描述符操作

标准库 IO 操作

特性

FILE 结构体,包含文件描述符

带缓存功能

stderr 无缓存,更快看到错误

常用api 以及 示例代码

1、fopen
FILE *fopen(const char *path, const char *mode);

在这里插入图片描述

2、fclose 关闭文件

文件一旦使用完毕,应该用 fclose() 函数把文件关闭,以释放相关资源,避免数据丢失。

int fclose(FILE *fp);

3、fgetc 与 fputc(以字符形式读写文件)

int fgetc (FILE *fp);

fp 为文件指针。fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF

EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。

EOF 不绝对是 -1,也可以是其他负数,这要看编译器的实现。

int fputc ( int ch, FILE *fp );

ch 为要写入的字符,fp 为文件指针。fputc() 写入成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。

4、fgets / fputs(以字符串形式读写文件)
5、fread/fwrite(以数据块的形式读写文件)
6、fprintf/fscanf(格式化读写文件)
7、rewind/fseek(随机读写文件)
8、ftell(获取文件大小)

系统调用 IO 操作

特性

内核提供的系统调用,不带缓存

基于文件描述符,非负整数

errno

errno 错误编码,分析这个错误,strerror(error)

或者直接使用perror(“open error”);,它会调用strerror,对错误码进行解释

perror定义在stdio.h中,如果程序中要使用errno,需要包含errno.h

常用api 以及 示例代码

open

功能:打开或创建一个文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
参数:
    pathname: 要打开或者创建的文件路径
    flags: 分为两类:主类 和 副类
        主类:
            O_RDONLY  只读
            O_WRONLY  只写
            O_RDWR    读写
        副类:
            O_CREAT 如果文件不存在则创建该文件
            O_EXCL 如果使用O_CREAT选项且文件存在,则返回错误消息
            O_TRUNC 如果文件已经存在则截断文件内容
            O_APPEND 以追加的方式打开
            O_NONBLOCK 非阻塞方式打开
    mode:新建文件的访问权限,对于open函数而言,仅当创建新文件时才使用第三个参数
返回值:
	成功返回文件描述符
	失败返回-1

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "usage: %s newfile\n", argv[0]);
        exit(1);
    }

    int fd = open(argv[1], O_RDONLY | O_CREAT | O_TRUNC, 0644);
    // int fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0777); // 创建文件权限 ~umask & mode
    // int fd = open(argv[1], O_RDONLY | O_CREAT | O_EXCL); //当O_EXCL 与 O_CREAT同事使用时,如果文件存在open失败
    if (fd < 0) {
        perror("open error");
        exit(1);
    }
    printf("fd = %d\n", fd);
    close(fd);

    return 0;
}
creat

使用creat函数创建一个新文件,如果原来该文件存在,会将这个文件的长度截短为0。函数定义如下:

#include <fcntl.h>  
int creat(const char *pathname, mode_t mode);

如果成功则返回为只写打开的文件描述符,出错则返回-1。

等价于open函数的O_WRONLY|O_CREAT|O_TRUNC

close

这里要注意下,open函数定义在fcntl.h文件中,和close不一样。

#include <unistd.h>
int close(int filedes);

read

在这里插入图片描述
ssize_t 实际是无符号的整数类型。

返回实际读到的字节数,> 0表示成功

网路中读取,有可能传输的文件很大,可能需要读好多次

write

在这里插入图片描述

lseek

在这里插入图片描述

文件的"读"、"写"使用同一偏移位置。

应用场景:

  • 求文件大小
  • 扩展文件大小(lssek, 10, SEEK_END) + IO操作

高级部分

设置非阻塞模式
  • open方式打开,设置O_NONBLOCK标志

  • 如果文件已经打开,通过fcntl设置

int flag = fcntnl(fd, F_GETFL);

flag |= O_NONBLOCK;

fcntl(fd, F_SETFL, flag);
dup 和 dup2函数

#include <unistd.h>

int dup(int oldfd); 复制文件描述符

int dup2(int oldfd, int newfd); 复制文件描述符 ; 重定向

返回:成功返回新文件描述符,出错返回-1

功能:文件描述符的复制(其实是复制指针),如果newfd已经打开,会先进行关闭

在进程间通信时可用来改变进程的标准输入和标准输出设备

文件权限

access函数 判断文件是否存在、可读、可写、可执行

umask

chmod

fchmod 对已经打开的文件进行操作

文件结构

目录项 i节点 数据块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值