1. 程式人生 > >POSIX共享記憶體-------共享計數器

POSIX共享記憶體-------共享計數器

問題描述

父子程序共享一個計數器,每次父程序或子程序可以給計數器加一。

簡單實現

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<sys/wait.h>
using namespace std;
struct Shared{
       int count;
};

Shared shared;
int main(){
    pid_t pid;
    shared.count = 0;

    if((pid = fork()) ==0){
       for
(int x=0;x<10;x++){ printf("Child change count = %d\n",shared.count++); } return 0; } for(int x=0;x<10;x++){ printf("Parent change count = %d\n",shared.count++); } waitpid(pid,NULL,0); }

執行結果

這裡寫圖片描述

結果在我們的意料之中,計數器並沒有實現共享,父子程序各自擁有一個計數器。

使用共享記憶體(mmap函式)

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<semaphore.h>
using namespace std;
struct Shared{
       int count;
};

const char
* file = "./temp"; //合法的檔案路徑 Shared* shared; int main(){ pid_t pid; int fd; fd = open(file,O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); //開啟共享檔案 ftruncate(fd,sizeof(struct Shared)); //修改檔案大小為Shared結構體的大小 shared =(Shared * ) mmap(NULL,sizeof(struct Shared),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); shared->count = 0; if((pid = fork()) ==0){ for(int x=0;x<10;x++){ printf("Child change count = %d\n",shared->count++); } return 0; //否則會執行2個for迴圈 } for(int x=0;x<10;x++){ printf("Parent change count = %d\n",shared->count++); } waitpid(pid,NULL,0); close(fd); }

執行結果

這裡寫圖片描述

我們先使用open函式開啟一個共享的檔案,然後用mmap函式將共享檔案對映到父子程序的程序空間上,從而實現共享計數器。從上面的結果中可以看出,父子程序間實現了共享計數器,但是沒有實現計數的功能,因為父子程序之間存在競爭條件,需要一定的同步機制來保證父子程序間的同步。

使用同步機制(訊號量)

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<semaphore.h>
using namespace std;
struct Shared{ 
       int count;
       sem_t  mutex;
};

const char* file = "./temp"; //合法的檔案路徑
Shared* shared;

int main(){
    pid_t pid;
    int fd;

    fd  = open(file,O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    ftruncate(fd,sizeof(struct Shared));
    shared =(Shared * ) mmap(NULL,sizeof(struct Shared),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
    shared->count = 0;
    sem_init(&shared->mutex,1, 1); //初始化訊號量,第一個1表示訊號量可以在程序共享

    if((pid = fork()) ==0){
       for(int x=0;x<10;x++){
           sem_wait(&shared->mutex); //mutex--
              printf("Child change count = %d\n",shared->count++); 
           sem_post(&shared->mutex); //mutex++
        }
       return 0; //否則會執行2個for迴圈
     }

     for(int x=0;x<10;x++){
         sem_wait(&shared->mutex); //mutex--
             printf("Parent change count = %d\n",shared->count++); 
         sem_post(&shared->mutex); //mutex++
      }
    waitpid(pid,NULL,0);
    sem_destroy(&shared->mutex);
    close(fd);
}

執行結果

這裡寫圖片描述

我們通過一個訊號量mutex來實現父子程序之間的互斥,從上面的結果可以看出,成功地實現了計數器的功能。