共享内存
共享内存的特点:
- :共享内存是一种最为高效的进程间通信方式。
- :进程可直接读写内存,不需要数据的复制。
- :内核专门留出一块内存区,此内存区可以由需要访问的进程将其映射到自己私有的地址空间。
- :由于多个进程访问一块共享内存,因此,也需要某种同步机制,如互斥锁和信息量。
共享内存的原理示意图:
共享内存的创建
第一步:创建共享内存 shmget()函数,成功:返回共享内存标识符,失败:返回-1;
第二步:映射共享内存到具体的进程空间中: shmat()函数,成功:返回被映射的段地址
失败:返回-1。
第三步:解除与共享内存的映射关系 shmdt()函数,成功返回0,失败返回-1.
第四步:删除共享内存。
实现共享内存传送消息完整代码:
接收消息代码:
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
void sigFunc(int signum)
{
if(SIGUSR1 == signum)
{
}
}
int main()
{
pid_t pid =
key_t key = ftok(".",10);
if(key < 0)
{
perror("ftok error!");
return -1;
}
printf("key = %d\n",key);
int shmld = shmget(key,100,0666|IPC_CREAT);
if(shmld < 0)
{
perror("shmget error!");
return -1;
}
printf("shmld = %d\n",shmld);
pid_t pid = getpid();
printf("shm_r pid: %d\n",pid);
pid_t *p1 = shmat(shmld,NULL,0);
if((pid_t*)-1 == p1)
{
perror("shmat error!");
shmctl(shmld,IPC_RMID,NULL);
return -1;
}
*p1 = pid;
shmdt(p1);
void*p = shmat(shmld,NULL,0);
if((void *)-1 == p)
{
perror("shmat error!");
shmctl(shmld,IPC_RMID,NULL);
return 0;
}
while(1)
{
signal(SIGUSR1,sigFunc);
pause();
printf("rec : %d\n",*((int *)p));
}
//shmdt(p);
// shmctl(shmld,IPC_RMID,NULL);
return 0;
}
发送消息代码:
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<signal.h>
int main()
{
key_t key = ftok(".",10);
if(key < 0)
{
perror("ftok error!");
return -1;
}
printf("key = %d\n",key);
int shmld = shmget(key,100,0666|IPC_CREAT);
if(shmld < 0)
{
perror("shmget error!");
return -1;
}
printf("shmld = %d\n",shmld);
void *p1 = shmat(shmld,NULL,0);
if((void*)-1 ==p1)
{
perror("shmat error!");
shmctl(shmld,IPC_RMID,NULL);
return -1;
}
pid_t pid = *(pid_t*)p1;
printf("shm_r pid :%d\n",pid);
shmdt(p1);
void *p =shmat(shmld,NULL,0);
while(1)
{
if((void*)-1 ==p)
{
perror("shmat error!");
shmctl(shmld,IPC_RMID,NULL);
return 0;
}
printf("intput int:");
scanf("%d",(int *)p);
kill(pid,SIGUSR1);
}
shmdt(p);
return 0;
}
运行操作:gcc shem_r.c -o r -lpthread
gcc shem_wc -o w -lpthread
注意:先./r 再./w 因为首先先将shem_r创建的pid发送于shem_w,从而shem_w通过pid给进程shem_r发送消息。
实现结果: