Linux下文件IO

Linux下的文件I/O(Input/Output,输入/输出)是指在Linux操作系统中进行文件读取和写入操作的过程。这是在计算机程序中常见的一项任务,用于与磁盘文件或其他I/O设备(如键盘、屏幕、网络套接字等)交互。文件I/O通常是通过文件描述符(file descriptor)来完成的,它是一个整数,用于标识打开的文件或其他I/O资源。以下是关于Linux文件I/O的详细解释:

文件描述符

在 Linux 中,文件 I/O 通过文件描述符来实现。文件描述符是一个非负整数,用于唯一标识一个打开的文件。通常,文件描述符 0 表示标准输入(stdin),文件描述符 1 表示标准输出(stdout),文件描述符 2 表示标准错误(stderr)。

通过系统调用函数 open(),可以打开或创建文件,并获得一个文件描述符来引用该文件。例如,int fd = open("example.txt", O_WRONLY | O_CREAT, 0644); 打开名为 "example.txt" 的文件以供写入,并返回文件描述符 fd。

open( )

描述:open() 函数用于打开文件或创建新文件,并返回一个文件描述符,以便后续对文件的操作。

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

const char *pathname:要打开或创建的文件的路径和名称。

int flags:用于指定文件操作模式,如只读、只写、读写、追加等。可以使用位掩码进行组合。

mode_t mode:只有在创建新文件时才使用,用于指定文件的权限(例如,读、写、执行权限)。

返回值:成功时返回一个文件描述符(非负整数),表示已打开的文件。如果出现错误,返回值为 -1。如果 open() 返回 -1,可以使用 errno 全局变量来确定错误类型,并采取适当的措施。

示例

打开已存在的文件:int fd = open("example.txt", O_RDONLY);

创建新文件:int fd = open("newfile.txt", O_WRONLY | O_CREAT, 0644);

附加写入文件:int fd = open("example.txt", O_WRONLY | O_APPEND);

同时读写文件:int fd = open("data.txt", O_RDWR);

设置文件权限:int fd = open("newfile.txt", O_WRONLY | O_CREAT, 0644);

close( )

描述:close() 函数用于关闭已打开的文件,释放与文件描述符相关的资源。

参数:int close(int fd);

int fd:要关闭的文件描述符。

返回值:成功时返回 0,失败时返回 -1。

示例

关闭文件描述符:int result = close(fd);

read( )

描述:read() 函数用于从已打开的文件中读取数据。

参数:ssize_t read(int fd, void *buf, size_t count);

int fd:要从中读取数据的文件描述符。

void *buf:用于存储读取数据的缓冲区。

size_t count:要读取的字节数。

返回值:当 read() 返回值为 0 时,表示已经读取到文件的末尾。这是通常发生在读取到文件的最后一部分数据后。在使用 read() 函数时,应该检查其返回值以处理可能的错误情况。如果 read() 返回 -1,可以使用 errno 全局变量来确定错误类型。例如,常见的错误类型包括 EINTR(读操作被中断)、EIO(I/O 错误)、EAGAIN(非阻塞模式下没有数据可读)等。如果文件描述符处于非阻塞模式,并且没有可用的数据可读,read() 可能会立即返回 -1,并设置 errno 为 EAGAIN 或 EWOULDBLOCK。

示例

从文件读取数据:char buffer[1024];  ssize_t bytesRead = read(fd, buffer, sizeof(buffer));

write( )

描述:write() 函数用于将数据写入已打开的文件。

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

int fd:要写入数据的文件描述符。

const void *buf:包含要写入的数据的缓冲区。

size_t count:要写入的字节数。

返回值:在使用 write() 函数时,应该检查其返回值以处理可能的错误情况。如果 write() 返回 -1,可以使用 errno 全局变量来确定错误类型。常见的错误类型包括 EINTR(写操作被中断)、EIO(I/O 错误)、ENOSPC(磁盘空间不足)等。如果文件描述符处于非阻塞模式,并且无法立即写入数据,write() 可能会立即返回 -1,并设置 errno 为 EAGAIN 或 EWOULDBLOCK。

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

向文件写入数据:char buffer[] = "Hello, World!"; ssize_t bytesWritten = write(fd, buffer, sizeof(buffer) - 1);

lseek( )

描述:lseek() 函数用于移动文件指针到指定位置,以便进行随机访问文件。

参数:off_t lseek(int fd, off_t offset, int whence);

int fd:要操作的文件描述符。

off_t offset:偏移量,表示要移动的字节数。

int whence:起始位置,可以是 SEEK_SET(文件开头)、SEEK_CUR(当前位置)、SEEK_END(文件末尾)之一。

返回值:当使用 lseek() 函数时,应该检查其返回值以处理可能的错误情况。如果 lseek() 返回 -1,可以使用 errno 全局变量来确定错误类型。常见的错误类型包括 EINVAL(无效的参数)、ESPIPE(不支持 lseek() 的文件描述符)等。

示例

移动文件指针:off_t newOffset = lseek(fd, 0, SEEK_SET);

获取文件大小:off_t fileSize = lseek(fd, 0, SEEK_END);

fcntl( )

描述:用于获取文件描述符 fd 的状态标志。返回的标志可以包括 O_RDONLY、O_WRONLY、O_RDWR、O_APPEND、O_NONBLOCK 等。

参数:int fcntl(int fd, int cmd, ... /* arg */);

int fd:要操作的文件描述符。

int cmd:要执行的命令,用于指定操作类型。

...:可选参数,根据不同的命令可能需要额外参数。

返回值:根据不同的命令和操作类型,返回不同的值。

示例

获取文件状态标志:int flags = fcntl(fd, F_GETFL);

设置文件状态标志:int result = fcntl(fd, F_SETFL, new_flags);

获取文件描述符标志:int fd_flags = fcntl(fd, F_GETFD);

设置文件描述符标志:int result = fcntl(fd, F_SETFD, new_fd_flags);

ioctl( )

描述:ioctl() 函数用于执行与设备或文件描述符相关的控制操作,通常在特殊设备文件上使用。

参数:int ioctl(int fd, unsigned long request, ...);

int fd:要操作的文件描述符。

int request:要执行的控制命令。

...:可选参数,根据不同的命令可能需要额外参数。

返回值:在使用 ioctl() 函数时,应检查其返回值以处理可能的错误情况。如果 ioctl() 返回 -1,可以使用 errno 全局变量来确定错误类型。

示例:ioctl() 函数的使用方式取决于所执行的具体命令和操作类型,因此示例的代码会因命令而异。

dup( )和dup2( )

描述:dup() 函数用于复制文件描述符,创建一个新的文件描述符,该新文件描述符引用与原始文件描述符相同的文件。dup2() 函数还允许指定新文件描述符的值。

参数

int oldfd:要复制的文件描述符。

int newfd:dup2() 中的新文件描述符,可以指定。

返回值:成功时返回新的文件描述符,失败时返回 -1。

示例

dup() 函数的作用是复制 oldfd 的文件描述符,然后返回一个新的文件描述符,这个新文件描述符和 oldfd 引用相同的文件或设备。新文件描述符是操作系统中未使用的最小文件描述符值。

dup2() 函数的作用是将 oldfd 的文件描述符复制到 newfd,如果 newfd 已经打开,那么它将首先关闭 newfd,然后将 oldfd 复制到 newfd。这可以用于将文件描述符重定向到指定的文件或标准输入/输出。

unlink( )

描述:unlink() 函数用于删除文件,即从文件系统中移除文件的目录项。文件将被删除,但如果有其他文件描述符仍然打开它,数据仍然可以被访问。

参数:int unlink(const char *pathname);

const char *pathname:要删除的文件的路径和名称。

返回值:unlink() 返回 -1,可以使用 errno 全局变量来确定错误类型。常见的错误类型包括 ENOENT(文件或目录不存在)、EACCES(权限不足)、EISDIR(试图删除目录而不是文件)等。

示例

删除文件:要删除文件,可以使用 unlink() 函数并传递文件的路径名作为参数。

删除目录:在使用 unlink() 函数时,应该检查其返回值以处理可能的错误情况。

总之,文件I/O是Linux系统编程中的基础操作之一,它允许程序读取和写入文件,与文件系统进行交互,并且是许多应用程序和工具的核心部分。正确地处理文件I/O操作对于编写高效、可靠的Linux应用程序至关重要。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355

推荐阅读更多精彩内容

  • 一、概述 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定...
    梁帆阅读 1,800评论 0 1
  • 一、文件IO涉及哪些接口?(内核向用户空间提供了哪些接口?) Input ,Output:是从用户空间角度考虑的输...
    3e1094b2ef7b阅读 557评论 0 0
  • 底层文件访问 open系统调用 在遵循POSIX规范的系统上,使用open系统调用并不需要包含头文件sys/typ...
    Select_Ep阅读 1,475评论 1 3
  • 开始本章学习之前了解一些概念: 1、带缓存和不带缓存IO 参考系统调用,用户程序通过系统级别API调用系统函数将请...
    lifesmily阅读 421评论 0 0
  • Linux遵循一切皆文件的理念,任何你能读写的东西都可以用文件描述符来访问。 内核为每个进程维护一个打开文件的列表...
    桔子满地阅读 453评论 0 0