在使用时,pthreads进程共享内存:docker run –ipc –pid
我正在C ++开发一个多处理的应用程序使用PTHREAD_PROCESS_SHARED
pthread_rwlock
pthreads
实现IPC通过命名共享内存。 对于共享内存访问,我使用shm_open
和mmap
:
auto fd = shm_open(name.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); ftruncate(fd, size); addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
rwlocks
在mmap
-ed内存中被初始化,使用:
pthread_rwlockattr_t attrrwlock; pthread_rwlockattr_init(&attrrwlock); pthread_rwlockattr_setpshared(&attrrwlock, PTHREAD_PROCESS_SHARED); pthread_rwlockattr_setkind_np(&attrrwlock, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); class Shm{ .... pthread_rwlock_t rwLock; ... } auto shm = Shm(addr); pthread_rwlock_init(&(shm.rwLock), &attrrwlock);
这在主机环境中工作正常:我可以启动例如一个生产者和多个消费者/工作者进程使用相同的IPC共享内存文件,并通过进程共享pthread_rwlocks同步读/写共享内存:
int errc = pthread_rwlock_timedrdlock(&rwLock, &abstime); errc = pthread_rwlock_timedwrlock(&rwLock, &abstime); errc = pthread_rwlock_unlock(&rwLock);
因为我们在Docker容器中运行这个应用程序的实验,所以我需要启动第一个容器中的消费者/工作者进程以及其他容器中的顺序多个生产者进程。 为了使IPC工作,我只需在--ipc=container:<nome/id>
docker run
的调用中添加--ipc=container:<nome/id>
即可。 现在所有的容器都使用了相同的共享内存。 一见钟情,locking似乎是正确的。 但偶尔一次, pthread_rwlock_timedrdlock
返回EDEADLK
错误代码,这是我以前没有遇到。 此外,经过一些更多的testing后,我得到了一些错误,看起来像并发的读/写错误。
首先我find了--cap-add
docker run
的参数--cap-add
。 Docker文档提到了mmap()
和shmctl()
作为--cap-add
用例的--cap-add
:
IPC_LOCK Lock memory (mlock(2), mlockall(2), mmap(2), shmctl(2)).
但是,将--cap-add=IPC_LOCK
到我的--cap-add=IPC_LOCK
docker run
调用中并不能阻止pthread_rwlock_timedrdlock
返回EDEADLK
。
然后,我读了docker中的PID-1-Problem,所以我想知道,pthread_rwlocks是否可能依赖于PID进行locking,当同一个PID试图lockingrwlock两次而不解锁时可能会感到困惑。 然后我find了--pid
docker run
的--pid
参数,其工作方式与--ipc
相似。
现在,我使用:
docker run -i -t -d --name=workers docker run -i -t --ipc=container:workers --pid=container:workers --name=producerN
这似乎现在正常工作。
现在是否有人有关于docker IPC的更多细节,以及是否可以使用具有相同PID的进程共享pthread_rwlock
?
什么是IPC_LOCK
? pthread_rwlock
需要吗?
主机:Docker版本17.03.0-ce Ubuntu 16.10 Linux 4.8.0-41
Docker容器:Ubuntu 16.04