linux open函数功能,Linux系统文件I / O编程(1)--- open()和其他基本功能
发布日期:2022-02-08 20:24:04 浏览次数:39 分类:技术文章

本文共 4414 字,大约阅读时间需要 14 分钟。

20180718130553512326.png

Linux文件I / O系统概述

虚拟文件系统(VFS)

Linux系统成功的关键因素之一是其与其他操作系统和谐共存的能力. Linux系统的文件系统由两层结构构成: 第一层是虚拟文件系统(VFS),第二层是各种特定的文件系统.

VFS用于提取各种特定文件系统的公共部分以形成抽象层,该抽象层是系统内核的一部分,位于用户程序和特定文件系统之间. 它为用户提供了标准的文件系统调用界面. 对于特定的文件系统(例如EXT2,FAT32等),它实际上通过不同文件系统共有的一系列功能指针来调用特定的文件系统功能,以完成实际的不同操作. 使用文件系统的任何程序都必须通过此层使用此接口. 这样,VFS可以使用户免受实施细节和底层文件系统的差异的影响.

VFS的作用: ①抽象特定文件系统的数据结构,并用统一的数据结构进行管理; ②接受来自用户层的系统调用,例如open(),read(),write(),stat(),link()等; ③支持各种特定文件系统之间的相互访问,接受来自内核其他子系统的操作请求,例如内存管理和进程调度.

VFS在Linux系统中的位置如下图1所示:

2b2c3b7512b6331b1d39f32204f540a0.png

使用命令: cat / proc / filesystems,可以检查系统中支持哪些文件系统

154133334b35b6aac92743d8b5e927db.png

第一列表示是否需要在块设备上挂载文件系统. Nodev指示不需要在块设备上挂载后续文件系统.

第二列是内核支持的文件系统.

Linu中的文件和文件描述符

与Windows不同,Linux操作系统基于文件的概念(这非常重要). 该文件是由字符序列组成的信息载体. 基于此,可以将I / O设备视为文件. 因此,用于与磁盘上的普通文件进行交互的同一系统调用可以直接用于I / O设备. 这大大简化了系统对不同设备的处理并提高了效率.

Linux中的文件主要分为4种类型: 普通文件,目录文件,链接文件和设备文件,如下所示:

155d8fe185c42df96f388773236b91cc.png

内核如何区分和引用特定文件?这里使用一个重要概念---文件描述符.

在Linux中,使用文件描述符执行设备和文件上的所有操作. 文件描述符是一个非负整数,它是一个索引值,并指向内核中每个进程打开的文件的记录表. 当打开一个现有文件或创建一个新文件时,内核将文件描述符返回给程序. 当需要读写文件时,还需要将文件描述符作为参数传递给相应的函数. (我们可以理解这种方式,只有在操作文件时,该文件才会具有文件描述符,并且不会为进程未使用的文件提供描述符)

通常,当进程启动时,它将打开三个文件: 标准输入,标准输出和标准错误处理. 这三个文件对应于描述符0、1和2(即宏替换STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO).

尽管基于文件描述符的I / O操作不能直接移植到Linux(例如Windows)以外的系统上,但这通常是实现某些I / O操作的唯一方法,例如Linux中的基础文件操作功能(我将在下面讨论),多通道I / O,TC [/ IP套接字编程接口等. 同时,它们还与Posix标准很好地兼容,因此可以轻松地移植到任何Posix平台. 基于文件描述符的I / O操作是Linux中最常用的操作之一. 让我们在下面谈论它.

低级文件I / O操作

这次主要介绍文件I / O操作的系统调用,主要使用5个函数: open(),read(),write(),lseek()和close(). 这些功能的功能没有缓存,可以直接读写文件(包括设备).

fc022fcd8e5881d695253c7b6dae3e0c.png

1. 基本文件操作

功能说明

●open()函数用于打开或创建文件. 打开或创建文件时,可以指定各种参数,例如文件属性和用户权限.

●close()函数用于关闭打开的文件. 进程终止时,内核自动关闭该进程打开的所有文件. 许多程序使用此功能关闭文件而不显示它.

●read()函数用于将从指定文件读取的数据放入缓冲区,并返回读取的实际字节数. 如果返回0,则表示没有数据可读取,即已到达文件末尾. 读取操作从文件的当前指针位置开始. 从设备文件读取数据时,通常一次最多读取一行.

●write()函数用于将数据写入打开的文件. 写入操作从文件的当前指针位置开始,然后写入磁盘文件. 如果磁盘已满或超过文件的长度,则write()函数将返回失败.

●lseek()函数用于将文件指针定位到指定文件描述符中的相应位置. 每个打开的文件都有读写位置. 打开文件时,读写位置通常指向文件的开头. 如果以其他方式打开文件(例如O_APPEND),则读写位置将指向文件的末尾. 当使用read()或write()时,读写位置将相应增加,lseek()用于控制文件的读写位置. 它只能用于可定位(随机访问)文件操作. 管道,套接字和大多数字符设备文件都无法定位,因此lseek()调用不能在这些文件的操作中使用.

功能格式

下面,我将以表格的形式编写这5个函数的格式,然后添加我的基本实验.

358eaa8790f5b4aa597fe6fdf0b13e72.png

在open()函数中,可以通过“ |”的组合来形成标志参数,但是前三个标志常量(O_RDONLY,O_WRONLY和O_RDWR)不能相互组合. 权限是文件访问权限,可以宏或八进制表示法定义.

a267d8f1332b1e7bf2f396f91d416a9d.png

bc412395260e0f0b7a092e102b629335.png

在读取普通文件时,如果在读取所需字节数之前已到达文件末尾,则返回的字节数将小于您要读取的字节数.

关于size_t和ssize_t之间的区别,如果您不了解,请参阅: 您也可以简单地记住: ssize_t是有符号的整形,size_t是无符号的整形.

4435b6879413c93d2db17f6ae3f2747c.png

写入普通文件时,写入操作从文件的当前指针位置开始.

42a195ac5208c0d2d78888a1fe28e4b6.png

以下是lseek的特殊用法

☆当您要将读写位置移动到文件的开头时: lseek(int fd,0,SEEK_SET)

☆当您要将读写位置移动到文件末尾时: lseek(int fd,0,SEEK_END)

ef70f17037ceb7467c9ea6a1bfafb023.png

☆当您想获取当前文件位置时: lseek(ind fd,0,SEEK_CUR)

注意: Linux系统不允许lseek()在tty设备上起作用. 此操作将导致lseek()返回ESPIPE.

此外,实际上有一个文件创建函数creat(),其函数原型为int creat(const char * pathname,int perms),等效于使用以下调用方法调用open():

open(const char * pathname,(O_CREAT | O_WRONLY | O_TRUNC));

基本实验1:

实验说明: 主要演示open()函数的使用. 首先在您自己的目录中使用该命令: vi open.c创建一个文件,如下所示,我在路径/ home / song / lianxi文件夹下创建了该文件:

cbb679a384f9d74e3c2ae5ac58538af9.png

然后按如下所示编写open.c文件的内容:

1fc0ec86c88bba7fba4fe748198823ad.png

在open.c之后编辑并保存文件夹中包含的所有文件,如下所示:

199085397c805f6a1137e1bd7487fc43.png

使用命令: gcc open.c -o open来编译c文件,如下所示:

12a36f84657978fb8d3e6721d7d16455.png

执行命令: ./open您可以看到我们的实验已成功输出:

83cf5552822678058396b6cf61deaba7.png

使用命令: more temp检查临时文件,我们使用write()编写了一些内容:

f59c9ca45adc9e5c902fa3548442c6a0.png

我将此文件的内容上传到: 单击此处下载,您可以自己下载

基本实验2

实验说明: 基本功能是从一个文件(源文件)读取最后2KB数据并将其复制到另一个文件(目标文件). 在该示例中,源文件以只读模式打开,目标文件以只读模式打开(可以使用读/写模式). 如果目标文件不存在,则可以创建权限的初始值并将其设置为644,即文件所有者可以读写,其他用户只能读取文件组合.

首先使用以下命令: vi copy_file.c和vi src.c在您自己的实验目录中创建文件,如下所示

9-810-jpg_6-1080-0-0-1080.jpg

9b2a8e0e63b851f79df521ad8d2fef97.png

然后按如下所示编辑copy_file.c的文件内容

#include

#include

#include

#include

#include

#include

#define Buffer_Size1024 / *每次读写缓冲区的大小为1KB并行文件系统i o特征,大小不同,运行效率也不同* /

#define Src_File_Name“ /home/song/lianxi/src.c” / *源文件名,建议使用宏定义* /

#define Dest_File_Name“ /home/song/lianxi/dest.c” //目标文件名* /

#define Offset1024 * 2 //复制数据的大小,这里是2KB * /

int main()

{

int src_fd,dest_fd; / *文件描述符* /

unsigned char buff [Buffer_Size]; / *定义用于缓冲数据的数组* /

int real_read_len; / *由read()函数实际读取的字节* /

/ *以只读方式打开源文件* /

src_fd = open(Src_File_Name,O_RDONLY);

/ *以只读模式打开目标文件,如果该文件不存在,请创建该文件并行文件系统i o特征,并且访问许可为644 * /

dest_fd = open(Dest_File_Name,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

ee07d71f37751a5891f30cd8fd7b895c.png

/ *如果打开文件时出错,请退出程序* /

if(src_fd <0 || dest_fd <0)

{

printf(“打开文件错误\ n”);

exit(1);

}

/ *将源文件的读/写指针移到最后2KB的开头* /

lseek(src_fd,-Offset,SEEK_END);

/ *读取源文件中的最后2KB数据并将其写入目标文件,每次读取和写入1KB * /

while((real_read_len = read(src_fd,buff,sizeof(buff)))> 0)

{

写(dest_fd,buff,real_read_len);

}

/ *关闭文件并释放资源* /

close(dest_fd);

close(src_fd);

返回0;

}

您可以自由地放置src.c文件的内容,但是要注意文件内容大于2KB.

我将这两个文件上传到资源网站,我可以自己下载它们: 单击此处下载

编辑后,使用命令: gcc copy_file.c -o copy_file编译文件,然后执行命令: ./copy_file,可以看到dest.c文件是自动生成的

f03e120f13d07b792ac32704ebc01540.png

使用命令: more dest.c查看文件内容

使用命令: ls -l dest.c,您可以看到文件大小恰好是2KB(2048)

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-237931-1.html

转载地址:https://blog.csdn.net/weixin_33132553/article/details/116833490 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:共创桌面linux,摒弃前嫌 KDE携手GNOME共创Linux桌面
下一篇:linux安装ruby环境 rvm,如何快速正确的安装 Ruby, Rails 运行环境

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月05日 21时24分25秒