共享内存相关知识点
目录
一、把共享内存中的数据读出来后,共享内存中还有这个数据吗?
二、同一时间只允许一个进程访问共享内存吗?
三、pthread_mutex_destroy和 munmap函数的使用介绍
1. pthread_mutex_destroy
2. munmap
一、把共享内存中的数据读出来后,共享内存中还有这个数据吗?
共享内存是什么?他是一种进程间的通信方法,允许多个进程访问同一块区域。当一个进程将数据写入共享内存后,其他进程可以读取这些数据。需要特别注意的是,共享内存中的内容不会因为读取而被删除或改变。
原理解析:
1、数据存储
当一个进程将数据写入共享内存------>数据存储子啊共享内存区域中------->直至被显示修改或释放。
2、读取数据:
另一个进程读取共享内存数据------>只是读取存储在那里的值,并不会影响原有数据----->内存中仍保留元数据,其他进程仍可以访问。
3、修改数据:
如某个进程------>对共享内存中数据进行写操作(例如,更新或覆盖数据)--->共享内存中实质数据被修改。
实际上,只有在数据在被合法修改或共享内存被删除(例如,调用shmctl函数)时,数据才会消失。
例子:
假设有两个进程 Process A
和 Process B
,并且它们都使用同一块共享内存来读取和写入数据。
- Process A 写入数据到共享内存。
- Process B 读取共享内存中的数据。
在这个过程中:
- 数据读取:
Process B
读取数据后,共享内存中的数据依然存在。 - 数据修改:如果
Process A
之后在共享内存中修改了数据,Process B
读取时将会看到更新后的数据。
注意事项
- 同步:由于多个进程可以同时访问共享内存---------->因此在访问共享内存时需要注意同步问题,以避免数据竞争------->通常通过信号量、互斥锁等机制实现。
- 内存管理:共享内存通常在不需要时------->通过特定的系统调用(如shmdt何shmctl)来卸载和释放,以防止内存泄漏。
简言之,读共享内存中的数据并不会改变或删除者共享内存中的数据,直到明确的写操作或释放这个共享内存。
那我们来解决一下进程竞争
二、同一时间只允许一个进程访问共享内存吗?
在使用共享内存进行进程间通信时,确实需要考虑到多个进程可能会同时访问同一块共享内存的问题。为了确保数据的一致性和完整性,通常需要使用同步机制来控制对共享内存的访问。以下是一些关键点:
1、同步机制
由于共享内存允许多个进程同时访问,若没有适当的同步机制,可能会导致数据竞争(data race)和不一致的状态。为了解决这个问题,可以使用以下几种同步机制:
-
互斥锁(Mutex):互斥锁可以确保同一时间只有一个进程对共享内存的访问。其他进程在尝试访问时被阻塞,直到持有锁的进程释放锁。
-
信号量(Semaphore):信号量是一种更为灵活的同步机制,可以用于控制多个进程对共享内存资源的访问。可以使用二进制信号量(类似于互斥锁)来确保互斥访问,或使用计数信号量来允许一定数量的进程同时访问。
-
读写锁(Read-Write Lock):允许多个进程同时读取共享内存,但在写入时会阻塞其他进程的读取或写入。这在读操作远多于写操作的场景下特别有效。
2、访问控制
在设计共享内存的使用时,通常会遵循以下原则:
-
初始化同步机制:在进程访问共享内存之前,必须先初始化相应的同步机制。
-
获取锁:在访问共享内存之前,进程应获取锁(或信号量),以防止其他进程同时访问。
-
释放锁:访问完成后,进程应释放锁,以便允许其他进程访问共享内存。
3、示例代码
以下是一个简单的示例,展示如何使用互斥锁来控制对共享内存的访问:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#define SHM_SIZE 1024
// 共享内存和互斥锁
char *shared_memory;
pthread_mutex_t mutex;
void *process_function(void *arg) {
// 获取锁
pthread_mutex_lock(&mutex);
// 读写共享内存
//(long)arg 将一个指针类型的变量值转换成整数类型,以进行数学运算或格式化输出。\
使用long进行转换能够确保足够的位数以容纳地址(取决于编译器和平台定义)
printf("Process %ld writing to shared memory...\n", (long)arg);
snprintf(shared_memory, SHM_SIZE, "Hello from process %ld", (long)arg);
// 释放锁
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
//创建共享内存
shared_memory = mmap(NULL,SHM_SIZE,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,-1,0);
//初始化互斥锁
pthread_mutex_init(&mutex,NULL);
pthread_t threads[5];//创建一个线程数组
//创建多个进程(线程)
for(long i = 0; i < 5; i++)
{
pthread_create(&threads[i],NULL,thread_function,NULL);
}
//等待所有线程完成
for(int i = 0;i < 5;i++)
{
pthread_join(threads[i],NULL);
}
//打印共享内存内容
printf("Final shared memory content: %s\n",shared_memory);
//清理与释放
pthread_mutex_destory(&mutex);
munmap(shared_memory,SHM_SIZE);
return 0;
}
三、pthread_mutex_destroy和 munmap函数的使用介绍
1. pthread_mutex_destroy
-
功能:
pthread_mutex_destroy
函数用于销毁一个已经初始化的互斥锁(mutex)。这意味着该互斥锁不再可用,并且释放与该互斥锁相关联的资源。 -
用法:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
-
参数:
mutex
:指向待销毁的互斥锁对象的指针。
-
返回值:
- 如果成功,返回 0;如果发生错误,返回一个错误码。
-
注意事项:
- 在调用
pthread_mutex_destroy
时,确保没有线程在使用该互斥锁(即,确保所有锁定已经解除并且所有线程都已结束),否则会导致未定义行为。 - 在销毁之前,可以使用
pthread_mutex_lock
或pthread_mutex_trylock
等函数检查互斥锁的状态。
- 在调用
2. munmap
-
功能:
munmap
函数用于解除映射的内存区域,通常是在使用mmap
进行内存映射后,用以释放该区域。它会将指定的内存区域从进程的地址空间中移除,释放地址空间。 -
用法:
int munmap(void *addr, size_t length);
-
参数:
addr
:指向要解除映射的内存区域的起始地址。length
:要解除映射的内存区域的大小(字节数)。
-
返回值:
- 如果成功,返回 0;如果发生错误,返回 -1,并设置 errno 以指示错误原因。
-
注意事项:
- 确保提供的
addr
和length
与之前用于mmap
的参数相匹配。 - 解除映射之前,不应在该内存区域中访问数据(即,确保没有正在使用该内存区域的线程)。
- 确保提供的