如何以非阻塞方式压缩文件

Posted

技术标签:

【中文标题】如何以非阻塞方式压缩文件【英文标题】:How to compress file in non-blocking way 【发布时间】:2019-02-04 19:54:59 【问题描述】:

我的应用程序有一个类,该类有一个使用 std::ofstream 写入文件的方法。

这是一个多线程应用程序,许多线程可以同时调用 log() 函数。因此,我在 log() 函数中添加了一个 std::lock_guard 互斥锁。

这些线程也可以是瞬态的,这意味着只要父进程存在,它们就不必存在。

一旦文件大小达到最大配置值,就应该重命名和压缩。

文件大小可以大到 1GB。 gzip 需要 20 多秒来压缩它。

因此线程被阻塞,直到 gzip 完成压缩。

我正在寻找一种可以以非阻塞方式压缩文件的方法,以保持 std::lock_guard guard(_log_mutex);记住。

class Logger 
    std::string   _logfile;
    std::mutex    _log_mutex;
    uint64_t      _sequence_number;
    std::ofstream::pos_type _curr_size;

 public:
    void log (std::string message)
    
        // Take the lock
        std::lock_guard<std::mutex> guard(_log_mutex);

        // If size exceeds max then close, rename, and compress.
        if (_curr_size >= MAX_FILE_SIZE) 
            _outputFile.close();

            // Code already in place to rename the file.

            // Compress _logfile ???

            _outputFile.open(_logfile, std::ios::app);
            _curr_size = _outputFile.tellp();
        

        _outputFile << _sequence_number << " : " << message << std::endl;
        _outputFile.flush();
        _curr_size = _outputFile.tellp();
        _sequence_number++;
    

    // Other stuffs...
    ...
;

我尝试了以下,但它仍然阻塞了线程:

compress_file(const char *file_name) 
    pid_t pid;

    pid = fork();

    if (!pid) 
        execl("/usr/bin/gzip", "gzip", "-f", file_name, NULL);
        exit(1);
     else 
        while (wait3(NULL, WNOHANG, NULL) > 0) 
          ;
        
    

【问题讨论】:

我认为您应该在开始异步压缩之前重命名文件并为传入日志打开一个新文件 除了@OznOg 所说的之外,您还可以在额外的线程中进行压缩。 【参考方案1】: 拿锁 关闭信息流 重命名文件 重新打开流 解除锁定 在不阻塞作者的情况下压缩重命名的文件

【讨论】:

以上是关于如何以非阻塞方式压缩文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中解压缩异步方式的zip文件?

无法在 docker 容器内以非阻塞方式读取类路径资源文件

如何使perl在NFS中以非阻塞模式锁定文件

如何以非阻塞方式处理 websocket 数据?

Spring如何以非阻塞方式匹配bcrypt密码

如何以非阻塞方式链接期货?也就是说,如何在不阻塞的情况下将一个future用作另一个future的输入?