Chuẩn POSIX có cho phép có tên là khối bộ nhớ dùng chung để chứa biến mutex và biến điều kiện không?Biến điều kiện trong bộ nhớ dùng chung - đây có phải là mã POSIX-conformant không?
Chúng tôi đã cố gắng sử dụng biến mutex và điều kiện để đồng bộ hóa quyền truy cập vào bộ nhớ được chia sẻ có tên theo hai quy trình trên LynuxWorks LynxOS-SE system (tuân thủ POSIX).
Một khối bộ nhớ chia sẻ được gọi là "/sync"
và chứa biến mutex và điều kiện, biến còn lại là "/data"
và chứa dữ liệu thực tế mà chúng tôi đang đồng bộ hóa quyền truy cập.
Chúng tôi đang chứng kiến những thất bại từ pthread_cond_signal()
nếu cả hai quá trình không thực hiện các cuộc gọi trong mmap()
chính xác theo thứ tự, hoặc nếu một quá trình mmaps trong một số phần khác của bộ nhớ chia sẻ trước khi nó mmaps bộ nhớ "/sync"
.
mã ví dụ này là về như ngắn như tôi có thể làm cho nó:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/file.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <iostream>
#include <string>
using namespace std;
static const string shm_name_sync("/sync");
static const string shm_name_data("/data");
struct shared_memory_sync
{
pthread_mutex_t mutex;
pthread_cond_t condition;
};
struct shared_memory_data
{
int a;
int b;
};
//Create 2 shared memory objects
// - sync contains 2 shared synchronisation objects (mutex and condition)
// - data not important
void create()
{
// Create and map 'sync' shared memory
int fd_sync = shm_open(shm_name_sync.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
ftruncate(fd_sync, sizeof(shared_memory_sync));
void* addr_sync = mmap(0, sizeof(shared_memory_sync), PROT_READ|PROT_WRITE, MAP_SHARED, fd_sync, 0);
shared_memory_sync* p_sync = static_cast<shared_memory_sync*> (addr_sync);
// init the cond and mutex
pthread_condattr_t cond_attr;
pthread_condattr_init(&cond_attr);
pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&(p_sync->condition), &cond_attr);
pthread_condattr_destroy(&cond_attr);
pthread_mutexattr_t m_attr;
pthread_mutexattr_init(&m_attr);
pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&(p_sync->mutex), &m_attr);
pthread_mutexattr_destroy(&m_attr);
// Create the 'data' shared memory
int fd_data = shm_open(shm_name_data.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
ftruncate(fd_data, sizeof(shared_memory_data));
void* addr_data = mmap(0, sizeof(shared_memory_data), PROT_READ|PROT_WRITE, MAP_SHARED, fd_data, 0);
shared_memory_data* p_data = static_cast<shared_memory_data*> (addr_data);
// Run the second process while it sleeps here.
sleep(10);
int res = pthread_cond_signal(&(p_sync->condition));
assert(res==0); // <--- !!!THIS ASSERT WILL FAIL ON LYNXOS!!!
munmap(addr_sync, sizeof(shared_memory_sync));
shm_unlink(shm_name_sync.c_str());
munmap(addr_data, sizeof(shared_memory_data));
shm_unlink(shm_name_data.c_str());
}
//Open the same 2 shared memory objects but in reverse order
// - data
// - sync
void open()
{
sleep(2);
int fd_data = shm_open(shm_name_data.c_str(), O_RDWR, S_IRUSR|S_IWUSR);
void* addr_data = mmap(0, sizeof(shared_memory_data), PROT_READ|PROT_WRITE, MAP_SHARED, fd_data, 0);
shared_memory_data* p_data = static_cast<shared_memory_data*> (addr_data);
int fd_sync = shm_open(shm_name_sync.c_str(), O_RDWR, S_IRUSR|S_IWUSR);
void* addr_sync = mmap(0, sizeof(shared_memory_sync), PROT_READ|PROT_WRITE, MAP_SHARED, fd_sync, 0);
shared_memory_sync* p_sync = static_cast<shared_memory_sync*> (addr_sync);
// Wait on the condvar
pthread_mutex_lock(&(p_sync->mutex));
pthread_cond_wait(&(p_sync->condition), &(p_sync->mutex));
pthread_mutex_unlock(&(p_sync->mutex));
munmap(addr_sync, sizeof(shared_memory_sync));
munmap(addr_data, sizeof(shared_memory_data));
}
int main(int argc, char** argv)
{
if(argc>1)
{
open();
}
else
{
create();
}
return (0);
}
Chạy chương trình này không có args, sau đó một bản sao với args, và là người đầu tiên sẽ thất bại tại assert kiểm tra pthread_cond_signal()
. Nhưng thay đổi thứ tự của các open()
chức năng để mmap()
các "/sync
"bộ nhớ trước khi "/data"
và nó sẽ tất cả làm việc tốt.
Điều này có vẻ giống như một lỗi lớn trong LynxOS với tôi, nhưng LynuxWorks tuyên bố rằng việc sử dụng mutex và biến điều kiện trong vòng bộ nhớ được chia sẻ theo cách này không thuộc phạm vi điều chỉnh của tiêu chuẩn POSIX, do đó, họ không quan tâm đến tiêu chuẩn POSIX, vì vậy họ không quan tâm đến các tiêu chuẩn POSIX, vì vậy họ không quan tâm đến việc tuân theo quy định của POSIX, vì vậy họ không quan tâm đến việc tuân thủ POSIX?
Chỉnh sửa: chúng tôi biết rằng PTHREAD_PROCESS_SHARED
là POSIX và được LynxOS hỗ trợ. Khu vực tranh chấp là liệu mutexes và semaphores có thể được sử dụng trong bộ nhớ chia sẻ được đặt tên (như chúng ta đã làm) hay không.
Tôi tự hỏi làm thế nào họ tưởng tượng chính xác việc chia sẻ cùng một biến bằng cách sử dụng PTHREAD_PROCESS_SHARED giữa hai quy trình (rõ ràng ngụ ý * một số cơ chế chia sẻ biến giữa các quá trình được cho là tồn tại.) Và AFAIK không có tiêu chuẩn cấm đặt mutexes và semaphores ở bất cứ nơi nào bạn muốn , vì vậy "không được bảo hiểm" có nghĩa là "nên hành xử như bình thường." –