Linux/AP_Autosar/C++系列之 linux系统调用下的IO

无聊逛51
发布于 2023-11-9 13:53
浏览
0收藏

 一步一步走,日坤月累,2023走到最下面

Linux/AP_Autosar/C++系列之 linux系统调用下的IO-鸿蒙开发者社区

文件描述符

在linux中,一切皆为文件,无论是对文件还是对设备进行操作,实际上都是对文件进行操作。

当打开或者创建文件时,内核向进程返回的是一个文件描述符。会有三种情况返回。

  • 标准输入 0 STDIN_FILENO
  • 标准输出 1 STDOUT_FILENO
  • 标准错误 2 STDERR_FILENO

这个宏定义在头文件

unistd.h

文件的打开,创建,与关闭

  • 文件的打开

#include <fcntl.h>

int open(const char *path, int flags);
int open(const char *path, int flags, mode_t mode);

open()函数的第一个参数是要打开或创建的文件的路径。

flags参数是一个整数,用于指定文件的打开方式和属性。它可以通过使用不同的标志位来组合实现不同的功能,常见的标志位包括:

  • O_RDONLY:只读方式打开文件
  • O_WRONLY:只写方式打开文件
  • O_RDWR:读写方式打开文件
  • O_CREAT:如果文件不存在则创建文件
  • O_TRUNC:如果文件存在,将文件长度截断为0
  • O_APPEND:追加方式打开文件,在文件末尾写入数据
  • O_EXCL:与O_CREAT一起使用,确保新创建的文件不存在,如果文件已存在则打开失败

mode参数用于指定新创建文件的权限。

open()函数返回一个文件描述符(非负整数),如果打开或创建文件失败,则返回-1。我们可以使用这个文件描述符来进行后续的读写操作。

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

int main() {
    char buffer[4096];
    int fileDescriptor = open("example.txt", O_RDONLY);
    if (fileDescriptor == -1) {
        // 打开文件失败
        return -1;
    }
    return 0;
}
  • 文件的创建

注意这个不是create, 二十creat. 我也不知道为什么没有e. 

#include <fcntl.h>

int creat(const char *path, mode_t mode);

creat()函数接受两个参数:

  • path:要创建的文件的路径和名称。
  • mode:指定新创建文件的权限。

creat()函数返回打开的文件描述符,如果创建文件失败,则返回-1。

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

int main() {
    int fileDescriptor = creat("example.txt", 0666);
    if (fileDescriptor == -1) {
        // 创建文件失败
        return -1;
    }
    return 0;
}
  • 文件的关闭

#include <unistd.h>

int close(int fd);

close()函数接受一个整数参数fd,表示要关闭的文件描述符。

close()函数返回一个整数值,如果关闭文件成功,则返回0;如果发生错误,则返回-1。

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

int main() {
    int fileDescriptor = open("example.txt", O_RDWR);
    if (fileDescriptor == -1) {
        // 打开文件失败
        return -1;
    }
    int closeResult = close(fileDescriptor);
    if (closeResult == -1) {
        // 关闭文件失败
        return -1;
    }

    return 0;
}

文件的读取与写入

这里我们先在试验台随便创建一个dat文件如下图。

Linux/AP_Autosar/C++系列之 linux系统调用下的IO-鸿蒙开发者社区

现在我们通过上面所学的来读取里面的内容。

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



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

int main()
{
    int fd = -1;

    ssize_t size = -1;

    char buf[10];
    char filename[] = "./data.dat";

    fd = open(filename,O_RDONLY);

    if(fd == -1)
    {
        printf("file open failure\n");
        return -1;
    }else
    {
        printf("file open success \n");

        while(size)
        {
            size = read(fd,buf,10);
            if(-1 == size)
            {
                printf("error happen \n");
                close(fd);
                return -1;
            }else
            {
                if(size > 0)
                {
                    printf("read data size is %ld: \n", size);
                    printf("\"");
                    for(int i =0; i<size; i++)
                    {
                        printf("%c ",buf[i]);
                    }
                    printf("\"\n");
                }else
                {
                    printf("no data any more \n");
                }

            }
        }
    }
}

Linux/AP_Autosar/C++系列之 linux系统调用下的IO-鸿蒙开发者社区

看着有点错乱,这个是因为每一行最后巧了enter, 被识别成


两个空字符。不影响代码阅读

文件的写入

#include <unistd.h>

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

这里我们用write来写入一个文件。

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

int main() {

    int fileDescriptor = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fileDescriptor == -1) {
        // 打开文件失败
        return -1;
    }else{
        printf("file created and opened\n");
    }

    const char *text = "Hello, world!";
    ssize_t bytesWritten = write(fileDescriptor, text, strlen(text));
    if (bytesWritten == -1) {
        // 写入文件失败
        return -1;
    }

    close(fileDescriptor);

    return 0;
}

Linux/AP_Autosar/C++系列之 linux系统调用下的IO-鸿蒙开发者社区

文件的偏移量

文件的读写我们学会了,但是一般使用中,肯定不是只有从头或者从尾开始,而是需要移动鼠标到指定的文件位置。这里我们学习一下lseek.

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

lseek()函数接受三个参数:

  • fd:要操作的文件描述符。
  • offset:根据whence参数来确定偏移量的值。可以是正值、负值或者0。
  • whence:指定偏移量的基准位置,可以使用以下常量:

       ○  SEEK_SET:从文件开头开始计算偏移量。

       ○  SEEK_CUR:以当前位置为基准计算偏移量。

       ○  SEEK_END:以文件末尾为基准计算偏移量。

还是用上一个代码,加了点lseek.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main() {


    off_t offset =-1;
    int fileDescriptor = open("example.txt", O_RDWR);
    if (fileDescriptor == -1) {
        // 打开文件失败
        return -1;
    }else{
        printf("file created and opened\n");
    }

    // const char *text = "Hello, world!";
    const char *text = "facaile";
    //在这里面添加偏移

    

    offset = lseek(fileDescriptor,5,SEEK_SET); //从头数5个
    ssize_t bytesWritten = write(fileDescriptor, text, strlen(text));
    if (bytesWritten == -1) {
        // 写入文件失败
        return -1;
    }

    close(fileDescriptor);

    return 0;
}

文件与内存

文件和内存映射,这里是把文件映射到内存中。

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

mmap()函数接受六个参数:

  • addr:指定映射的起始地址。通常设置为NULL,由操作系统决定实际的地址。
  • length:映射的长度,以字节为单位。
  • prot:指定映射的保护方式,可以使用以下标志的组合:

       ○  PROT_NONE:页面不可访问。

       ○  PROT_READ:页面可读。

       ○  PROT_WRITE:页面可写。

       ○  PROT_EXEC:页面可执行。

  • flags:指定映射的特性,可以使用以下标志的组合:

       ○  MAP_SHARED:映射区域与文件关联,对映射区域的更改会反映到文件中。 

       ○  MAP_PRIVATE:映射区域与文件关联,但对映射区域的更改不会反映到文件中。

       ○  MAP_ANONYMOUS:创建匿名映射,不与文件关联。

       ○  MAP_FIXED:强制将映射区域放置在特定地址处。

  • fd:要映射到内存的文件描述符。如果指定了MAP_ANONYMOUS标志,则应为-1。
  • offset:文件中的偏移量,表示映射的起始位置。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

int main() {
    int fileDescriptor = open("example.txt", O_RDONLY);
    if (fileDescriptor == -1) {
        // 打开文件失败
        return -1;
    }

    struct stat fileInfo;
    if (fstat(fileDescriptor, &fileInfo) == -1) {
        // 获取文件信息失败
        close(fileDescriptor);
        return -1;
    }

    off_t fileSize = fileInfo.st_size;

    // 映射文件到内存
    void *mappedAddress = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fileDescriptor, 0);
    if (mappedAddress == MAP_FAILED) {
        // 映射文件失败
        close(fileDescriptor);
        return -1;
    }

    // 读取内存映射的文件数据
    char *data = (char *)mappedAddress;
    for (off_t i = 0; i < fileSize; i++) {
        printf("%c", data[i]);
    }
    return 0;
}

Linux/AP_Autosar/C++系列之 linux系统调用下的IO-鸿蒙开发者社区




文章转载自公众号:汽车与基础软件

分类
已于2023-11-9 13:53:48修改
收藏
回复
举报
回复
    相关推荐