分类: LINUX
2013-01-05 15:06:49
在POSIX标准中,信号量分两种,一种是无名信号量,一种是命名信号量。无名信号量只用于线程间,命令信号量只用于进程间。信号量是属于POSIX:SEM的,不是属于POSIX:THR的,需要的文件头是
无名信号量是用来保护和共享线程间的临界区和共享资源的。它比起互斥锁功能更强大,互斥锁只是用来排他性访问临界区和共享资源,当一个线程要访问临界区或共享资源时,就必须先加锁,访问完成后再解锁,也就是说,加锁和解锁是成对出现的,且一个互斥锁只能对应一个临界区或共享资源个体。当同类临界区或共享资源不止一个的时候,就应该用无名信号量来进行保护和同步。例如,一个计算机系统有多个线程,都共享两台打印机,那么这时,对这两台打印机的保护和共享就必须使用无名信号量。因为无名信号量不是单纯的排他性,它还包含了一个资源计数器,用来记录空闲资源个数。更为一般的情况是,生产和消费问题,例如网络端口处的有几个缓存区,网络应用程序有两个线程一个用来接收数据并把数据放入缓存区,另一个用来处理存放在缓存区的数据。那么接收数据的线程就是生产者,处理数据的线程就是消费者。这时,生产资源和消费资源是独立的,不是成对出现的,同样需要用无名信号量来进行保护和同步。一般情况下,无名信号量要和互斥锁协作使用。
下面是无名信号量的相关数据类型和函数:
无名信号量的数据类型是:sem_t;
(1)初始化函数:
int sem_init(sem_t *sem, int pshared, unsigned value);
该函数将sem引用的无名信号量初始化为value,该参数表示拥有资源的个数,不能为负数。pshared指定为0,表示信号量只能由初始化这个信号量的进程使用,不能在进程间使用。一个无名信号量在被使用前必须先初始化。
该函数如果不成功将返回-1并设置errno。
(2)销毁函数:
int sem_destroy(sem_t *sem);
该函数用来销毁一个已经被初始化过的无名信号量。
如果不成功返回-1并设置errno。
(3)信号量操作函数:
int sem_wait(sem_t *sem);
该函数用来获取资源,如果信号量为0,表示这时没有相应资源空闲,那么调用线程就将挂起,直到有空闲资源可以获取。如果信号量不为0,那么表示这时有相应资源可用,那么将信号量减1,并返回,表示获取一个资源。
如果成功返回0,如果不成功,函数返回-1,并设置errno。值得注意的是,该函数是信号可中断的,当正在等待资源的线程收到信号(可捕捉信号)时,该函数返回-1并把errno设置为EINTR。所以,必须在被信号中断后重新启动该函数,简单代码如下:
while((-1==sem_wait(&sem))&&(EINTR==errno));
int sem_trywait(sem_t *sem);
该函数试图获取资源,当信号量为0时,它不阻塞,直接返回-1并将errno置为EAGAIN。
int sem_post(sem_t *sem);
该函数实现了信号量的signal操作,如果没有线程阻塞在该sem上,表示没有线程等待该资源,这时该函数就对信号量的值进行增1操作,表示同类资源多增加了一个。如果至少有一个线程阻塞在该sem上,表示有线程等待资源,信号量为0,这时该函数保持信号量为0不变,并使某个阻塞在该sem上的线程从sem_wait函数中返回,表示有一个可用资源到达,并被某个线程占有,所以信号量还是为0。