Skip to content

Utils_FdWrapper

SweerItTer edited this page Feb 1, 2026 · 3 revisions

FdWrapper API 文档

概述

FdWrapper 是 utilsCore Utils 模块的核心类,提供文件描述符封装功能,自动管理文件描述符生命周期。

职责

  • 自动管理文件描述符生命周期
  • 防止文件描述符泄漏
  • 支持 RAII 模式
  • 支持移动语义

适用场景

  • 打开文件
  • 创建 socket
  • 管道通信
  • 事件监听

依赖关系

  • 依赖: Linux 系统调用(fcntl.h, unistd.h)
  • 被依赖: UdevMonitor, V4L2 等模块

类分析

FdWrapper 类

职责与用途

FdWrapper 是文件描述符的封装类,提供:

  • 自动关闭文件描述符
  • 文件描述符访问
  • 支持移动语义
  • 防止拷贝

设计模式

  • RAII: 自动管理文件描述符生命周期
  • Wrapper 模式: 封装文件描述符操作

公共 API 方法

构造函数

explicit FdWrapper(int fd = -1);
~FdWrapper();

参数说明:

  • fd (输入): 文件描述符,默认 -1 表示无效

返回值: 无

所有权归属:

  • FdWrapper 拥有文件描述符的所有权

注意事项:

  1. 默认构造创建无效文件描述符(fd = -1)
  2. 析构时自动关闭有效的文件描述符
  3. 析构时打印关闭信息到 stdout

使用例程:

// 创建空包装器
FdWrapper fd1;

// 包装现有文件描述符
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
FdWrapper fd2(sockfd);

禁止拷贝

FdWrapper(const FdWrapper&) = delete;
FdWrapper& operator=(const FdWrapper&) = delete;

说明: 禁止拷贝构造和拷贝赋值,防止重复关闭文件描述符


移动构造

FdWrapper(FdWrapper&& other) noexcept;

参数说明:

  • other (输入): 右值引用

返回值: 无

所有权归属:

  • 所有权从 other 转移给 this

注意事项:

  1. 接管 other 的文件描述符
  2. other 的 fd_ 设置为 -1,避免重复关闭

使用例程:

FdWrapper fd1(open("file.txt", O_RDONLY));
FdWrapper fd2 = std::move(fd1);  // fd1 的 fd 转移给 fd2
// fd1 现在的 fd_ = -1

移动赋值

FdWrapper& operator=(FdWrapper&& other) noexcept;

参数说明:

  • other (输入): 右值引用

返回值: *this

所有权归属:

  • 关闭当前文件描述符(如果有效)
  • 接管 other 的文件描述符

注意事项:

  1. 先关闭当前文件描述符(如果有效)
  2. 接管 other 的文件描述符
  3. other 的 fd_ 设置为 -1

使用例程:

FdWrapper fd1(open("file1.txt", O_RDONLY));
FdWrapper fd2(open("file2.txt", O_RDONLY));

fd1 = std::move(fd2);  // 关闭 file1,接管 file2

get() - 获取文件描述符

int get() const;

参数说明: 无

返回值: 文件描述符

所有权归属:

  • 只读访问,不转移所有权

注意事项:

  1. 返回底层的文件描述符
  2. -1 表示无效文件描述符

使用例程:

FdWrapper fd(open("file.txt", O_RDONLY));

if (fd.get() >= 0) {
    // 使用文件描述符
    read(fd.get(), buffer, size);
}

私有成员

closeFd() - 关闭文件描述符

void closeFd();

行为:

  1. 如果 fd_ >= 0,打印关闭信息到 stdout
  2. 调用 close(fd_)
  3. 设置 fd_ = -1

完整代码

#ifndef FD_WRAPPER_H
#define FD_WRAPPER_H

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

class FdWrapper {
public:
    explicit FdWrapper(int fd = -1) : fd_(fd) {}

    FdWrapper(const FdWrapper&) = delete;
    FdWrapper& operator=(const FdWrapper&) = delete;

    FdWrapper(FdWrapper&& other) noexcept : fd_(other.fd_) {
        other.fd_ = -1;
    }

    FdWrapper& operator=(FdWrapper&& other) noexcept {
        if (this != &other) {
            closeFd();
            fd_ = other.fd_;
            other.fd_ = -1;
        }
        return *this;
    }

    ~FdWrapper() {
        closeFd();
    }

    int get() const { return fd_; }

private:
    int fd_;

    void closeFd() {
        if (fd_ >= 0) {
            fprintf(stdout, "[FdWrapper] close fd: %d\n", fd_);
            close(fd_);
            fd_ = -1;
        }
    }
};

#endif // FD_WRAPPER_H

线程安全说明

同步机制

  • 无锁设计
  • 不保证线程安全

线程安全建议

  • 单线程使用
  • 多线程使用需要外部同步

典型使用场景

场景 1: 基本使用

FdWrapper fd(open("file.txt", O_RDONLY));

if (fd.get() >= 0) {
    char buffer[1024];
    ssize_t n = read(fd.get(), buffer, sizeof(buffer));
    printf("Read %zd bytes\n", n);
}
// 文件描述符自动关闭
// 输出: [FdWrapper] close fd: 3

场景 2: Socket 编程

FdWrapper sockfd(socket(AF_INET, SOCK_STREAM, 0));

if (sockfd.get() >= 0) {
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

    if (connect(sockfd.get(), (struct sockaddr*)&addr, sizeof(addr)) == 0) {
        printf("Connected\n");
    }
}
// Socket 自动关闭
// 输出: [FdWrapper] close fd: 4

场景 3: 移动语义

FdWrapper create_fd() {
    FdWrapper fd(open("file.txt", O_RDONLY));
    return fd;  // 移动构造
}

auto fd = create_fd();
// 使用 fd...
// 析构时自动关闭

场景 4: 移动赋值

FdWrapper fd1(open("file1.txt", O_RDONLY));
FdWrapper fd2(open("file2.txt", O_RDONLY));

printf("Before: fd1=%d, fd2=%d\n", fd1.get(), fd2.get());

fd1 = std::move(fd2);

printf("After: fd1=%d, fd2=%d\n", fd1.get(), fd2.get());
// 输出: [FdWrapper] close fd: 3

场景 5: 异常安全

void process_file(const std::string& filename) {
    FdWrapper fd(open(filename.c_str(), O_RDONLY));
    
    if (fd.get() < 0) {
        throw std::runtime_error("Failed to open file");
    }
    
    // 处理文件...
    // 即使抛出异常,文件描述符也会自动关闭
}

注意事项

  1. 自动关闭: 析构时自动关闭文件描述符
  2. 所有权: 注意所有权转移,使用移动语义
  3. 禁止拷贝: 只支持移动,不支持拷贝
  4. 无效描述符: -1 表示无效文件描述符
  5. 调试信息: 析构时会打印关闭信息
  6. 线程安全: 不保证线程安全
  7. 异常安全: RAII 保证异常安全
  8. 移动后: 移动后的对象 fd_ = -1

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally