"_locking()"到底是做什么的?

5

我在寻找答案时发现这个问题,其中提到了函数_locking()。它的说明中写道,该函数可以“锁定或解锁文件的字节”(实际上我无法理解这句话的真正意思)。如果有人有使用该函数的经验,请问是否可以将其用于解决第一个问题描述的问题?

4个回答

1

它简单地为获取文件锁的进程保留了文件范围,以供其独占使用。如果锁定调用成功,则试图读取或写入该文件部分的另一个进程将失败。这允许多个进程以一致的方式访问同一文件并对其进行更新。这有点像文件范围的互斥量。

基本上,它允许您原子地更新文件的某些部分,因此任何其他正在读取或写入文件的进程都将看到(或更改)全部更新或全部不更新。它也适用于读取 - 您可以锁定要读取的文件范围,以防止另一个进程在您正在读取时更改其中的一部分。

但是,进程仍然可以无误差或延迟地访问文件的其他部分。

它不会解决你所提到的问题,因为_lock()只在进程粒度上起作用。如果线程A锁定了一个文件范围,那么同一进程中的线程B仍然可以读/写该范围。为了防止同一进程中的另一个线程访问文件范围,该进程必须实现自己的内部机制,以尊重另一个线程锁定了文件范围。至少我不知道Win32 API中有这样的东西(我想可能有我不知道的东西)。


该函数锁定文件以防止所有写入,并使其仅对那些字节可读。用户可以轻松添加一个标志,使线程在进入文件之前进行检查。 - Dennis Hayden
根据文档,锁定会防止对范围的任何访问 - 读取或写入。我需要运行一些测试来证明它是否有其他作用。这也是有道理的,如果进程A正在更改文件中的记录,则进程B在更新完成之前不希望读取该记录。@Dennis - Michael Burr
@Dennis:同时也不要高估“添加标志”有多容易。如果您希望线程间访问检查对文件范围进行细分,您需要保留某种数据结构来指示哪些范围已被锁定,并且您需要同步机制(关键部分对象或其他)来管理对该数据结构的访问。这并不像检查标志那样简单。此外,您需要在需要时显式添加访问检查。如果您没有在正确的时间进行检查,则线程B将在线程A“锁定”范围时访问该范围。 - Michael Burr
这就是我提到竞态条件的整个意义。他使用这个函数也会遇到同样的问题。如果文件被锁定,他必须检查以查看是否已锁定,如果已锁定,则“等待”。他甚至可能会遇到死锁或其他许多问题。我理解他想要锁定和解锁文件。但这只锁定了一部分,他仍然需要做所有其他工作。但我猜我可能错了,所以不要在意。 - Dennis Hayden
@Michael Burr谢谢您的回复。但我不认为它是这样工作的。当我使用_LK_NBLCK模式中的函数锁定文件以锁定文件的所有字节时,即使在同一进程中,我也无法从文件中读取(strerror为“Permission denied”)。也许我做错了什么,应该从传递给_locking()的相同fd中读取,而不是再次打开文件? - Mihran Hovsepyan

1
引用您提供的MSDN页面:
int _locking(
   int fd,
   int mode,
   long nbytes 
);
_locking 函数锁定或解锁由 fd 指定的文件中的 nbytes 字节。在文件中锁定字节可以防止其他进程访问这些字节。所有锁定或解锁都从文件指针的当前位置开始,并继续进行下一个 nbytes 字节。可以锁定超出文件末尾的字节。

是的,我读过这个。但是当我尝试锁定一个文件时,我无法通过同一进程中的ofstream写入该文件。那么锁定字节到底意味着什么? - Mihran Hovsepyan

0

http://msdn.microsoft.com/en-us/library/8054ew2f(v=vs.71).aspx

我发现这有助于“修复”问题竞态条件

最后一个写入文件的人获胜。假设您只需要读取文件的前半部分,没有理由锁定整个文件。

因此,您将文件大小(以字节为单位)传递给此函数,然后将其锁定。

如果成功,该函数将返回0。返回值为-1表示失败,在这种情况下,errno设置为MSDN页面告诉您的内容。

回答您的问题

您可以获取文件的大小,然后将其锁定,但是您只能从文件中读取。您将其锁定为一种只读模式。

在竞态条件的维基中,它告诉您如何通过让第二个进程检查标志来锁定文件,这可能适用于您的情况,请研究一下。


0

它防止其他进程访问文件的同一部分。


@smerlin:是的,它是独占的。 - user541686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接