Linux文件编程(open read write close函数)

简介: Linux文件编程(open read write close函数)

前言

本篇文章我们来讲解Linux中的文件编程,这篇文章会先介绍open read write函数。

一、open函数

open 函数是一个在 POSIX 标准中定义的函数,用于打开文件或者创建新文件。它是文件操作中很常用的一个函数,主要用于在程序中访问文件系统。

下面是 open 函数的原型:

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

参数说明:

pathname:要打开或创建的文件路径名。

flags:文件打开的标志,用来指定打开方式和操作权限。

mode:新创建文件的权限(仅在创建新文件时有效)。

open 函数返回一个非负整数,称为文件描述符,它是用于标识打开文件的唯一值。如果函数执行失败,则返回 -1,表示出错。

下面是一些常用的 flags 参数的取值:

O_RDONLY:只读方式打开文件。

O_WRONLY:只写方式打开文件。

O_RDWR:读写方式打开文件。

O_CREAT:如果文件不存在,则创建文件。

O_APPEND:追加方式打开文件,写入内容会追加到文件末尾。

O_TRUNC:如果文件存在,将其内容截断为0,即清空文件。

下面是一些常用的 mode 参数的取值:

S_IRUSR:用户具有读权限。

S_IWUSR:用户具有写权限。

S_IXUSR:用户具有执行权限。

S_IRGRP:用户组具有读权限。

S_IWGRP:用户组具有写权限。

S_IXGRP:用户组具有执行权限。

S_IROTH:其他用户具有读权限。

S_IWOTH:其他用户具有写权限。

S_IXOTH:其他用户具有执行权限。

当前目录下不存在1.txt文件,我们使用open函数来创建并打开一个1.txt文件:

示例代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
    int fd = 0;
    fd = open("1.txt", O_RDWR | O_CREAT);
    if(fd == -1)
    {
        printf("open 1.txt is err\n");
        return -1;
    }
    return 0;
}

运行结果:

在这里我们可以看到整个文件是红色的,因为我们在创建时没有给任何权限,那么这里我们在创建文件时给这个文件一些权限:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
    int fd = 0;
    fd = open("1.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR);
    if(fd == -1)
    {
        printf("open 1.txt is err\n");
        return -1;
    }
    return 0;
}

二、read函数

read 函数是一个系统调用,用于从已打开文件的文件描述符中读取数据。它的原型如下:

#include <unistd.h>
ssize_t read(int fd, void *buffer, size_t count);

参数解释:

fd 是文件描述符,指定要读取数据的文件或设备。

buffer 是一个指针,指向用于存储读取数据的缓冲区。

count 是要读取的字节数,指定要从文件中读取的数据量。

read 函数从文件描述符指定的文件位置开始读取数据,并将其存储到提供的缓冲区中。它返回实际读取的字节数。如果 read 函数返回0,表示已到达文件末尾。如果返回负值,表示读取出错,具体的错误码会存储在全局变量 errno 中供用户程序查询。

使用 read 函数时,需要注意以下几点:

1.在调用 read 之前,应确保文件已经被成功打开并获得有效的文件描述符。

2.缓冲区的大小应足够大,以容纳要读取的数据。

3.返回的字节数可能小于请求的字节数 count,特别是在读取非阻塞文件描述符时,这是正常的情况。

4.多次调用 read 函数可以连续读取更多的数据,直到返回值为0,表示已读取完文件。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
    int fd = 0;
    char buf[1024];
    int len = 0;
    fd = open("1.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); //打开文件,如果不存在则创建文件为可读可写
    if(fd == -1)
    {
        printf("open 1.txt is err\n");
        return -1;
    }
    len = read(fd, buf, 1024);
    if(len != -1)
    {
        printf("read buf : %s len : %d\n", buf, len);
    }
    return 0;
}

先在vi编辑器中修改文件中的内容:

运行结果:

三、write函数

write 函数是一个系统调用,用于将数据写入已打开文件的文件描述符中。它的原型如下:

#include <unistd.h>
ssize_t write(int fd, const void *buffer, size_t count);

参数解释:

fd 是文件描述符,指定要写入数据的文件或设备。

buffer 是一个指针,指向包含要写入的数据的缓冲区。

count 是要写入的字节数,指定要写入的数据量。

write 函数将 count 字节的数据从 buffer 中写入到文件描述符指定的文件中。它返回实际写入的字节数。如果返回负值,表示写入出错,具体的错误码会存储在全局变量 errno 中供用户程序查询。

使用 write 函数时,需要注意以下几点:

1.在调用 write 之前,应确保文件已经被成功打开并获得有效的文件描述符。

2.缓冲区中至少包含 count 字节的数据。

3.返回的字节数可能小于请求的字节数 count,特别是在写入非阻塞文件描述符时,这是正常的情况。

4.可以多次调用 write 函数来连续写入更多的数据。

示例代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
    int fd = 0;
    char buf[1024];
    int len = 0;
    fd = open("1.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); //打开文件,如果不存在则创建文件为可读可写,并且将文件内容全部清除
    if(fd == -1)
    {
        printf("open 1.txt is err\n");
        return -1;
    }
    len = write(fd, "Hello", 6);
    if(len == -1)
    {
        printf("write err\n");
    }
    lseek(fd, 0, SEEK_SET);
    len = read(fd, buf, 1024);
    if(len != -1)
    {
        printf("read buf : %s len : %d\n", buf, len);
    }
    return 0;
}

运行结果:

四、open read write函数本质

当调用 open、read、write 等文件相关的函数时,通常会触发系统调用(syscall),进入操作系统内核执行相应的操作。系统调用是用户程序与操作系统之间的接口,允许用户程序请求操作系统提供的服务和资源。

在执行系统调用时,用户程序通过特殊的指令(例如 x86 架构上的 int 0x80 或 syscall 指令)将控制权转移到操作系统内核。操作系统根据系统调用号识别用户请求的具体服务,并执行相应的操作。

系统调用的执行通常会引起特权转换(从用户模式切换到内核模式),因为内核需要访问受保护的资源和执行特权指令。在这个过程中,会触发一个异常(如 ARM 架构中的 SVC 异常),将控制权转移到内核中的异常处理程序。

异常处理程序在内核中执行所需的操作,例如打开文件、读写文件等。一旦操作完成,控制权将返回到用户程序,继续执行后续的指令。

因此,当调用 open、read、write 等文件相关函数时,通常会触发 SVC 异常,并进入内核执行相应的文件操作。

五、close函数

close 函数用于关闭打开的文件描述符。在使用完文件后,应该调用 close 函数来释放系统资源并确保数据的完整性。

函数原型如下:

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

其中,fd 是需要关闭的文件描述符。如果关闭成功,返回值为0;如果发生错误,返回值为-1。

close 函数的主要作用如下:

1.释放文件描述符:调用 close 函数会释放文件描述符,并使其可供其他程序使用。这是一种良好的资源管理实践,避免文件描述符的浪费。

2.刷新缓冲区:在关闭文件之前,close 函数会自动刷新文件的缓冲区,确保所有的数据都被写入到磁盘中。这样可以避免数据的丢失或不一致。

3.断开与文件的连接:通过关闭文件描述符,close 函数会断开程序与文件之间的连接,不再对文件进行读写操作。这是确保文件的安全性以及其他进程能够访问文件的重要步骤。

总结

本篇文章就讲解到这里,下篇文章继续讲解Linux文件编程。


相关文章
|
9月前
|
Linux 开发工具
7种比较Linux中文本文件的最佳工具
7种比较Linux中文本文件的最佳工具
7种比较Linux中文本文件的最佳工具
|
7月前
|
存储 数据管理 Linux
区分Linux中.tar文件与.tar.gz文件的不同。
总之,".tar"文件提供了一种方便的文件整理方式,其归档但不压缩的特点适用于快速打包和解压,而".tar.gz"文件通过额外的压缩步骤,尽管处理时间更长,但可以减小文件尺寸,更适合于需要节约存储空间或进行文件传输的场景。用户在选择时应根据具体需求,考虑两种格式各自的优劣。
1137 13
|
8月前
|
安全 Linux
Linux赋予文件000权限的恢复技巧
以上这些步骤就像是打开一扇锁住的门,步骤看似简单,但是背后却有着严格的逻辑和规则。切记,在任何时候,变更文件权限都要考虑安全性,不要无谓地放宽权限,那样可能
240 16
|
9月前
|
Linux
【Linux】 Linux文件I/O常见操作技巧
以上就是Linux文件I/O操作的一些技巧,接纳它们,让它们成为你在Linux世界中的得力伙伴,工作会变得轻松许多。不过记住,技巧的运用也需要根据实际情况灵活掌握,毕竟,最适合的才是最好的。
270 28
|
8月前
|
存储 Linux 数据处理
深入剖析Linux中一切即文件的哲学和重定向的机制
在计算机的奇妙世界中,Linux的这套哲学和机制减少了不同类型资源的处理方式,简化了抽象的概念,并蕴藏着强大的灵活性。就像变戏法一样,轻轻松松地在文件、程序与设备之间转换数据流,标准输入、输出、错误流就在指尖舞动,程序的交互和数据处理因此变得既高效又富有乐趣。
137 4
|
9月前
|
Ubuntu Linux
"unzip"命令解析:Linux下如何处理压缩文件。
总的来说,`unzip`命令是Linux系统下一款实用而方便的ZIP格式文件处理工具。本文通过简明扼要的方式,详细介绍了在各类Linux发行版上安装 `unzip`的方法,以及如何使用 `unzip`命令进行解压、查看和测试ZIP文件。希望本文章能为用户带来实际帮助,提高日常操作的效率。
1868 12
|
10月前
|
Linux Shell
Linux系统下快速批量创建和删除文件的方法
总的来说,使用shell脚本来批量处理文件是一种非常强大的工具,只要你愿意花时间学习和实践,你会发现它能大大提高你的工作效率。
544 19
|
8月前
|
Linux
linux文件重命名命令
本指南介绍Linux文件重命名方法,包括单文件操作的`mv`命令和批量处理的`rename`命令。`mv`可简单更改文件名并保留扩展名,如`mv old_file.txt new_name.txt`;`rename`支持正则表达式,适用于复杂批量操作,如`rename &#39;s/2023/2024/&#39; *.log`。提供实用技巧如大小写转换、数字序列处理等,并提醒覆盖风险与版本差异,建议使用`-n`参数预览效果。
|
11月前
|
监控 Linux
Linux基础:文件和目录类命令分析。
总的来说,这些基础命令,像是Linux中藏匿的小矮人,每一次我们使用他们,他们就把我们的指令准确的传递给Linux,让我们的指令变为现实。所以,现在就开始你的Linux之旅,挥动你的命令之剑,探索这个充满神秘而又奇妙的世界吧!
200 19
|
10月前
|
缓存 Linux
如何创建Linux交换文件?Linux交换文件最新创建方法
Swap是Linux中的虚拟内存空间,用于在物理内存不足时将非活动进程移至磁盘,从而优化活动进程的性能。通过创建交换文件(如1GB),可灵活调整交换空间而无需重新分区。步骤包括:使用`fallocate`或`dd`创建文件、设置权限 (`chmod 600`)、格式化 (`mkswap`)、启用交换 (`swapon`)、修改`/etc/fstab`以持久化配置,以及调整`vm.swappiness`值(默认60,建议从10开始)来平衡内存与交换的使用。最后通过`swapon -s`检查状态并重启生效。此方法适用于VPS和专用服务器,需以root用户操作。
270 2