实验目的
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;
}