【问题标题】:Read lock on file failed with error number EBADF文件读取锁定失败,错误号为 EBADF
【发布时间】:2018-06-30 07:46:38
【问题描述】:

我正在尝试编写一个测试程序来测试文件锁定是否正常工作。但是,其中一项测试失败了。我正在尝试获取文件的读锁,但测试失败。当我尝试打印错误号时,它打印了9,它表示EBADF,即错误的文件号(或文件描述符)。我还尝试打印文件描述符值,它打印了3,这似乎是一个有效的文件描述符。我正在使用 Netbeans IDE 及其简单测试功能。

要读取的文件与源代码文件在同一文件夹中。

这是我的代码:

#include <stdlib.h>
#include <iostream>
#include <sys/file.h>
#include <sys/unistd.h>
using namespace std;
/*
 * Simple C++ Test Suite
 */
int acquireRLock(int fd, struct flock &lock) {
    lock.l_len = 0;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_type = F_RDLCK;
    struct flock temp_lock = lock;
    fcntl(fd, F_GETLK, &temp_lock);
    if(temp_lock.l_type == F_WRLCK) {
        return -1;
    }
    else {
        int ret_val = fcntl(fd, F_SETLK, &lock);
        if(ret_val == -1) cout << "Failed here errno = " << errno << " fd = " << fd << endl;
        return ret_val;
    }
}
int acquireWLock(int fd, struct flock &lock) {
    lock.l_len = 0;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_type = F_WRLCK;
    struct flock temp_lock = lock;
    fcntl(fd, F_GETLK, &temp_lock);
    if(temp_lock.l_type == F_RDLCK || temp_lock.l_type == F_WRLCK)
        return -1;
    else
        return fcntl(fd, F_SETLK, &lock);
}
int FileOpenTest() {
    int fd = open("test_file.txt", O_WRONLY);
    if(fd == -1) {
        cout << "%TEST_FAILED% time=0 testname=FileOPenTest (newsimpletest) message=file open failed" << endl;
    }
    return fd;
}
void FileReadLockTest(int fd) {
    struct flock lock;
    if(acquireRLock(fd, lock) < 0) {
        cout << "%TEST_FAILED% time=0 testname=FileReadLockTest (newsimpletest) message=file read lock acquire failed" << endl;
    }
}
void FileWriteLockTest(int fd) {
    struct flock lock;
    if(acquireWLock(fd, lock) < 0) {
        cout << "%TEST_FAILED% time=0 testname=FileWriteLockTest (newsimpletest) message=file write lock acquire failed" << endl;
    }
}
void FileWriteTest(int fd) {
    if(write(fd, (void*) "I am a ball", 13) <= 0) {
        cout << "%TEST_FAILED% time=0 testname=FileWriteTest (newsimpletest) message=file write failed" << endl;
    }
}
void FileCloseTest(int fd) {
    if(close(fd) < 0) {
        cout << "%TEST_FAILED% time=0 testname=FileCloseTest (newsimpletest) message=file close failed" << endl;
    }
}
int main(int argc, char** argv) {
    std::cout << "%SUITE_STARTING% newsimpletest" << std::endl;
    std::cout << "%SUITE_STARTED%" << std::endl;

    std::cout << "%TEST_STARTED% FileOpenTest (newsimpletest)" << std::endl;
    int fd = FileOpenTest();
    std::cout << "%TEST_FINISHED% time=0 FileOpenTest (newsimpletest)" << std::endl;

    std::cout << "%TEST_STARTED% FileReadLockTest (newsimpletest)\n" << std::endl;
    FileReadLockTest(fd);
    std::cout << "%TEST_FINISHED% time=0 FileReadLockTest (newsimpletest)" << std::endl;

//    std::cout << "%TEST_STARTED% FileWriteLockTest (newsimpletest)\n" << std::endl;
//    FileWriteLockTest(fd);
//    std::cout << "%TEST_FINISHED% time=0 FileWriteLockTest (newsimpletest)" << std::endl;
//    
//    std::cout << "%TEST_STARTED% FileWriteTest (newsimpletest)\n" << std::endl;
//    FileWriteTest(fd);
//    std::cout << "%TEST_FINISHED% time=0 FileWriteTest (newsimpletest)" << std::endl;

    std::cout << "%TEST_STARTED% FileCloseTest (newsimpletest)\n" << std::endl;
    FileCloseTest(fd);
    std::cout << "%TEST_FINISHED% time=0 FileCloseTest (newsimpletest)" << std::endl;

    std::cout << "%SUITE_FINISHED% time=0" << std::endl;

    return (EXIT_SUCCESS);
}

它显示以下输出:

取消注释获取写锁的代码时,获取写锁并写入文件,但读锁仍然失败,如下面的输出所示。但是,实际行为应该是读锁成功,写锁失败:

请帮助我找出测试失败的原因。

【问题讨论】:

  • @GhostCat,明白了,谢谢..会小心的!
  • 感谢我们快速而友善的回归!

标签: c++ unit-testing netbeans-8 file-locking


【解决方案1】:

man page for fcntl我们可以阅读

为了设置读锁,fd 必须打开以供读取。为了 要放置写锁,fd 必须打开以进行写操作。放置两者 锁类型,以读写方式打开文件。

您正在打开文件

int fd = open("test_file.txt", O_WRONLY);

来自man page for open

O_RDONLY 仅供阅读。

O_WRONLY 仅供写作。

O_RDWR 开放阅读和写作。如果将此标志应用于 FIFO,则结果未定义。

为了放置读写锁,打开文件

int fd = open("test_file.txt", O_RDWR);

【讨论】:

  • 是的,现在读锁测试通过了!但是,现在我面临一个不同的问题;写锁没有按预期失败。如果在同一个文件上存在读锁,则写锁不应该成功。返回的锁类型(temp_lock)是3,这很奇怪。
  • 这也在我的答案中的链接中指定。单个进程只能在文件区域上持有一种类型的锁;如果将新锁应用于已锁定的区域,则现有锁将转换为新的锁类型。
  • 哦,是的,我忘记了。感谢提及! :-)
  • 我遇到了类似的问题。真的不可能使用 O_RDONLY 和 open 然后使用 fcntl 和 f_WRLCK 的 l_type 设置排他锁吗?如何打开文件进行读取,同时防止其他任何内容读取/写入文件?
  • @DaveNottage,首先很抱歉回复晚了,我不知道我是怎么错过你评论的通知的。其次,不,不可能使用 O_RDONLY 打开文件并尝试对其进行写锁定。为此,您将需要 O_RDWR。第三,打开一个文件进行读取并避免其他人在文件中读取/写入,检查当前锁,如果当前锁为 F_RDLCK,则抛出错误。例如,在我的代码中的acquireRLock()acquireWLock() 中执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2023-03-08
相关资源
最近更新 更多