linux进程间通信编程-共享内存
linux 进程间通信编程,共享内存的实验
代码分析
程序分析
共享内存实现的步骤大体如下:
- 创建共享内存对象,shm_open
- 分配共享内存大小,ftruncate
- 映射共享内存(到具体的进程空间),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操作完成。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不听话的兔子君!