将读写锁放到共享内存,实现进程之间对于同一文件的读写操作

82 篇文章 2 订阅
15 篇文章 0 订阅
该博客介绍了如何利用读写锁在多个进程中实现对共享文件的安全读写操作。首先,通过创建共享内存并初始化读写锁属性,确保锁可以在不同进程间共享。接着,定义读写函数分别进行文件读取和追加写入。在父子进程中,通过加锁和解锁来协调读写操作,避免数据冲突。最后,设计了一个销毁函数用于清理资源。测试部分展示了读写函数在fork后的两个进程中如何交替执行。
摘要由CSDN通过智能技术生成

思路

  • 将读写锁和读写锁的属性以及一个用于存储共享内存的地址的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;
}

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值