思路
- 将读写锁和读写锁的属性以及一个用于存储共享内存的地址的int型变量三者封装成一个struct结构
- 将这个结构体放到共享内存中,以及将读写锁的属性设置成全局性质,然后使用这个属性初始化锁,以及将锁的地址关联到结构体的内存地址这个变量
- 定义一个销毁函数,用于退出进程的时候,将内存空间销毁,以及删除对应的变量
- 定义读写函数,读函数读取文件的内容,输出文件的内容;写函数,以追加的方式,向指定文件中写入数据
- 测试:使用fork创建父子两个进程,定义一个for循环,循环5次之后,退出循环并且执行销毁函数。
- 在使用读写函数之前需要对于锁执行相关的操作,比如加读锁,加写锁,以及执行完读写文件函数之后去掉锁
代码
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cassert>
#include <pthread.h>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstring>/*** 返回一片共享内存标识符,用于后续获取该共享内存,以及销毁该共享内存*/
namespace hhh{namespace hhh{class mutex_function{public:mutex_function() = default;// 定义进程锁结构体typedef struct mutex_struct{pthread_rwlock_t lock;pthread_rwlockattr_t lock_attr;int memory_addr;}mutex_struct_t;int create_share_memory_id(const int index_of_key,size_t md5){const char* file_path = "./";key_t id = ftok(file_path,md5);const int share_memory_id = shmget(id,md5,IPC_CREAT | 0666);if (share_memory_id == -1){std::cout << "share_memory_id error!\n" << std::endl;exit(EXIT_FAILURE);}else{return share_memory_id;}}// 初始化进程锁结构体int init_mutex_struct(mutex_struct_t* mutex_ptr){pthread_rwlockattr_init(&(mutex_ptr->lock_attr));pthread_rwlockattr_setpshared(&(mutex_ptr->lock_attr),PTHREAD_PROCESS_SHARED);pthread_rwlock_init(&(mutex_ptr->lock),&(mutex_ptr->lock_attr));return 0;}// 在共享内存上定义进程锁结构体并且返回其位置mutex_struct_t* mutex_struct_addr(const int index){int memory_id = create_share_memory_id(index,sizeof (mutex_struct_t));mutex_struct_t * share_ptr = (mutex_struct_t* )shmat(memory_id, 0, 0);if (share_ptr == (void *)-1){std::cout << "share_ptr error!\n" << std::endl;exit(EXIT_FAILURE);}share_ptr->memory_addr = memory_id;assert(init_mutex_struct(share_ptr)== 0);return share_ptr;}// 销毁进程锁结构体,利用其memory_addr变量索引到其占用的共享内存并销毁const int destroy_mutex_memory(mutex_struct_t * mutex_struct){pthread_rwlock_destroy(&(mutex_struct->lock));pthread_rwlockattr_destroy(&(mutex_struct->lock_attr));assert(shmctl(mutex_struct->memory_addr,IPC_RMID, nullptr) == 0);return 0;}public:mutex_struct_t* mutex_struct_ptr;};}//namespace hhh
}//namespace hhh//read file
void read_file(const std::string file_name,int id){std::ifstream fp(file_name,std::ios::binary);std::stringstream ss;ss << fp.rdbuf();std::cout << "线程"<< id << "抢占了资源,输出:" << ss.str() << std::endl;sleep(3);std::cout << "线程"<< id << "释放了资源...\n" << std::endl;fp.close();
}
//write file
void write_file(const char *file_name,char *str,int id){FILE *fd = fopen(file_name,"a+");if (fd == nullptr){printf("fd is nullptr and open file fail\n");} else{std::cout <<"线程"<< id << "抢占了资源" << std::endl;fwrite(str,strlen(str),1,fd);char *next = "\0";fwrite(next,strlen(next),1,fd);sleep(5);std::cout << "线程"<< id << "释放了资源...\n" << std::endl;}fclose(fd);
}
int main(){std::string file_name = "/home/gsc/Projects/1.txt";char * str1 = "progress 1";// 创建自定义进程锁hsm::hal::mutex_function mutex_function_object;mutex_function_object.mutex_struct_ptr = mutex_function_object.mutex_struct_addr(111);// 创建新进程int id = fork();assert(id >= 0);// 设置循环次数for (int i = 0; i < 5; ++i) {if (id > 0) { // 父进程// 读锁
// pthread_rwlock_rdlock(&(mutex_function_object.mutex_struct_ptr->lock));
// read_file(file_name,getpid());
// pthread_rwlock_unlock(&(mutex_function_object.mutex_struct_ptr->lock));// 写锁pthread_rwlock_wrlock(&(mutex_function_object.mutex_struct_ptr->lock));write_file(file_name.c_str(),str1,getpid());pthread_rwlock_unlock(&(mutex_function_object.mutex_struct_ptr->lock));} else { // 子进程// 读锁
// pthread_rwlock_rdlock(&(mutex_function_object.mutex_struct_ptr->lock));
// read_file(file_name,getpid());
// pthread_rwlock_unlock(&(mutex_function_object.mutex_struct_ptr->lock));// 写锁pthread_rwlock_wrlock(&(mutex_function_object.mutex_struct_ptr->lock));write_file(file_name.c_str(),str1,getpid());pthread_rwlock_unlock(&(mutex_function_object.mutex_struct_ptr->lock));}}// 等待循环完毕sleep(1);// 循环完毕,销毁进程锁,释放申请的共享内存if (id > 0) { // 父进程mutex_function_object.destroy_mutex_memory((mutex_function_object.mutex_struct_ptr));mutex_function_object.mutex_struct_ptr = nullptr;printf("父进程释放资源完毕\n");}return 0;
}