经过共享内存通讯是最快的,不过既然是共享资源,那么就必需要有同步机制。segmentfault
建立共享内存有两种方式shm和mmap的方式。app
shm的建立要确保原子性的话,能够经过重命名来作。函数
http://www.javashuo.com/article/p-ktybynmz-km.htmlspa
1 char* SharedMemory::CreateMapping(const std::string file_name, unsigned mapping_size, bool &is_new) { 2 char* mapping = (char*)MAP_FAILED; 3 int fd = -1; 4 fd = open(file_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0666); // 同步O_EXCL 5 if (fd == -1) { 6 fd = open(file_name.c_str(), O_RDWR, 0666); 7 if (fd < 0) { 8 return mapping; 9 } 10 } 11 12 struct stat file_stat; 13 if(fstat(fd, &file_stat)== -1) { 14 close(fd); 15 return mapping; 16 } 17 int file_size = file_stat.st_size; 18 is_new = false; 19 if (file_size == 0) { 20 file_size = mapping_size; 21 ftruncate(fd, file_size); 22 is_new = true; 23 } 24 mapping = (char*)mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 25 if (is_new) { 26 memset(mapping, 0, sizeof(char) * file_size); 27 } 28 close(fd); 29 return mapping; 30 }
这里用O_CREAT | O_EXCL来确保只建立一次文件,若是建立失败就以rw的方式来打开。操作系统
跨进程的同步机制,根据APUE 15.9节提到的,能够有三种方式,带undo的信号量、记录锁、互斥量。pthread带的跨进程互斥量须要高版本支持。.net
1 bool SharedMemory::Init() { 2 bool is_new = false; 3 mutex_ = (pthread_mutex_t *)CreateMapping(file_name_ + ".lock", sizeof(pthread_mutex_t), is_new); 4 if (mutex_ == MAP_FAILED) { 5 return false; 6 } 7 if (is_new) { 8 InitLock(); 9 } 10 is_init_ = true; 11 return true; 12 } 13 14 void SharedMemory::InitLock() { 15 pthread_mutexattr_t attr; 16 pthread_mutexattr_init(&attr); //~necessary, or weird EINVAL error occurs when operating on the mutex 17 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 18 pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); 19 pthread_mutex_init(mutex_, &attr); 20 } 21 22 void SharedMemory::Lock() { 23 if (!is_init_) { 24 return; 25 } 26 while (EOWNERDEAD == pthread_mutex_lock(mutex_)) { 27 pthread_mutex_consistent(mutex_); 28 pthread_mutex_unlock(mutex_); 29 } 30 } 31 32 void SharedMemory::Unlock() { 33 if (!is_init_) { 34 return; 35 } 36 pthread_mutex_unlock(mutex_); 37 }
pthread_mutex_consistent这个函数有版本限制。线程
若是持有 mutex 的线程退出,另一个线程在 pthread_mutex_lock 的时候会返回 EOWNERDEAD。这时候你须要调用 pthread_mutex_consistent 函数来清除这种状态,不然后果自负。code
http://www.javashuo.com/article/p-ktybynmz-km.htmlblog
pthread_mutexattr_setpshared配合PTHREAD_PROCESS_SHARED能够建立跨进程的mutex,可是必需保证mutex所在的内存区域能够被每一个进程访问,也就是说必需被建立在进程间共享的内存区域中,好比mmap建立的共享内存。进程
https://segmentfault.com/q/1010000000628904
记录锁的功能:当一个进程正在读或修改文件的某个部分是,它能够阻止其余进程修改同一文件区。
记录锁是更经常使用的方式。由于它没有版本限制,进程退出时会自动释放锁。
1 void SharedMemory::InitLock(short type) { 2 if (lock_fd_ < 0) { 3 return; 4 } 5 struct flock lock; 6 lock.l_type = type; 7 lock.l_whence = SEEK_SET; 8 lock.l_start = 0; 9 lock.l_len = 0; 10 int ret = fcntl(lock_fd_, F_SETLKW, &lock); 11 //printf("InitLock %d \n", ret); 12 } 13 14 void SharedMemory::LockWrite() { 15 if (!is_init_) { 16 return; 17 } 18 19 InitLock(F_WRLCK); 20 } 21 22 void SharedMemory::LockRead() { 23 if (!is_init_) { 24 return; 25 } 26 27 InitLock(F_RDLCK); 28 } 29 30 void SharedMemory::Unlock() { 31 if (!is_init_) { 32 return; 33 } 34 InitLock(F_UNLCK); 35 }