1.实验目的
通过编写共享内存实验,进一步了解使用共享内存的具体步骤,同时加深对共享内存的理解。在本实验中,采用信号量作为同步机制完善两个进程(“生产者”和“消费者”)之间的通信,其功能类似于4.6节中的实例。在实例中使用信号量同步机制。
2.实验内容
该实现要求利用共享内存实现文件的打开和读写操作。
3.实验步骤
(1)画出流程图。该实验流程图如图1所示。
图1 实验流程图 (2)编写代码。下面是共享内存缓冲区的数据结构的定义:
/* shm_com.h */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_BUFF_SZ 2048
struct shm_buff
{
int pid;
char buffer[SHM_BUFF_SZ];
}; 以下是“生产者”程序部分:
/* sem_com.h 和 sem_com.c 与4.4节示例中的同名程序相同 */
/* producer.c */
#include "shm_com.h"
#include "sem_com.h"
#include <signal.h>
int ignore_signal(void)
{ /* 忽略一些信号,以免非法退出程序 */
signal(SIGINT, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
return 0;
}
int main()
{
void *shared_memory = NULL;
struct shm_buff *shm_buff_inst;
char buffer[BUFSIZ];
int shmid, semid;
/* 定义信号量,用于实现访问共享内存的进程间的互斥 */
ignore_signal(); /* 防止程序非正常退出 */
semid = semget(ftok(".", 'a'), 1, 0666|IPC_CREAT); /* 创建一个信号量 */
init_sem(semid);/* 初始值为1 */
/* 创建共享内存 */
shmid = shmget(ftok(".", 'b'), sizeof(struct shm_buff), 0666|IPC_CREAT);
if (shmid == -1)
{
perror("shmget failed");
del_sem(semid);
exit(1);
}
/* 将共享内存地址映射到当前进程地址空间 */
shared_memory = shmat(shmid, (void*)0, 0);
if (shared_memory == (void*)-1)
{
perror("shmat");
del_sem(semid);
exit(1);
}
printf("Memory attached at %X\n", (int)shared_memory);
/* 获得共享内存的映射地址 */
shm_buff_inst = (struct shared_use_st *)shared_memory;
do
{
sem_p(semid);
printf("Enter some text to the shared memory(enter 'quit' to exit):");
/* 向共享内存写入数据 */
if (fgets(shm_buff_inst->buffer, SHM_BUFF_SZ, stdin) == NULL)
{
perror("fgets");
sem_v(semid);
break;
}
shm_buff_inst->pid = getpid();
sem_v(semid);
} while(strncmp(shm_buff_inst->buffer, "quit", 4) != 0);
/* 删除信号量 */
del_sem(semid);
/* 删除共享内存到当前进程地址空间中的映射 */
if (shmdt(shared_memory) == 1)
{
perror("shmdt");
exit(1);
}
exit(0);
} 以下是“消费者”程序部分:
/* customer.c */
#include "shm_com.h"
#include "sem_com.h"
int main()
{
void *shared_memory = NULL;
struct shm_buff *shm_buff_inst;
int shmid, semid;
/* 获得信号量 */
semid = semget(ftok(".", 'a'), 1, 0666);
if (semid == -1)
{
perror("Producer is'nt exist");
exit(1);
}
/* 获得共享内存 */
shmid = shmget(ftok(".", 'b'), sizeof(struct shm_buff), 0666|IPC_CREAT);
if (shmid == -1)
{
perror("shmget");
exit(1);
}
/* 将共享内存地址映射到当前进程地址空间 */
shared_memory = shmat(shmid, (void*)0, 0);
if (shared_memory == (void*)-1)
{
perror("shmat");
exit(1);
}
printf("Memory attached at %X\n", (int)shared_memory);
/* 获得共享内存的映射地址 */
shm_buff_inst = (struct shm_buff *)shared_memory;
do
{
sem_p(semid); printf("Shared memory was written by process %d :%s",
shm_buff_inst->pid, shm_buff_inst->buffer);
if (strncmp(shm_buff_inst->buffer, "quit", 4) == 0)
{
break;
}
shm_buff_inst->pid = 0;
memset(shm_buff_inst->buffer, 0, SHM_BUFF_SZ);
sem_v(semid);
} while(1);
/* 删除共享内存到当前进程地址空间中的映射 */
if (shmdt(shared_memory) == -1)
{
perror("shmdt");
exit(1);
}
/* 删除共享内存 */
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl(IPC_RMID)");
exit(1);
}
exit(0);
} 4.实验结果
实验运行结果如下:
$./producer
Memory attached at B7F90000
Enter some text to the shared memory(enter 'quit' to exit):First message
Enter some text to the shared memory(enter 'quit' to exit):Second message
Enter some text to the shared memory(enter 'quit' to exit):quit
$./customer
Memory attached at B7FAF000
Shared memory was written by process 3815 :First message
Shared memory was written by process 3815 :Second message
Shared memory was written by process 3815 :quit 本文选自华清远见嵌入式培训教材《从实践中学嵌入式Linux应用程序开发》
|