信号量
信号量是一个计数器的值,它可以被几个进程作为一个集合义原子的方式执行。信号量的计数器控制着对资源的访问控制,信号量提供了两个主要的操作来处理计数器的值:
(1)资源的使用者在使用资源之前等待信号量。如果信号量的值为0,则继续等待,如果大于0,则将信号量值减1,使用者开始使用资源。
(2)资源的使用者在资源使用完毕后通知信号量。使用者通知信号量不再使用资源了,信号量的值加1,检查等待信号量的使用者的序列,以确定是否有其他的使用者在等待之中。
使用信号量进行进程间的通信一般牵涉到以下操作:
相关信号量的操作函数一般应该包含下面的头文件;
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
1.创建信号量:在程序使用信号量之前,必须首先创建信号量。创建信号量的函数原形如下所示:
int semget(key_t key,int nsems,int semflg);
参数说明:
(1)key:在本地系统中表示要创建或者访问的信号量及的关键字,当然为了避免与其他的信号量产生冲突,我们可以简单的利用IPC_PRIVATE来表示一个新建的信号量。
(2)nsems:要创建或者要访问的信号量集中信号量的数目。
(3)指定不同的选项和权限位的标志。可以为IPC_CREATE,IPC_EXCL.
创建一个新的信号量:
int semid;
semid=semget(0x1234,2,IPC_CREATE|IPC_EXCL|0600);
if(semid<0)
{
process error case.
}else
{
do the next thing;
}
使用已经存在的信号量:
int semid;
semid=semget(0x1234,0,0);
if(semid<0)
{}else
{}
2.初始化信号集:
int semctl(int semid,int semnum,int cmd,union semun arg);
union semun
{
int val;
struct semid_ds *buf;
ushort *array;
};
eg:
int semid;
int z;
union semun arg;
ushort initv[]={4,2};
arg.array=initv;
z=semctl(semid,2,SETALL,arg);
3.等待通知信号量:等待信号量和通知信号量都是利用函数semop(),只是相关的参数不同而已。
int semop(int semid,struct sembuf *sops,unsigned nsops);
struct sembuf
{
short sem_num; /*信号量的索引*/
short sem_op; /*信号量的相关操作为一个整数(正数表示通知信号量,负数表示等待信号量)*/
short sem_flg;/*相关的操作标记*/
};
eg:
int z;
static struct sembuf sops[]=
{
{1,-1,0},
{0,-1,0}
};
z=semop(semid,sops,2);
如果是通知信号量,则sembuf的值可以设为
static struct sembuf sops[]=
{
{1,+1,0},
{0,+1,0}
};
z=semop(semid,sops,2);
4.删除信号量
当信号量在系统中没有用处后,应该将其删除,这样才能释放内核中的支持表所占用的资源。
int semctl(int semid,int semnum,int cmd,union semun arg);
eg:
int semid;
int z;
union semun arg;
z=semctl(semid,0,IPC_RMID,arg);
值得一提的是信号量的使用遵循自愿的原则的,也就是说信号量并不能强制的限制应用程序对资源的访问,我们在编写每一个程序的时候,都将通过资源的原则来执行如下操作:
1)在访问受控资源前等待信号量。
2)释放受控的资源后要通知信号量。