共享内存:
特点:
1、共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
2、为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
3、进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。
4、由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
实现步骤:
主要函数:
1、 ftok(任意路径,任意0-255之间的数);//利用ftok函数获得一个key值
2、shmget(key值,空间大小,权限:例0666 | IPC_CREAT);//创建并打开共享内存创建共享内存:
3、char *p = (char *)shmat(shmID,NULL,0);//映射到用户空间。
4、shmdt (p);//撤销共享内存
5、shmctl(shmID,IPC_RMID,NULL);//删除共享内存
案例:
qy.c:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <semaphore.h> #include <fcntl.h> int main(void) { //有名信号量的创建 sem_t* sem_1 = sem_open("sem1", O_CREAT | O_RDONLY, 0666, 1); if(SEM_FAILED == sem_1) { perror("sem_open error"); return -1; } sem_t* sem_2 = sem_open("sem2", O_CREAT | O_RDONLY, 0666, 0); if(SEM_FAILED == sem_2) { perror("sem_open error"); return -1; } //获得一个Key值 key_t key = ftok("./",10); //创建共享内存,返回一个内存ID int shmID = shmget(key, 200, 0666 | IPC_CREAT); if(-1 == shmID) { perror("shmget error"); return -1; } //映射到用户空间返回空间地址 char *p = (char *)shmat(shmID, NULL, 0); if((void *)-1 == (void *)p) { perror("shmat error"); return -1; } //信号量的用法与无名相同 sem_wait(sem_2); printf("%s\n",p); sem_post(sem_1); //删除信号量 sem_unlink(sem_1); sem_unlink(sem_2); //撤销映射 shmdt(p); //删除共享内存 shmctl(shmID, IPC_RMID, NULL); return 0; }
wf.c
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <semaphore.h> #include <fcntl.h> int main(void) { //有名信号量的创建 sem_t* sem_1 = sem_open("sem1", O_CREAT | O_RDONLY, 0666, 1); if(SEM_FAILED == sem_1) { perror("sem_open error"); return -1; } sem_t* sem_2 = sem_open("sem2", O_CREAT | O_RDONLY, 0666, 0); if(SEM_FAILED == sem_2) { perror("sem_open error"); return -1; } //获得一个Key值 key_t key = ftok("./",10); //创建共享内存,返回一个内存ID int shmID = shmget(key, 200, 0666 | IPC_CREAT); if(-1 == shmID) { perror("shmget error"); return -1; } //映射到用户空间返回空间地址 char *p = (char *)shmat(shmID, NULL, 0); if((void *)-1 == (void *)p) { perror("shmat error"); return -1; } //信号量的用法与无名相同 sem_wait(sem_1); printf("请输入:"); gets(p); sem_post(sem_2); //关闭信号量文件 sem_close(sem_1); sem_close(sem_2); //撤销映射 shmdt(p); //删除共享内存 shmctl(shmID, IPC_RMID, NULL); return 0; }
makefile
APP: gcc qy.c -o qy -lpthread gcc wf.c -o wf -lpthread
注意:这里清空共享内存空间可以用memset();
在终端输入ipcs -m 查看shmid
然后输入ipcrm -m ID号 及删除共享内存