在进程通信当中,我经常会用到信号灯的操作,为此,我小结一下:
信号灯有无名信号灯和有名信号灯,我们仅讨论无名信号灯,
创建信号灯:
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem表示信号灯的一些信息,类似于进程的PCB。
pshared表示是否为多进程所共享,而不仅仅是一个用于一个进程,linux Thread下没有实现多进程的信号灯共享,所以这个值一般为0,否则会返回-1错误值。
value表示信号灯的数量。
注销信号灯:
int sem_destroy(sem_t *sem);
sem表示要注销的信号灯。
获取灯值:
int sem_getvalue(sem_t *sem, int *sval);
读取sem灯的灯计数。
点灯操作:
int sem_post(sem_t *sem);
给灯值原子加1,表示增加了一个可用的资源。
灭灯操作:
int sem_wai(sem_t *sem);
int sem_trywait(sem_t *sem);
这两个都是将信号灯的原子值减1,表示减少一个可用的资源。但这两个也是有区别的:如果当信号灯的原子值小于或等于0,使用sem_trywait()时不会使线程阻塞,而sem_wait()时将会使线程阻塞。
有关信号灯的操作一般都在头文件
当中,下面是人sem_t的结构体定义:
typedef union
{
char __size[__SIZEOF_SEM_T];
long int __align;
} sem_t;
一个实例:生产者-消费者(经典IPC问题)
/* *Time:2010/9/27 *Author:Software Engineering */ # include < stdio. h> # include < string . h> # include < pthread. h> //包含线程操作的一些函数 # include < semaphore. h> //包含信号灯操作的一些函数 # define N 4 //定义缓冲池的数量 # define P_COUNT 3 //定义生产者的数量 # define C_COUNT 3 //定义消费者的数量 int first = 0; //记录缓冲区的下标 char buffer[ N] [ 20] ; //缓冲区的定义 pthread_mutex_t mutex; //互斥锁 sem_t full, empty; //分别表示缓冲池中的空区和满区的数量 void print( ) { int i; for ( i = 0; i < N; i+ + ) { printf ( "%s\t" , buffer[ i] ) ; } printf ( "\n" ) ; } void * producer( ) { char * goods = "鸡蛋" ; int count = 8; do { sem_wait( & empty) ; //关灯操作 pthread_mutex_lock ( & mutex) ; strcpy ( buffer[ first+ + ] , goods) ; printf ( "%u生产者:" , pthread_self( ) ) ; print( ) ; sleep ( 1) ; pthread_mutex_unlock ( & mutex) ; sem_post( & full) ; //开灯操作 } while ( count - - > 0) ; } void * customer( ) { int count = 8; do { sem_wait( & full) ; //关灯操作 pthread_mutex_lock ( & mutex) ; strcpy ( buffer[ - - first] , "0" ) ; printf ( "%u消费者:" , pthread_self( ) ) ; print( ) ; sleep ( 1) ; pthread_mutex_unlock ( & mutex) ; sem_post( & empty) ; //开灯操作 } while ( count - - > 0) ; } int main( ) { pthread_t tid1, tid2; int i; //初始化缓冲池 for ( i = 0; i < N; i+ + ) { strcpy ( buffer[ i] , "0" ) ; } //创建信号灯 sem_init( & empty, 0, N) ; sem_init( & full, 0, 0) ; //创建生产者线程和消费者线程 for ( i = 0; i < P_COUNT; i+ + ) { pthread_create ( & tid1, NULL , producer, NULL ) ; } for ( i = 0; i < C_COUNT; i+ + ) { pthread_create ( & tid2, NULL , customer, NULL ) ; } pthread_exit ( 0) ; }
运行的部分结果:
3068443504生产者:鸡蛋 鸡蛋 鸡蛋 0
3026484080消费者:鸡蛋 鸡蛋 0 0
3026484080消费者:鸡蛋 0 0 0
3047463792消费者:0 0 0 0
3068443504生产者:鸡蛋 0 0 0
3068443504生产者:鸡蛋 鸡蛋 0 0
3068443504生产者:鸡蛋 鸡蛋 鸡蛋 0
3057953648生产者:鸡蛋 鸡蛋 鸡蛋 鸡蛋
3026484080消费者:鸡蛋 鸡蛋 鸡蛋 0
3068443504生产者:鸡蛋 鸡蛋 鸡蛋 鸡蛋
3047463792消费者:鸡蛋 鸡蛋 鸡蛋 0
3047463792消费者:鸡蛋 鸡蛋 0 0
3047463792消费者:鸡蛋 0 0 0
<script>window._bd_share_config={"common":{"bdsnskey":{},"bdtext":"","bdmini":"2","bdminilist":false,"bdpic":"","bdstyle":"0","bdsize":"16"},"share":{}};with(document)0[(getelementsbytagname('head')[0]||body).appendchild(createelement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new date()/36e5)];</script>
阅读(752) | 评论(0) | 转发(0) |