共享內存跨進程通訊

經過共享內存通訊是最快的,不過既然是共享資源,那麼就必需要有同步機制。segmentfault

建立共享內存有兩種方式shm和mmap的方式。app

  1. mmap是在磁盤上創建一個文件,每一個進程地址空間中開闢出一塊空間進行映射。
  2. 而對於shm而言,shm每一個進程最終會映射到同一塊物理內存。shm保存在物理內存,這樣讀寫的速度要比磁盤要快,可是存儲量不是特別大。
  3. 相對於shm來講,mmap更加簡單,調用更加方便,因此這也是你們都喜歡用的緣由。
  4. 另外mmap有一個好處是當機器重啓,由於mmap把文件保存在磁盤上,這個文件還保存了操做系統同步的映像,因此mmap不會丟失,可是shmget就會丟失。

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 }
  1. F_SETLK:獲取(l_type爲F_RDLCK或F_WRLCK)或釋放由lock指向flock結構所描述的鎖,若是沒法獲取鎖時,該函數會當即返回一個EACCESS或EAGAIN錯誤,而不會阻塞。
  2. F_SETLKW:F_SETLKW和F_SETLK的區別是,沒法設置鎖的時候,調用線程會阻塞到該鎖可以受權位置。
  3. F_GETLK:F_GETLK主要用來檢測是否有某個已存在鎖會妨礙將新鎖授予調用進程,若是沒有這樣的鎖,lock所指向的flock結構的l_type成員就會被置成F_UNLCK,不然已存在的鎖的信息將會寫入lock所指向的flock結構中

https://blog.csdn.net/anonymalias/article/details/9197641

相關文章
相關標籤/搜索