一、几个基本概念
- 原子操作:不可中断的操作,一旦操作开始执行,就不能停止,直到其运行终止。
- 临界资源:同一时刻,只能被一个进程访问的资源。
- 临界区:在程序中访问临界资源的代码区域。
- 进程同步:一个进程需要等待另一个进程某些条件的发生,才能接着运行,是一种合作的关系。
- 进程异步:两个或两个以上进程互不干涉,相互不影响,是独立运行的个体。
- 信号量:是做进程间同步控制的记录资源数量的一个计数器。信号量是一个特殊的变量,只能对它进行等待和发送信号两种操作,在Linux中,信号量变量p用于等待,v用于发送信号。
二、信号量的使用的基本步骤
1、创建信号量并初始化,semget:创建/获取信号量
2、P操作、V操作,semop
3、销毁信号量
三、具体操作
1、semget函数:创建或者获取信号量
int semget((key_t)key,int nsems,int flag);
nsems指定信号量集中信号量的个数。
flag操作权限。
如果是新创建的信号量,必须做信号量初始化设置:
int semctl(int semid,int semnum,int cmd,union semun arg);
cmd=SETVAL
arg.val=信号量的初始值
如果是获取的,则可以直接使用。
2、P/V操作
int semop(int semid,struct buf[],size_t size);
semid是semget返回的信号量的标识符;
buf是一个指向结构体数组的指针,至少包含下面这些成员:
struct sembuf
{
short sem_num;//指定本变量操作的信号量集中信号量的下标
short sem_op; // -1 p操作 1 v操作
short sem_flg;// SEM_UNDO
};
int semctl(int sem_id, int sem_num, int command,…);
semid:信号量标识符
sem_num:信号量编号
command是将要采取的动作
- SETVAL:用来把信号量初始化为已知的值,这个值通过union semun中的val成员设置,其作用是在信号量第一次使用时设定它。
- IPC_RMID:用于删除一个无需继续使用的信号量标识符
返回值:当参数为SETVAL或IPC_RMID,成功返回0,失败返回-1