POSIX共享記憶體-------共享計數器
阿新 • • 發佈:2019-01-30
問題描述
父子程序共享一個計數器,每次父程序或子程序可以給計數器加一。
簡單實現
#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來實現父子程序之間的互斥,從上面的結果可以看出,成功地實現了計數器的功能。