static struct sembuf hms_rl[2] = { {0, -1, SEM_UNDO}, {0, 2, SEM_UNDO}
static struct sembuf hms_wl[2] = { {0, -1, SEM_UNDO}, {0, 0, SEM_UNDO} };
static struct sembuf hms_url[1] = { {0, -1, SEM_UNDO} };
static struct sembuf hms_uwl[1] = { {0, 1, SEM_UNDO} };
static struct sembuf hms_init[1] = { {0, 1} };
int hms_lock_read(int semid)
{
/*
1. 申请读锁时,首先做P(1)操作,确保当前没有其他进程在进行写操作;
然后做V(2)操作,最终实际是对信号量做V(1)操作.
2. 如果被信号打断,则再次获取锁,否则返回失败。
3. 从实际对信号量的V(1)操作可以看出,该读写锁是读者优先的。
4. 该信号量的取值范围是[0 - 同时调用hms_lock_read()的进程数+1]。
5. 写者优先锁:将hms_rl和hms_wl,hms_url和hms_uwl的定义互换即可。
6. 读锁可申请成功的条件是:当前信号量的值大于或等于1.
*/
while (semop(semid, hms_rl, 2) == -1) {
if (errno == EINTR) {
continue;
} else {
return -1;
}
}
return 0;
}
int hms_lock_write(int semid)
{
/*
1. 申请写锁时,首先做P(1)操作,确保当前没有其他进程在进行写操作;
然后做P(0)或V(0)操作,判断信号量的值是否为0,即确认没有进程在进行读操作.
2. 如果被信号打断,则再次获取锁,否则返回失败。
3. 写锁可申请成功的条件是:
3.1 当前信号量的值等于1.
3.2 或者说:只有当所有的读锁都释放后,且没有其他进程获取的写锁,本次写锁才会申请成功。
*/
while (semop(semid, hms_wl, 2) == -1) {
if (errno == EINTR) {
continue;
} else {
return -1;
}
}
return 0;
}
void hms_unlock_read(int semid)
{
/*
1. 释放读锁时,做P(1)操作.
*/
semop(semid, hms_url, 1);
}
void hms_unlock_write(int semid)
{
/*
1. 释放写锁时,做V(1)操作,用于通知后续的读或写操作,当前有资源存在。
*/
semop(semid, hms_uwl, 1);
}
int hms_init_rwlock(int key)
{
/*
1. 初始化锁资源值为1.
*/
int semid;
if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 1023)) == -1) {
if (errno != EEXIST)
return -1;
if ((semid = semget(key, 1, 0)) == -1)
return -1;
} else {
semop(semid, hms_init, 1);
}
return semid;
}