Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1878925
  • 博文数量: 217
  • 博客积分: 4362
  • 博客等级: 上校
  • 技术积分: 4180
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-20 09:31
文章分类

全部博文(217)

文章存档

2017年(1)

2015年(2)

2014年(2)

2013年(6)

2012年(42)

2011年(119)

2010年(28)

2009年(17)

分类: LINUX

2010-09-27 20:11:55

在进程通信当中,我经常会用到信号灯的操作,为此,我小结一下:
信号灯有无名信号灯和有名信号灯,我们仅讨论无名信号灯,

创建信号灯:
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   
阅读(1765) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~