【问题标题】:Linux open() file descriptorLinux open() 文件描述符
【发布时间】:2011-04-10 02:10:46
【问题描述】:

如果我在不同的线程中打开同一个文件(.txt 文件)几次,返回的文件描述符会不同。如果我尝试使用文件描述符 write(),那么自从多个线程尝试写入同一个文件时,写入函数的任何机会都会被阻止?

我关心的是当一个线程调用写入单个文件时,当另一个线程调用写入同一个文件时也是如此。那么第二个线程的写入会先等待第一个线程的写入完成吗?如果是这种情况,我如何确保第二次 write 调用不会等待并且如果有第一次写入会立即返回,因为我不希望第二个线程的写入等待。

谢谢

【问题讨论】:

  • 不如先试试看吧?
  • 是的..我已经写了代码..问题是我怎么知道写功能被阻止了?关于如何测试的任何建议?
  • Linux 没有内置任何东西来锁定已打开写入的文件。就像拉胡尔说的那样,试试看会发生什么。
  • @xnine - 感谢您的回复。如果写函数不会被阻塞,那么open()的O_NONBLOCK标志有什么用?
  • 我想知道您的一些 cmets 是否对 Unix I/O 上下文中的“阻塞”与“锁定”的含义感到困惑?您正在询问多个线程写入同一个文件,这将是一个“锁定”问题,但您使用的是“阻塞”一词,这是当您尝试从具有没有可读取的数据。

标签: linux


【解决方案1】:

不,但如果最新的 write() 正在写入文件的重叠区域,则它们总是会破坏较早的写入。

一个更常见的问题是关于写入的文件偏移量,这可能是您真正的问题。在这种情况下,答案是:如果您从每个线程调用 open(),则不会。写入将发生在从最后一个 write() 到源自相同原始 open() 调用的任何描述符的剩余文件偏移处,例如由 dup() 获得的描述符,或由同一进程中的线程共享的描述符。

【讨论】:

  • 如果我只调用一次 open() 并获取文件描述符,我能否将您的上述句子总结为,写入将附加到末尾,从而导致它阻塞。如果我多次调用 open 并获取不同的文件描述符,它不会阻塞但它可能会覆盖?
  • 在你给定的条件下,它不会以任何方式阻塞、锁定或同步。
【解决方案2】:

您可以在写入模式下打开文件(在这种情况下,写入可能会相互破坏),或者您可以在附加模式下打开文件(在这种情况下,操作系统将锁定并确保每次写入自动完成,未来写入 - 来自任何线程 - 指向文件的新结尾)。

所以,使用附加模式。您的线程将快速将数据转移到内核队列中(假设您正在刷新),然后您继续进行操作。如果您发现这还不够快,那么您可以尝试将数据从您的单个线程移动到一个专门用于执行文件更新的线程中,但首先要获得一个具有更简单、更清晰的实现的工作系统,然后再进行配置。

【讨论】:

    【解决方案3】:

    如果您有多个线程共享同一个资源(在您的情况下是一个文件),则您有责任使用某种同步(例如,信号量或互斥锁)来确保在任何时候只有一个写入正在进行时间。否则,结果将是不确定的。 Unix 不会为您记录这一点——如果您在一个线程中开始写入,而在另一个线程中正在对同一文件进行写入,则不会发生阻塞。写入将迅速完成,但不保证对底层物理设备的 I/O 操作的顺序——它们甚至可以交错。

    【讨论】:

      【解决方案4】:

      无论你使用进程还是线程,同时写入同一个文件很可能会导致问题,除非它非常小心。

      文件描述符是否相同无关紧要。

      write() 在写入磁盘文件时通常不会阻塞,因为更改只会进入操作系统缓存。执行此操作的任务数无关紧要。

      但是,如果您从多个进程写入文件,则文件中可能会出现垃圾,因为写入的顺序是不确定的。


      如果你想在多个线程中写入同一文件的不同部分,那么你可以使用 pwrite() 写入文件中的特定位置,多个线程可以共享同一个文件描述符。如果您的线程做正确的事情,这没关系。

      这种技术通常不适用于文本文件。文本文件通常只需要一次由一个线程写入即可获得可预测的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-22
        • 2023-03-23
        相关资源
        最近更新 更多