当前位置: 首页 > news >正文

linux下io操作详细解析

在 Linux 系统下,IO(输入/输出)操作是程序与外部设备(如文件、网络等)交互的重要方式。Linux 提供了丰富的系统调用和库函数来支持各种 IO 操作。以下是对 Linux 下 IO 操作的详细解析,包括文件 IO、网络 IO 和缓冲机制等内容。


一、文件 IO 操作

1. 打开文件(open 系统调用)

open 系统调用用于打开一个文件,返回一个文件描述符(file descriptor),后续操作都通过这个文件描述符进行。

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

int main() {
    int fd = open("example.txt", O_RDONLY); // 打开文件用于只读
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    std::cout << "File opened successfully, file descriptor: " << fd << std::endl;
    close(fd); // 关闭文件
    return 0;
}
  • O_RDONLY:只读模式。

  • O_WRONLY:只写模式。

  • O_RDWR:读写模式。

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

  • O_TRUNC:如果文件已存在,将其长度截断为 0。

  • O_APPEND:写入时将数据追加到文件末尾。

2. 读取文件(read 系统调用)

read 系统调用从文件描述符指定的文件中读取数据。

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

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    char buffer[128];
    ssize_t bytesRead = read(fd, buffer, sizeof(buffer) - 1);
    if (bytesRead == -1) {
        perror("read failed");
        close(fd);
        return 1;
    }

    buffer[bytesRead] = '\0'; // 确保字符串以 null 结尾
    std::cout << "Read " << bytesRead << " bytes: " << buffer << std::endl;

    close(fd);
    return 0;
}
  • read 返回读取的字节数,如果返回 0 表示已到达文件末尾,返回 -1 表示出错。

3. 写入文件(write 系统调用)

write 系统调用将数据写入到文件描述符指定的文件中。

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

int main() {
    int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    const char* msg = "Hello, world!";
    ssize_t bytesWritten = write(fd, msg, strlen(msg));
    if (bytesWritten == -1) {
        perror("write failed");
        close(fd);
        return 1;
    }

    std::cout << "Wrote " << bytesWritten << " bytes." << std::endl;

    close(fd);
    return 0;
}
  • O_CREAT:如果文件不存在,则创建文件。

  • 0644:文件权限,表示所有者有读写权限,组用户和其他用户有读权限。

4. 关闭文件(close 系统调用)

close 系统调用用于关闭文件描述符,释放资源。

close(fd);

二、网络 IO 操作

1. 创建套接字(socket 系统调用)

socket 系统调用用于创建一个套接字,用于网络通信。

#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建 TCP 套接字
    if (sockfd == -1) {
        perror("socket failed");
        return 1;
    }

    std::cout << "Socket created successfully, file descriptor: " << sockfd << std::endl;
    close(sockfd);
    return 0;
}
  • AF_INET:IPv4 地址族。

  • SOCK_STREAM:TCP 套接字。

  • SOCK_DGRAM:UDP 套接字。

2. 绑定地址(bind 系统调用)

bind 系统调用将套接字绑定到一个本地地址和端口。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket failed");
        return 1;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080); // 端口号
    addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有可用地址

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind failed");
        close(sockfd);
        return 1;
    }

    std::cout << "Socket bound to port 8080." << std::endl;
    close(sockfd);
    return 0;
}

3. 监听连接(listen 系统调用)

listen 系统调用将套接字设置为监听状态,等待客户端连接。

if (listen(sockfd, 5) == -1) { // 最大连接队列长度为 5
    perror("listen failed");
    close(sockfd);
    return 1;
}

std::cout << "Server is listening on port 8080." << std::endl;

4. 接受连接(accept 系统调用)

accept 系统调用接受一个客户端连接,返回一个新的套接字用于与客户端通信。

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);

int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
if (clientfd == -1) {
    perror("accept failed");
    close(sockfd);
    return 1;
}

std::cout << "Client connected." << std::endl;

5. 读写网络数据

使用 readwrite 系统调用(或 recvsend 函数)进行网络数据的读写。

char buffer[1024];
ssize_t bytesRead = read(clientfd, buffer, sizeof(buffer) - 1);
if (bytesRead == -1) {
    perror("read failed");
    close(clientfd);
    close(sockfd);
    return 1;
}

buffer[bytesRead] = '\0';
std::cout << "Received message: " << buffer << std::endl;

const char* response = "Hello, client!";
write(clientfd, response, strlen(response));

三、缓冲机制

1. 标准 IO 缓冲

C 标准库提供了缓冲机制,通过 FILE* 指针操作文件。例如:

#include <cstdio>
#include <iostream>

int main() {
    FILE* file = fopen("example.txt", "r");
    if (!file) {
        perror("fopen failed");
        return 1;
    }

    char buffer[128];
    while (fgets(buffer, sizeof(buffer), file)) {
        std::cout << buffer;
    }

    fclose(file);
    return 0;
}
  • fgets 从文件中读取一行,自动处理缓冲。

  • fputs 将字符串写入文件,也使用缓冲机制。

2. 系统调用与缓冲

系统调用(如 readwrite)通常不使用缓冲,直接与内核交互。如果需要缓冲,可以手动实现,例如:

char buffer[1024];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer));

3. 非阻塞 IO 和异步 IO

  • 非阻塞 IO:通过设置文件描述符为非阻塞模式,使 readwrite 在数据未准备好时立即返回

    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  • 异步 IO:使用 aioio_uring 等机制,允许程序在 IO 操作完成之前继续执行。

http://www.dtcms.com/a/123097.html

相关文章:

  • Pandas分块读取技术:高效处理大数据的秘密武器
  • Mysql自动增长数据的操作(修改增长最大值)
  • go-zero学习笔记(六)---gozero中间件介绍
  • nacos配置达梦数据库驱动源代码步骤
  • 【Scrapy】Scrapy教程12——中间件
  • list的使用以及模拟实现
  • Nodejs流
  • 中美贸易摩擦背景下国家车规芯片产业应对策略
  • matplotlib.pyplot常见图形及组合基础用法文档
  • 学习threejs,使用EffectComposer后期处理组合器(采用RenderPass、FilmPass渲染通道)
  • 轻量级锁是什么?轻在哪里?重量级锁是什么?重在哪里?
  • 技术与情感交织的一生 (五)
  • 无人机隐身技术难点要点!
  • [强网杯 2019]随便注 1
  • Matter的优势#4:安全性和加密
  • RHCSA Linux系统 数据流和重定向 tee 命令
  • 【非机动车检测】用YOLOv8实现非机动车及驾驶人佩戴安全帽检测
  • MySQL 的四种社交障碍等级
  • 经济金融最优化:从理论到MATLAB实践——最大利润问题全解析
  • 程序设计竞赛1
  • java笔记03
  • 安装了VM Tools,仍无法复制拖动-解决方案
  • 如何通过前端表格控件实现自动化报表?1
  • wsl2+ubuntu22.04安装blenderproc教程
  • React 的 context 是什么?
  • GPT - 因果掩码(Causal Mask)
  • C语言复习笔记--指针(4)
  • lombok的坑
  • JVM 调试与内存优化实战详解
  • 可编辑37页PPT | 建筑行业DeepSeek日常实操培训