进程间共享互斥所

本文详细介绍了如何在共享内存中实现进程间互斥锁,包括锁的初始化、属性设置及使用示例。同时,分析了该方法存在的缺陷,即在互斥区域内进程挂起可能导致的死锁问题。
static pthread_mutex_t *mptr;
 
将互斥锁放在共享内存。
设置互斥锁的属性为PTHREAD_PROCESS_SHARED,并初始化互斥锁。

进程间锁的例子,通过在父进程声明,然后在fork出来的子进程变可以使用这个锁的对象来进程数据访问的互斥控制


缺陷:如果一个进程在互斥区里面挂了 就发生死锁了。。
所以不是一个好办法


void my_lock_init(char *pathname)
{
int fd;
pthread_mutexattr_t mattr;
fd=open("/dev/zero", O_RDWR, 0);
mptr=mmap(0, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mptr, &mattr);
}

进程间锁的例子,通过在父进程声明,然后在fork出来的子进程变可以使用这个锁的对象来进程数据访问的互斥控制



### 共享内存中实现互斥访问的方式 在使用共享内存进行进程间通信时,为了防止多个进程同时访问共享内存导致数据不一致的问题,通常需要结合信号量(semaphore)或其他同步机制来实现互斥访问。以下详细说明其实现方式: #### 1. 使用信号量控制互斥访问 信号量是一种常用的同步工具,可以用来控制对共享资源的访问。在共享内存中,可以通过定义一个包含信号量的结构体来实现互斥访问。例如,可以定义如下结构体[^4]: ```c typedef struct { sem_t semr; // 读锁 sem_t semw; // 写锁 char buf[MAXSIZE]; // 共享数据区 } SHM; ``` - `semr` 用于控制读操作的互斥。 - `semw` 用于控制写操作的互斥。 在创建共享内存后,初始化信号量以确保其初始状态正确。例如: ```c sem_init(&shm->semr, 1, 1); // 初始化读锁,允许一个进程进入 sem_init(&shm->semw, 1, 1); // 初始化写锁,允许一个进程进入 ``` 当进程需要访问共享内存时,必须先获取信号量,访问完成后释放信号量。例如: ```c sem_wait(&shm->semw); // 获取写锁 // 对共享内存进行写操作 strcpy(shm->buf, "Hello Shared Memory"); sem_post(&shm->semw); // 释放写锁 ``` #### 2. 使用系统V信号量 在Linux系统中,还可以使用系统V信号量来实现互斥访问。通过调用 `semget()` 创建信号量集,并使用 `semop()` 操作信号量。例如: ```c int semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); // 创建信号量 struct sembuf sb = {0, -1, SEM_UNDO}; // 定义P操作 semop(semid, &sb, 1); // 执行P操作 // 访问共享内存 semop(semid, &sb, 1); // 执行V操作 ``` #### 3. 使用文件锁 除了信号量外,还可以通过文件锁(如 `flock()` 或 `fcntl()`)来实现互斥访问。例如,可以将共享内存映射到一个文件上,并对该文件加锁: ```c int fd = open("shared_memory_file", O_CREAT | O_RDWR, 0666); if (fd == -1) { perror("open"); exit(1); } struct flock lock; lock.l_type = F_WRLCK; // 写锁 lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; fcntl(fd, F_SETLKW, &lock); // 加锁 // 访问共享内存 lock.l_type = F_UNLCK; // 解锁 fcntl(fd, F_SETLK, &lock); ``` #### 4. 结合代码示例 以下是一个完整的代码示例,展示了如何使用信号量实现共享内存的互斥访问[^5]: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <unistd.h> #define MAXSIZE 1024 typedef struct { int semid; char buf[MAXSIZE]; } SHM; union semun { int val; struct semid_ds *buf; unsigned short *array; }; void init_sem(int semid) { union semun arg; arg.val = 1; semctl(semid, 0, SETVAL, arg); } void p_operation(int semid) { struct sembuf sb = {0, -1, SEM_UNDO}; semop(semid, &sb, 1); } void v_operation(int semid) { struct sembuf sb = {0, 1, SEM_UNDO}; semop(semid, &sb, 1); } int main() { key_t key = ftok("shared_memory_key", 1); int shmid = shmget(key, sizeof(SHM), IPC_CREAT | 0666); SHM *shm = (SHM *)shmat(shmid, NULL, 0); int semid = semget(key, 1, IPC_CREAT | 0666); init_sem(semid); p_operation(semid); // 获取锁 strcpy(shm->buf, "Hello Shared Memory"); printf("Shared memory content: %s\n", shm->buf); v_operation(semid); // 释放锁 shmdt(shm); shmctl(shmid, IPC_RMID, NULL); semctl(semid, 0, IPC_RMID); return 0; } ``` ### 注意事项 - 在多进程环境中,必须确保所有进程都遵循相同的规则来访问共享内存,否则可能导致竞态条件或数据损坏。 - 使用信号量时,需注意初始化和清理工作,避免遗留无效信号量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值