实验目的
1、进一步加深理解进程同步的概念
2、加深对进程通信的理解
3、了解Linux下共享内存的使用方法
实验内容
1、按照下面要求,写两个c程序,分别是生产者producer.c以及customer.c
2、一组生产者和一组消费者进程共享一块环形缓冲区
使用共享内存+信号量实现生产者-消费者
1、生产者进程:在第0个缓冲区写入a,第1个写入b,……,第9个写入j,并在屏幕上打印:“Producer-pid:write Y”,其中Y为写入字符,pid为生产者进程的进程ID;
2、消费者进程:依次从缓冲区中读出写入字符,读出后,将该缓冲区置为X,并在屏幕上打印:“Customer:read Y”,其中Y为读出字符,pid为消费者进程的进程ID;
基本思路
- 定义一个数据结构:
typedef struct{
int write;//当前要写的缓冲区 i
nt read;//当前要读的缓冲区
char buf[10];//10个缓冲区
}shared_buf;
- 创建一个大小为sizeof(shared_buf)的共享内存
- Producer:在buf[write]写字符‘a’+ write,然后write = (++write)% 10;
- Customer:读buf[read]中字符,并置buf[read] = ‘X’,然后read = (++read)% 10;
- 使用信号量:full、empty、mutex来进行同步及互斥
参考:共享内存
Linux POSIX共享内存
Linux System V共享内存
实验代码
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>// 定义共享数据结构
typedef struct {int write;int read;char buf[10];
} shared_buf;// 信号量句柄
HANDLE empty_semaphore;
HANDLE full_semaphore;
HANDLE mutex_semaphore;// 共享内存句柄
HANDLE shared_memory_handle;
shared_buf* shared_memory_ptr;// 生产者函数
unsigned __stdcall producer(void* arg) {int pid = _getpid();for (int i = 0; i < 20; i++) {// 等待有空缓冲区WaitForSingleObject(empty_semaphore, INFINITE);// 互斥访问共享内存WaitForSingleObject(mutex_semaphore, INFINITE);char ch = 'a' + i;shared_memory_ptr->buf[shared_memory_ptr->write] = ch;printf("Producer - %d: write %c\n", pid, ch);shared_memory_ptr->write = (shared_memory_ptr->write + 1) % 10;ReleaseSemaphore(mutex_semaphore, 1, NULL);ReleaseSemaphore(full_semaphore, 1, NULL);}return 0;
}// 消费者函数
unsigned __stdcall consumer(void* arg) {int pid = _getpid();for (int i = 0; i < 20; i++) {// 等待有满缓冲区WaitForSingleObject(full_semaphore, INFINITE);// 互斥访问共享内存WaitForSingleObject(mutex_semaphore, INFINITE);char ch = shared_memory_ptr->buf[shared_memory_ptr->read];shared_memory_ptr->buf[shared_memory_ptr->read] = 'X';printf("Consumer - %d: read %c\n", pid, ch);shared_memory_ptr->read = (shared_memory_ptr->read + 1) % 10;ReleaseSemaphore(mutex_semaphore, 1, NULL);ReleaseSemaphore(empty_semaphore, 1, NULL);}return 0;
}int main() {// 创建信号量empty_semaphore = CreateSemaphore(NULL, 10, 10, NULL);full_semaphore = CreateSemaphore(NULL, 0, 10, NULL);mutex_semaphore = CreateSemaphore(NULL, 1, 1, NULL);// 创建共享内存shared_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,sizeof(shared_buf),"SharedMemory");if (shared_memory_handle == NULL) {perror("CreateFileMapping");return 1;}shared_memory_ptr = (shared_buf*)MapViewOfFile(shared_memory_handle,FILE_MAP_ALL_ACCESS,0,0,sizeof(shared_buf));if (shared_memory_ptr == NULL) {perror("MapViewOfFile");CloseHandle(shared_memory_handle);return 1;}// 初始化共享内存shared_memory_ptr->write = 0;shared_memory_ptr->read = 0;for (int i = 0; i < 20; i++) {shared_memory_ptr->buf[i] = 'X';}// 创建生产者和消费者线程unsigned thread_id_producer;unsigned thread_id_consumer;HANDLE producer_thread = (HANDLE)_beginthreadex(NULL, 0, producer, NULL, 0, &thread_id_producer);HANDLE consumer_thread = (HANDLE)_beginthreadex(NULL, 0, consumer, NULL, 0, &thread_id_consumer);// 等待线程结束WaitForSingleObject(producer_thread, INFINITE);WaitForSingleObject(consumer_thread, INFINITE);// 清理资源UnmapViewOfFile(shared_memory_ptr);CloseHandle(shared_memory_handle);CloseHandle(empty_semaphore);CloseHandle(full_semaphore);CloseHandle(mutex_semaphore);CloseHandle(producer_thread);CloseHandle(consumer_thread);return 0;
}