共享内存防止读写冲突

共享内存的读写冲突问题:
在设计上尽量就是一个写,一个或多个读。那么要解决的问题有两个:
1. 读写同步问题,例如如果写一段数据中就有人来读了,那就是读到了一半旧的一半新的数据,播放帧就是花屏,又例如写结构体,先写帧地址,在写帧长度,那么user就可能读到新的地址和旧的长度导致越界(实际和读写锁一样:写比读优先,写时不允许读写,多个可以同时读)。
2. 写了之后通知读者有更新。和信号量的一对一不同,我们需要多个读者读同一个资源,因此采用信号或futex通知。

int futex(int *uaddr, int op, int val, const struct timespec *timeout,
                 int *uaddr2, int val3);

例如:
等待参数1地址的值改变(自己知道的现值是参数3),参数2为op。timeout为最多等待的时间,为NULL则不更新就一直阻塞。后两个参数忽略。
futex(&ptr_bq->latest_seq, FUTEX_WAIT, ptr_bq->latest_seq, timeout, NULL, 0);
通知参数1地址的值已改变,新的值就是这个地址里的值,参数2为op。它最多环境参数3个数的等待者。后三个参数忽略。
futex(&ptr_bq->latest_seq, FUTEX_WAKE, CUST_NUM_MAX, NULL, NULL, 0);
注意,第一个参数也是共享内存里的,当然,对于多进程,由于页表不同,第一个参数的虚拟地址(即进程中看到的地址)不同,但物理地址相同的,所以没关系。

–共享内存同步要注意什么–
使用共享内存的时候,除了设计上减少同步,还有别的要注意么?
1,创建任何东西先带着CREAT | EXCL去创建,失败了则直接打开,这是原子性必备的。
2,共享内存初始化之前如何同步?即如何保证创建chm的进程对共享内存初始化好了,其他进程才能够shmget? 设置mode的x位(用shmctl设置IPC_STAT,因为x位未使用)后开始初始化共享内存,结束后取消x位,任何进程打开共享内存后stat轮询检查x位(用shmctl获取IPC_STAT)是否复位,复位后才可以开始操作。
3,进程共享的mutex, cond,你应该都会用,不会用看书或者man pthread.h找接口。
4,共享内存可以做成chunk list内存块链表,一般用于在共享内存中建立树型数据结构,或者建死的多级hash表,或者循环队列,都是可以做的。

进程间共享的mutex和cond,可实现共享内存的读写互斥:

int   pthread_condattr_setpshared(pthread_condattr_t *, int);
int   pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);

例如(随便找的例子):
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);
}

一个进程里的多线程就好办多了,互斥直接用pthread_mutex_lock,对于整数变量的访问可以通过__sync_add_and_fetch来无锁编程。

你可能感兴趣的:(闲得慌)