文件锁定与信号量

发布于 2024-09-16 14:06:31 字数 188 浏览 8 评论 0原文

只是出于好奇,在 Linux 上实现进程间同步的首选方法是什么? sem*(2) 系列系统调用似乎有一个非常笨重且过时的界面,而锁定文件的方法有三种 - fcntl()flock() 和lockf()。

内部差异是什么(如果有)以及您如何证明每个差异的使用合理性?

Just out of curiosity, what is the preferred way to achieve interprocess synchronization on Linux? The sem*(2) family of system calls seem to have a very clunky and dated interface, while there are three ways to lock files - fcntl(), flock() and lockf().

What are the internal differences (if any) and how would you justify the usage of each?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

謌踐踏愛綪 2024-09-23 14:06:31

两者都不。 pthread_* 的实际版本(例如 phtread_mutex_t)都允许将变量放置在通过 shm_open 创建的共享段中。您只需在 init 调用中添加一些额外的参数即可。

如果没有必要,请不要使用信号量 (sem_t),它们的级别太低并且会被 IO 等中断。

不要滥用文件锁定来进行进程间控制。它不是为此而设计的。特别是,您无法刷新文件元数据(例如锁),因此您永远不知道锁/解锁何时对第二个进程可见。

Neither. The actual versions of pthread_* (eg. phtread_mutex_t) all allow to place the variables in shared segments that are created via shm_open. You just have to place some extra parameter to the init calls.

Don't use semaphores (sem_t) if you don't have to, they are too low level and are interupted by IO etc.

Don't abuse file locking for interprocess control. It is not made for that. In particular, you don't have a possibility to flush file meta-data such as locks, so you never know when a lock / unlock will become visible to a second process.

忆离笙 2024-09-23 14:06:31

正如《DarkDust》指出的那样,你正在经历来自丰富历史的大量选择。对于它的价值,我的决策树是这样的:

当一次只有一个进程/线程可以访问时使用互斥体。

当两个或多个(但仍然有限)进程/线程可以使用资源时使用信号量。

使用 POSIX 信号量,除非您确实需要 SYSV 信号量所具有的功能 - 例如 UNDO、上次操作的 PID 等。

对文件使用文件锁定,或者如果上述内容在某些方面不符合您的要求。

You are suffering a wealth of choices from a rich history, as DarkDust noted. For what it's worth my decision tree goes something like this:

Use mutexes when only one process/thread can have access at a time.

Use semaphores when two or more (but nevertheless finite) processes/threads can use a resource.

Use POSIX semaphores unless you really need something SYSV semaphores have - e.g. UNDO, PID of last operation, etc.

Use file locking on files or if the above don't fit your requirements in some way.

我不在是我 2024-09-23 14:06:31

不同的锁定/信号量实现都在不同的系统上实现。在 System V Unix 上,您有 semget/semop,POSIX 使用 sem_initsem_wait定义了不同的实现>sem_post。据我所知,flock 起源于 4.2BSD。

由于它们都具有一定的重要性,Linux 现在都支持它们以便于移植。此外,flock 是互斥体(锁定或解锁),但 sem* 函数(SysV 和 POSIX)是信号量:它们允许应用程序授予多个并发进程访问,例如,您可以允许 4 个进程使用信号量同时访问资源。您可以使用信号量实现互斥锁,但反之则不然。我记得在 Marc J. Rochkind 的优秀《高级 UNIX 编程》中,他演示了如何通过信号量在进程之间传输数据(非常低效,他这样做只是为了证明可以做到)。但我找不到任何关于效率的可靠信息。

我想这更像是“使用你想要的”。

The different locking/semaphore implementations all came to life on different systems. On System V Unix you had semget/semop, POSIX defined a different implementation with sem_init, sem_wait and sem_post. And flock originated in 4.2BSD, as far as I could find out.

Since they all gained a certain significance Linux supports them all now to make porting easy. Also, flock is a mutex (either locked or unlocked), but the sem* functions (both SysV and POSIX) are semaphores: they allow an application to grant several concurrent processes access, e.g. you could allow access to a resource to 4 processes simultaneous with semaphores. You can implement a mutex with semaphores but not the other way round. I remember that in the excellent "Advanced UNIX Programming" by Marc J. Rochkind he demonstrated how to transmit data between processes via semaphores (very inefficient, he did it just to prove it can be done). But I couldn't find anything reliable about efficiency.

I guess it's more like "Use what you want".

奢华的一滴泪 2024-09-23 14:06:31

一个潜在的显着差异可能是资源分配的公平性。我不知道 semget/semop 系列的实现细节,但我怀疑就调度而言,它通常是作为“传统”信号量实现的。一般来说,我认为释放的线程是在 FIFO 的基础上处理的(第一个等待信号量的线程首先被释放)。我认为文件锁定不会发生这种情况,因为我怀疑(再次只是猜测)处理不是在内核级别执行的。

我有现有代码来测试用于 IPC 目的的信号量,因此我比较了两种情况(一种使用 semop,一种使用 lockf)。我做了一个穷人的测试,只是运行到应用程序的实例。共享信号量用于同步启动。运行 semop 测试时,两个进程几乎同步完成了 300 万次循环。另一方面,lockf 循环则不太公平。一个进程通常会完成,而另一个进程只完成一半的循环。

semop 测试的循环如下所示。 semwaitsemsignal 函数只是 semop 调用的包装器。

   ct = myclock();
   for ( i = 0; i < loops; i++ )
      {
      ret = semwait( "test", semid, 0 );
      if ( ret < 0 ) { perror( "semwait" ); break; }

      if (( i & 0x7f ) == 0x7f )
         printf( "\r%d%%", (int)(i * 100.0 / loops ));

      ret = semsignal( semid, 0 );
      if ( ret < 0 ) { perror( "semsignal" ); break; }
      }
   printf( "\nsemop time: %d ms\n", myclock() - ct );

两种方法的总运行时间大致相同,尽管有时由于调度的不公平,lockf 版本实际上总体上更快。第一个进程完成后,另一个进程将获得约 150 万次迭代的无竞争访问权限,并且运行速度极快。

当无竞争运行时(单个进程获取和释放锁),semop 版本速度更快。 100 万次迭代大约需要 2 秒,而 lockf 版本大约需要 3 秒。

这是在以下版本上运行的:

[]$ uname -r
2.6.11-1.1369_FC4smp

A potentially significant difference might be the fairness of the resource distribution. I don't know the details of the implementation of the semget/semop family, but I suspect that it is typically implemented as a "traditional" semaphore as far as scheduling goes. Generally, I believe the released threads are handled on a FIFO basis (first one waiting for the semaphore is released first). I don't think this would happen with file locking since I suspect (again just guessing) that the handling is not performed at the kernel level.

I had existing code sitting around to test semaphores for IPC purposes, and so I compared the two situations (one using semop and one using lockf). I did a poor man's test and just ran to instances of the application. The shared semaphore was used to sync the start. When running the semop test, both processes finished 3 million loops almost in sync. The lockf loop, on the other hand, was not nearly as fair. One process would typically finish while the other one had only completed half the loops.

The loop for the semop test looked like the following. The semwait and semsignal functions are just wrappers for the semop calls.

   ct = myclock();
   for ( i = 0; i < loops; i++ )
      {
      ret = semwait( "test", semid, 0 );
      if ( ret < 0 ) { perror( "semwait" ); break; }

      if (( i & 0x7f ) == 0x7f )
         printf( "\r%d%%", (int)(i * 100.0 / loops ));

      ret = semsignal( semid, 0 );
      if ( ret < 0 ) { perror( "semsignal" ); break; }
      }
   printf( "\nsemop time: %d ms\n", myclock() - ct );

The total run time for both methods was about the same, although the lockf version actually was faster overall sometimes because of the unfairness of the scheduling. Once the first process finished, the other process would have uncontested access for about 1.5 million iterations and run extremely fast.

When running uncontested (single process obtaining and releasing the locks), the semop version was faster. It took about 2 seconds for 1 million iterations while the lockf version took about 3 seconds.

This was run on the following version:

[]$ uname -r
2.6.11-1.1369_FC4smp
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文