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

举报
yd_274589494 发表于 2023/07/30 12:00:51 2023/07/30
【摘要】 @TOC 前言本篇文章我们来讲解Linux中的文件编程,这篇文章会先介绍open read write函数。 一、open函数open 函数是一个在 POSIX 标准中定义的函数,用于打开文件或者创建新文件。它是文件操作中很常用的一个函数,主要用于在程序中访问文件系统。下面是 open 函数的原型:#include <fcntl.h>int open(const char *pathname...

@TOC


前言

本篇文章我们来讲解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文件编程。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。