首页 > 解决方案 > 如何使用 C/++ 在 linux 中正确写入磁带驱动器?

问题描述

我目前正在尝试通过 C++ 写入 LTO 磁带设备。我的问题是,随后的写入请求将导致“无效参数”错误,而第一次调用似乎工作得很好。

我已将磁带机设置为使用 64k 的固定块大小(这意味着一次只能以 64k 或 64k 倍数的块写入)。
现在尝试通过 fwrite() 对其进行写入时,第一次调用将成功(或至少返回写入的请求的条目数量),但后续调用(使用相同的参数)将导致没有数据被写入( fwrite 返回 0) 和“无效参数”错误。
以下是一个小的示例应用程序,用于复制该问题。

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

#define BLOCK_SIZE (64 * 1024)
#define DATA_BLOCKS 32
#define byte unsigned char

int main(int argc, char *argv[]) {
    if (argc <= 1) {
        std::cout << "Missing first parameter: Target file\n";
        return 1;
    }

    // Create file handle to access tape device in RW mode
    FILE* handle;
    const char* targetFile = argv[1];
    if (access(targetFile, R_OK | W_OK) == 0) {
        handle = fopen(targetFile, "r+");
        printf("Create handle OK: %s\n", targetFile);
    } else {
        printf("Could not access %s: Missing rad or write permission\n", targetFile);
        return 1;
    }

    // Create an byte array with data for DATA_BLOCKS blocks
    byte *data = new byte[BLOCK_SIZE * DATA_BLOCKS];

    // Initialize with some data
    for (int i = 0; i < BLOCK_SIZE * DATA_BLOCKS; i++) {
        data[i] = '5';
    }

    // Write data in BLOCK_SIZE chunks, blocksToWrite times per fwrite() call, in numberOfWriteCalls fwrite() calls
    size_t blocksToWrite = 4;
    int numberOfWriteCalls = 5;

    size_t written;
    for (int i = 0; i < numberOfWriteCalls; i++) {
        written = fwrite(data, BLOCK_SIZE, blocksToWrite, handle);
        printf("Round %d: Wrote %d entries of expected %d entries\n", i+1, (int) written, (int) blocksToWrite);

        // Check if there was an error and if so, print error info to stderr
        if (ferror(handle)) {
            printf("Error while writing:\n");
            perror("");
            clearerr(handle);
        }

        /* Start modification: Added flushing, as pointed out by user7860670 */
        fflush(handle);

        // Check if there was an error and if so, print error info to stderr
        if (ferror(handle)) {
            printf("Error while flushing:\n");
            perror("");
            clearerr(handle);
        }
        /* End modification: Added flushing, as pointed out by user7860670 */
    }

    delete[] data;

    // Close file handle
    fclose(handle);

    return 0;
}

此代码调用 fwrite 函数 5 次,每次尝试写入 4 块 64k 数据。这适用于普通文件,但在我的所有磁带设备上返回以下输出:

Create handle OK: /dev/nst0
Round 1: Wrote 4 entries of expected 4 entries
Round 2: Wrote 0 entries of expected 4 entries
Invalid argument
Round 3: Wrote 0 entries of expected 4 entries
Invalid argument
Round 4: Wrote 0 entries of expected 4 entries
Invalid argument
Round 5: Wrote 0 entries of expected 4 entries
Invalid argument

可以看出,第一次调用的反应如预期:fwrite 返回已写入 4 块数据。但是所有后续调用,即使使用相同的参数,也会返回 0 个写入块和“无效参数”错误。
尝试写入我不知道的磁带文件时是否有任何“特殊调味料”,或者我可能以错误的方式使用 fwrite 功能?

标签: c++linuxioalignmentsequential

解决方案


推荐阅读