我正在考虑使用Posix健壮的互斥锁来保护不同进程之间的共享资源(在Linux上)。但是,在不同情况下对安全性存在一些疑问。我有以下问题:
是否在内核或用户代码中实现了强大的互斥锁?
如果是后者,则在调用pthread_mutex_lock或pthread_mutex_unlock时以及共享的pthread_mutex数据结构正在更新时,如果进程崩溃导致崩溃怎么办?
我了解,如果一个进程锁定了互斥锁和死亡,则另一个进程中的线程将被唤醒并返回EOWNERDEAD。但是,如果进程(在不太可能的情况下)恰好在更新pthread_mutex数据结构(在共享内存中)时死掉了,将会发生什么情况?在这种情况下,互斥体会损坏吗?如果调用pthread_mutex函数,映射到同一共享内存的另一个进程会发生什么情况?在这种情况下,仍然可以恢复互斥锁吗?
此问题适用于具有PTHREAD_PROCESS_SHARED属性的任何pthread对象。从不同进程对同一对象同时调用pthread_mutex_lock,pthread_mutex_unlock,pthread_cond_signal等函数是否安全?它们在不同进程之间是线程安全的吗?
从pthread的手册页中:
Over time, two threading implementations have been provided by the
GNU C library on Linux:
LinuxThreads
This is the original Pthreads implementation. Since glibc
2.4, this implementation is no longer supported.
NPTL (Native POSIX Threads Library)
This is the modern Pthreads implementation. By comparison
with LinuxThreads, NPTL provides closer conformance to the
requirements of the POSIX.1 specification and better
performance when creating large numbers of threads. NPTL is
available since glibc 2.3.2, and requires features that are
present in the Linux 2.6 kernel.
Both of these are so-called 1:1 implementations, meaning that each
thread maps to a kernel scheduling entity. Both threading
implementations employ the Linux clone(2) system call. In NPTL,
thread synchronization primitives (mutexes, thread joining, and so
on) are implemented using the Linux futex(2) system call.
来自man futex(7):
In its bare form, a futex is an aligned integer which is touched only
by atomic assembler instructions. Processes can share this integer
using mmap(2), via shared memory segments or because they share
memory space, in which case the application is commonly called
multithreaded.
在此处找到其他备注:
(以防万一您想知道它们如何在共享内存中工作:Futex会根据其物理地址进行加密)
总而言之,Linux决定在其“本机”futex
原语之上实现pthread,而这些原语确实存在于用户进程地址空间中。对于共享同步原语,这将是共享内存,并且在一个进程终止后,其他进程仍将能够看到它。
在流程终止的情况下会发生什么?Ingo Molnar就此发表了一篇名为《Robust Futexes》的文章。相关报价:
健壮的飞鹰
但是有一种可能的竞赛:由于在glibc获取了futex之后完成了从列表中添加和删除列表的工作,因此线程(或进程)在那里死了,留下了一些指令窗口,使futex挂起了。为了防止这种情况的发生,用户空间(glibc)还维护了一个简单的每个线程的“ list_op_pending”字段,以允许内核在线程在获取锁之后死掉之前(但可能在将自身添加到列表中之前)清理掉。Glibc会在尝试获取futex之前设置此list_op_pending字段,并在list-add(或list-remove)完成后清除它
这为您带来了其他平台的无限开放空间。可以肯定地说,至少Linux实施已非常小心地满足了我们对健壮性的常识性期望。
看到其他操作系统通常首先使用基于内核的同步原语,我认为它们的实现自然更健壮。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句