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

汽车安全 9个月前 admin
163 0 0

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


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



01


文件描述符

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

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

    • 标准输入 0 STDIN_FILENO

    • 标准输出 1 STDOUT_FILENO

    • 标准错误 2 STDERR_FILENO

这个宏定义在头文件

unistd.h


02


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

  • 文件的打开

#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;}


03


文件的读取与写入

这里我们先在试验台随便创建一个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 failuren"); 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 openedn"); }
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


04


文件的偏移量


文件的读写我们学会了,但是一般使用中,肯定不是只有从头或者从尾开始,而是需要移动鼠标到指定的文件位置。这里我们学习一下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 openedn"); }
// 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;}


05


文件与内存

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

#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


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

原文始发于微信公众号(汽车与基础软件):Linux/AP_Autosar/C++系列之 linux系统调用下的IO

版权声明:admin 发表于 2023年7月31日 上午12:14。
转载请注明:Linux/AP_Autosar/C++系列之 linux系统调用下的IO | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...