linux 进程间通信编程,共享内存的实验

代码分析

  程序分析
  共享内存实现的步骤大体如下:

  1. 创建共享内存对象,shm_open
  2. 分配共享内存大小,ftruncate
  3. 映射共享内存(到具体的进程空间),mmap
//producer_customer.c
//在多线程中
//使用SYSTEM V API实现生产者消费者经典程序
//实际上这是POSIX的实现方法,上面那句话可能有误?
#include <signal.h>
#include "shm_com.h"
#include "sem_com.h"
#include <pthread.h>

#define SHM_NAME	"/MY_SHM"

int semid ;				//信号量id
char *shm_addr = NULL;	//共享内存映射地址
struct shm_buf *shm_buf_inst = NULL;

int ignore_signal(void)
{	//忽略部分信号,避免程序非法退出
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGSTOP, SIG_IGN);
	return 0;
}

void *producer(void *arg)
{
	do
	{
		sem_p(semid);			//生产者对信号量进行P操作,申请对共享内存互斥操作
		printf("请向共享内存中输入信息(输入'quit'退出):");
		if((fgets(shm_buf_inst->buf, BUF_SIZE, stdin)) == NULL)
		{
			perror("Error fgets");
			sem_v(semid);
			break;
		}
		shm_buf_inst->pid = getpid();
		sem_v(semid);			//生产者完成对共享内存的操作,对信号量进行V操作
	}while(strncmp(shm_buf_inst->buf, "quit", 4));
	
	pthread_exit(NULL);
}


void *customer(void *arg)
{
	do
	{
		sem_p(semid);		//消费者对信号量进行P操作,申请对共享内存的互斥操作
		printf("进程%d向共享内存写入信息:%s", shm_buf_inst->pid, shm_buf_inst->buf);

		if((strncmp(shm_buf_inst->buf, "quit", 4)) == 0)
		{
			sem_v(semid);
			break;
		}

		shm_buf_inst->pid = 0;
		memset(shm_buf_inst->buf, 0, BUF_SIZE);
		sem_v(semid);		//消费者简称对信号量进行V操作,完成对共享内存菜单操作
	}while(1);
	pthread_exit(NULL);
}
int main()
{

	int fd;					//共享内存对应open对应的文件描述符
	int res;
	pthread_t thread_p, thread_c;
	//创建信号量,并初始化为1
	if((semid =(semget(ftok(".", 'a'), 1, 0666|IPC_CREAT))) == -1)
	{
		perror("Error semget");
		exit(-1);
	}
	init_sem(semid, 1);

	//创建共享内存区
	if((fd = shm_open(SHM_NAME, O_RDWR|O_CREAT, 0666)) == -1)
	{
		perror("Error shm_open");
		
		del_sem(semid);
		
		exit(-1);
	}

	//为共享内存区分配内存空间
	if((ftruncate(fd, SHM_BUF_SIZE)) == -1)
	{
		perror("Error ftruncate");
		
		del_sem(semid);

		close(fd);
		shm_unlink(SHM_NAME);
		exit(-1);
	}

	//将共享内存地址映射到当前进程地址空间
	if((shm_addr = mmap(NULL, SHM_BUF_SIZE, PROT_READ|PROT_WRITE,\
					MAP_SHARED, fd, 0)) == MAP_FAILED)
	{
		perror("Error, mmap");
		
		del_sem(semid);

		close(fd);
		shm_unlink(SHM_NAME);

		exit(-1);
	}
	printf("共享内存映射地址%p\n", shm_addr);

	shm_buf_inst = (struct shm_buf *) shm_addr;

	res = pthread_create(&thread_p, NULL, producer, NULL);
	if (res != 0)
	{
		perror("Error pthread_create producer");
	}
	res = pthread_create(&thread_c, NULL, customer, NULL);
	if (res != 0)
	{
		perror("Error pthread_create customer");
	}

	pthread_join(thread_p, NULL);
	pthread_join(thread_c, NULL);

	del_sem(semid);

	if((munmap(shm_addr, SHM_BUF_SIZE)) == -1)
	{
		perror("Error munmap");
		exit(-1);
	}

	close(fd);
	shm_unlink(SHM_NAME);
	exit(0);
}

执行结果

  右边进程在往共享内存里写,左边的进程可以检测到,并打印相关信息,读写控制由PV操作完成。
执行结果