在linux系统下,使用mmap技术,实现两个进程访问同一个内存区域的操作,并增加锁保护

写入进程

首先,编写一个创建共享内存文件并写入数据的进程代码,添加信号量来保护共享内存区域;当两个进程需要同时写入共享内存区域时,使用锁机制来避免竞争条件和数据不一致是非常重要的。在Linux系统中,可以使用POSIX信号量(semaphore)来实现进程间的同步;
POSIX命名信号量在Linux系统中通过内核管理,位于内存中的 /dev/shm/ 虚拟文件系统内,对系统的开销非常小,务必在程序结束时正确清理信号量。

// writer.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>

#define SHARED_MEMORY_NAME "/my_shared_memory"
#define SEMAPHORE_NAME "/my_semaphore"
#define SHARED_MEMORY_SIZE 4096

int main() {
    // 创建并初始化信号量
    sem_t *sem = sem_open(SEMAPHORE_NAME, O_CREAT, 0666, 1);
    if (sem == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }

    // 创建共享内存对象
    int fd = shm_open(SHARED_MEMORY_NAME, O_CREAT | O_RDWR, 0666);
    if (fd == -1) {
        perror("shm_open");
        exit(EXIT_FAILURE);
    }

    // 设置共享内存大小
    if (ftruncate(fd, SHARED_MEMORY_SIZE) == -1) {
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }

    // 映射共享内存
    void *shared_mem = mmap(NULL, SHARED_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (shared_mem == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    // 写入共享内存前加锁
    sem_wait(sem);

    const char *message = "Hello from writer process!";
    memcpy(shared_mem, message, strlen(message) + 1);
    printf("Writer wrote: %s\n", message);

    // 解锁
    sem_post(sem);

    // Cleanup
    munmap(shared_mem, SHARED_MEMORY_SIZE);
    close(fd);
    sem_close(sem);

    return 0;
}

读取进程

接着,编写一个读取共享内存文件的进程代码,添加信号量来保护共享内存区域。

// reader.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>

#define SHARED_MEMORY_NAME "/my_shared_memory"
#define SEMAPHORE_NAME "/my_semaphore"
#define SHARED_MEMORY_SIZE 4096

int main() {
    // 打开信号量
    sem_t *sem = sem_open(SEMAPHORE_NAME, 0);
    if (sem == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }

    // 打开共享内存对象
    int fd = shm_open(SHARED_MEMORY_NAME, O_RDONLY, 0666);
    if (fd == -1) {
        perror("shm_open");
        exit(EXIT_FAILURE);
    }

    // 映射共享内存
    void *shared_mem = mmap(NULL, SHARED_MEMORY_SIZE, PROT_READ, MAP_SHARED, fd, 0);
    if (shared_mem == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    // 读取共享内存前加锁
    sem_wait(sem);

    printf("Reader read: %s\n", (char *)shared_mem);

    // 解锁
    sem_post(sem);

    // Cleanup
    munmap(shared_mem, SHARED_MEMORY_SIZE);
    close(fd);
    sem_close(sem);
	// 运行完成之后,清理共享内存和信号量
	shm_unlink("/my_shared_memory");
	sem_unlink("/my_semaphore");
    return 0;
}

编译和运行

将这两个文件分别保存为 writer.c 和 reader.c,然后编译并运行它们。

gcc -o writer writer.c -lrt -pthread
gcc -o reader reader.c -lrt -pthread

./writer
./reader
  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你的问题。以下是基于 mmap 系统实现简单的双向聊天程序的 C 语言代码: ```c // chat.c #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <string.h> #define SHM_SIZE 1024 int main() { int shm_fd; void *ptr; pid_t pid; shm_fd = shm_open("/chat", O_CREAT | O_RDWR, 0666); if (shm_fd == -1) { perror("shm_open"); exit(1); } ftruncate(shm_fd, SHM_SIZE); ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (ptr == MAP_FAILED) { perror("mmap"); exit(1); } pid = fork(); if (pid == 0) { // Child process char *msg = "Hello from child!\n"; while (1) { fgets(ptr, SHM_SIZE, stdin); printf("Child: %s\n", (char *) ptr); strncpy(ptr, msg, strlen(msg) + 1); } } else { // Parent process char *msg = "Hello from parent!\n"; while (1) { strncpy(ptr, msg, strlen(msg) + 1); printf("Parent: %s\n", (char *) ptr); fgets(ptr, SHM_SIZE, stdin); } wait(NULL); } munmap(ptr, SHM_SIZE); shm_unlink("/chat"); return 0; } ``` 这是一个简单的通过共享内存进行通信的程序。程序首先创建了一个大小为 1024 字节的共享内存区域,并将其映射到进程的虚拟地址空间中。然后,程序调用 `fork()` 函数创建了一个子进程,并在子进程中不断读取从父进程中发送过来的消息,并向父进程中发送回复消息;在父进程中相反,父进程不断读取从子进程中发送过来的消息,并向子进程中发送回复消息。程序最后释放了共享内存区域,并删除了命名的共享内存对象。 这个程序仅仅是一个示例,仍然存在许多问题,例如缺少错误处理、没有使用信号量进行处理等。实际上,在生产环境中,我们不应该使用这种简单的共享内存通信方式,而应该使用更为复杂的进程间通信方式,例如消息队列、信号量等。 希望这个答案能对你有所帮助!如果你有更多的问题,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值