信號燈(信號量)集
POSIX 線程中的同步用的是無名信號量
進程間的同步使用的是IPC 對象[信號燈集]
信號燈集:信號燈集合,每一個信號燈都可以用來表示一類資源,其值表示資源的個數
(1)創建信號燈集
int semget(key_t key, int nsems, int semflg);
參數:
@key IPC_PRIVATE , ftok()
@nsems 信號燈集中信號燈的個數
@semflg IPC_CREAT | 0666,IPC_CREAT | IPC_EXCL
返回值:
成功返回ID,失敗返回-1
(2)初始化信號燈集中信號燈的值
int semctl(int semid, int semnum, int cmd, ...);
參數:
@semid 信號燈集的ID
@semnum 信號燈的編號[編號從0開始]
@cmd SETVAL[設置信號燈的值] ,GETVAL(獲取信號燈的值),IPC_RMID[刪除信號燈集]
返回值:
成功返回0,失敗返回-1
思考:將信號燈集中的1號信號燈初始化為1?
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
void init_sem_value(int sem_id,int sem_num,int value)
{
union semun sem_val;
sem_val.val = value;
if(semctl(sem_id,sem_num,SETVAL,sem_val) < 0)
{
...
}
return ;
}
(3)PV操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:完成PV操作
參數:
@semid 信號燈集的ID
@sops 操作方式結構體首地址
@nsops 操作信號燈的個數
返回值:
成功返回0,失敗返回-1
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_op :
<1>0 等待信號燈的值變成0
<2>1 釋放資源,V操作
<3>-1 申請資源,P操作
sem_flg:
0 : 阻塞方式
IPC_NOWAIT : 非阻塞方式調用
SEM_UNDO : 進程結束的時候,它申請的資源自動釋放
void P(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = -1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
void V(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = 1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
練習:A,B通過信號燈集同步對共享內存操作
讓創建信號燈集的進程,初始化信號燈的值 ,如果信號燈集已經存在則不初始化
sem_id = semget(key,2,IPC_CREAT | IPC_EXCL | 0666);
if(sem_id < 0)//信號燈集已經,不初始化信號燈值
{
sem_id = semget(key,2,IPC_CREAT | 0666);
}else{
//初始化信號燈集中信號燈的值
}