- 操作系统实验job9
- 实验内容
- 实验代码
- `pc.c`
- `pp.c`
- 实验思路
- 使用信号量解决生产者、计算者、消费者问题 pc.c
- 使用信号量实现 ping-pong 问题 pp.c
#includepp.c#include #include #define CAPACITY 4 int buffer1[CAPACITY]; int buffer2[CAPACITY]; int in_buffer1; int out_buffer1; int in_buffer2; int out_buffer2; int buffer1_is_empty() { return in_buffer1 == out_buffer1; } int buffer1_is_full() { return (in_buffer1 + 1) % CAPACITY == out_buffer1; } int buffer2_is_empty() { return in_buffer2 == out_buffer2; } int buffer2_is_full() { return (in_buffer2 + 1) % CAPACITY == out_buffer2; } int get_buffer1_item() { int item; item = buffer1[out_buffer1]; out_buffer1 = (out_buffer1 + 1) % CAPACITY; return item; } int get_buffer2_item() { int item; item = buffer2[out_buffer2]; out_buffer2 = (out_buffer2 + 1) % CAPACITY; return item; } void put_buffer1_item(int item) { buffer1[in_buffer1] = item; in_buffer1 = (in_buffer1 + 1) % CAPACITY; } void put_buffer2_item(int item) { buffer2[in_buffer2] = item; in_buffer2 = (in_buffer2 + 1) % CAPACITY; } typedef struct { int value; pthread_mutex_t mutex; pthread_cond_t cond; } sema_t; void sema_init(sema_t *sema, int value) { sema->value = value; pthread_mutex_init(&sema->mutex, NULL); pthread_cond_init(&sema->cond, NULL); } void sema_wait(sema_t *sema) { pthread_mutex_lock(&sema->mutex); while (sema->value <= 0) pthread_cond_wait(&sema->cond, &sema->mutex); sema->value--; pthread_mutex_unlock(&sema->mutex); } void sema_signal(sema_t *sema) { pthread_mutex_lock(&sema->mutex); ++sema->value; pthread_cond_signal(&sema->cond); pthread_mutex_unlock(&sema->mutex); } sema_t mutex_sema; sema_t empty_buffer1_sema; sema_t full_buffer1_sema; sema_t empty_buffer2_sema; sema_t full_buffer2_sema; #define ITEM_COUNT (CAPACITY * 2) void *produce(void *arg) { int i; int item; for (i = 0; i < ITEM_COUNT; i++) { sema_wait(&empty_buffer1_sema); sema_wait(&mutex_sema); item = 'a' + i; put_buffer1_item(item); printf(" %cn", item); sema_signal(&mutex_sema); sema_signal(&full_buffer1_sema); } return NULL; } void *calculate(void *arg) { int i; int item; for (i = 0; i < ITEM_COUNT; i++) { sema_wait(&full_buffer1_sema); sema_wait(&mutex_sema); item = get_buffer1_item()+'A'-'a'; sema_signal(&mutex_sema); sema_signal(&empty_buffer1_sema); sema_wait(&empty_buffer2_sema); sema_wait(&mutex_sema); put_buffer2_item(item); printf("t %c:%cn",item-'A'+'a',item); sema_signal(&mutex_sema); sema_signal(&full_buffer2_sema); } return NULL; } void *consume(void *arg) { int i; int item; for (i = 0; i < ITEM_COUNT; i++) { sema_wait(&full_buffer2_sema); sema_wait(&mutex_sema); item = get_buffer2_item(); printf("tt %cn", item); sema_signal(&mutex_sema); sema_signal(&empty_buffer2_sema); } return NULL; } int main() { pthread_t consumer_tid1; pthread_t consumer_tid2; sema_init(&mutex_sema, 1); sema_init(&empty_buffer1_sema, CAPACITY - 1); sema_init(&full_buffer1_sema, 0); sema_init(&empty_buffer2_sema, CAPACITY - 1); sema_init(&full_buffer2_sema, 0); pthread_create(&consumer_tid1, NULL, consume, NULL); pthread_create(&consumer_tid2, NULL, calculate, NULL); produce(NULL); pthread_join(consumer_tid1, NULL); pthread_join(consumer_tid2, NULL); return 0; }
#include实验思路#include #include typedef struct { int value; pthread_mutex_t mutex; pthread_cond_t cond; } sema_t; void sema_init(sema_t *sema, int value) { sema->value = value; pthread_mutex_init(&sema->mutex, NULL); pthread_cond_init(&sema->cond, NULL); } void sema_wait(sema_t *sema) { pthread_mutex_lock(&sema->mutex); while (sema->value <= 0) pthread_cond_wait(&sema->cond, &sema->mutex); sema->value--; pthread_mutex_unlock(&sema->mutex); } void sema_signal(sema_t *sema) { pthread_mutex_lock(&sema->mutex); ++sema->value; pthread_cond_signal(&sema->cond); pthread_mutex_unlock(&sema->mutex); } sema_t mutex_sema; sema_t wait_ping; sema_t wait_pong; int flag=1; void *ping(void *arg) { while(1) { if(flag==0) sema_wait(&wait_pong); sema_wait(&mutex_sema); printf("pingn"); sleep(1); flag=0; sema_signal(&mutex_sema); sema_signal(&wait_ping); } } void *pong(void *arg) { while(1) { if(flag==1) sema_wait(&wait_ping); sema_wait(&mutex_sema); printf("pongn"); sleep(1); flag=1; sema_signal(&mutex_sema); sema_signal(&wait_pong); } } int main() { pthread_t consumer_tid; sema_init(&mutex_sema, 1); sema_init(&wait_ping, 0); sema_init(&wait_pong, 0); pthread_create(&consumer_tid, NULL, pong,`在这里插入代码片` NULL); ping(NULL); pthread_join(consumer_tid, NULL); return 0; }
主要还是在job8的基础上进行修改。在讲义中条件变量章节的例子2说明了如何基于条件变量实现信号量
核心代码为
typedef struct { //条件变量结构体
int value; //value记录了信号量的值
pthread_mutex_t mutex;
pthread_cond_t cond;
} sema_t;
void sema_init(sema_t *sema, int value)
{
sema->value = value;
pthread_mutex_init(&sema->mutex, NULL);
pthread_cond_init(&sema->cond, NULL);
}
void sema_wait(sema_t *sema) //如果信号量的值小于等于0,则等待条件变量
{ //将信号量的值减一
pthread_mutex_lock(&sema->mutex);
while (sema->value <= 0)
pthread_cond_wait(&sema->cond, &sema->mutex);
sema->value--;
pthread_mutex_unlock(&sema->mutex);
}
void sema_signal(sema_t *sema) //将信号量的值加一,唤醒等待条件变量的线程
{
pthread_mutex_lock(&sema->mutex);
++sema->value;
pthread_cond_signal(&sema->cond);
pthread_mutex_unlock(&sema->mutex);
}
定义好信号量之后替换job8中的条件变量即可。
注意:使用信号量机制后mutex加锁的位置与条件变量不同,是相反的,值得注意。



