共享記憶體
使用共享記憶體的步驟
#include <sys/ipc.h>
#include <sys/shm.h>
1 建立
int shmget(key_t key, size_t size, int shmflg);
2 attach
void *shmat(int shmid, const void *shmaddr, int shmflg);
3 使用
和使用malloc的記憶體一樣。
4 detach
int shmdt(const void *shmaddr);
5 刪除
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
建立共享記憶體段和建立訊號量非常相似,都是值得一個key,然後返回一個id。
int key = 9999;
int id = shmget((key_t)key, size, 0666|IPC_CREAT|IPC_EXCL)
如果返回的id是-1,說明建立失敗。此時需要判斷errno,如果errno等於EEXIST,說明共享記憶體段已經存在。
if(errno == EEXIST)
{
if((id = shmget((key_t)key, size, 0)) < 0)
{
return -1;
}
else
{
printf("get exists shared memory: %d\n", id);
}
}
其它可能的錯誤:
EACCES 許可權問題
EEXIST 相同key的共享記憶體段已經存在
EINVAL 多種原因,比如指定的size不符合SHMMIN和SHMMAX
ENFILE 超出檔案描述符限制
ENOENT 沒有找到指定key對應的共享記憶體段,同時又沒有指定IPC_CREAT
ENOMEM 記憶體不足
ENOSPC 共享記憶體的ID用完了(SHMMNI), 或者超過共享記憶體的系統限制(SHMALL)
EPERM 指定了SHM_HUGETLB,但是沒有許可權(did not have the CAP_IPC_LOCK capability)
得到共享記憶體端的id之後,就可以attach。attach就是把共享記憶體的地址對映到自己的地址空間裡。
void* p = shmat(id, NULL, 0666);
第一個引數是shmget得到的id
第二個引數是希望對映到的地址,如果不指定,就會自動對映一個地址。
第三個引數和其它函式一樣。
返回的指標是實際對映到的地址。
attach得到的地址傳給shmdt就可以完成detach
int shmdt(const void *shmaddr);
刪除共享記憶體段
shmctl(id,IPC_RMID, NULL);
完整例子
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int initshm(int key, int size, void** p)
{
int id = 0;
if((id = shmget((key_t)key, size, 0666|IPC_CREAT|IPC_EXCL)) < 0)
{
if(errno == EEXIST)
{
if((id = shmget((key_t)key, size, 0)) < 0)
{
return -1;
}
else
{
printf("get exists shared memory: %d\n", id);
}
}
}
else
{
printf("create shared memory: %d\n", id);
}
if((*p = shmat(id, NULL, 0666)) == NULL)
{
return -1;
}
return id;
}
int delshm(int id)
{
return shmctl(id,IPC_RMID, NULL);
}
int main()
{
int key = ftok("a.c", 1);
int id = 0;
char* p = NULL;
if((id = initshm(key, BUFSIZ, (void**)&p)) < 0)
{
printf("shmget(): %s\b", strerror(errno));
exit(1);
}
char cmd[BUFSIZ];
char str[BUFSIZ];
while(1)
{
puts("p for print.");
puts("w for write.");
puts("q for exit.");
scanf("%s", cmd);
if(strcmp(cmd, "p") == 0)
{
printf("share memory: %s\n", p);
}
else if(strcmp(cmd, "w") == 0)
{
scanf("%s", str);
strcpy(p, str);
}
else if(strcmp(cmd, "q") == 0)
{
exit(0);
}
else
{
continue;
}
}
if(delshm(id) == 0)
{
printf("shared memory %d deleted.\n", id);
}
else
{
printf("shmget(): %s\b", strerror(errno));
exit(1);
}
exit(0);
}
使用方法
shell 1
提示建立了共享記憶體
[root@server2 shm]# ./a
create shared memory: 393221
p for print.
w for write.
q for exit.
shell 2
提示得到已存在的共享記憶體
[root@server2 shm]# ./a
get exists shared memory: 393221
p for print.
w for write.
q for exit.
shell 1
按w回車,然後輸出字串後按回車
w
abcdef
shell 2
按p回車,輸出shell 1儲存到共享記憶體裡的內容
p
share memory: abcdef
然後shell 1 和 shell 2 可以交替修改和列印共享記憶體段。
此時可以看到這個共享記憶體段有兩個attach
[root@server2 ~]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 gdm 600 393216 2 dest
0x00000000 32769 gdm 600 393216 2 dest
0x00000000 65538 gdm 600 393216 2 dest
0x00000000 98307 gdm 600 393216 2 dest
0x01026a7d 393221 root 666 8192 2
兩個程式都推出後,attach被系統自動清理
[root@server2 ~]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 gdm 600 393216 2 dest
0x00000000 32769 gdm 600 393216 2 dest
0x00000000 65538 gdm 600 393216 2 dest
0x00000000 98307 gdm 600 393216 2 dest
0x01026a7d 393221 root 666 8192 0
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26239116/viewspace-2075998/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Golang 共享記憶體Golang記憶體
- POSIX共享記憶體記憶體
- oracle 共享記憶體Oracle記憶體
- POSIX 共享記憶體記憶體
- nginx共享記憶體分析Nginx記憶體
- QT之共享記憶體QT記憶體
- 共享記憶體函式記憶體函式
- shmget() -- 建立共享記憶體記憶體
- SGA與共享記憶體記憶體
- linux共享記憶體Linux記憶體
- 自動共享記憶體管理 自動記憶體管理 手工記憶體管理記憶體
- Qt共享記憶體QSharedMemoryQT記憶體
- Linux共享記憶體(二)Linux記憶體
- 修改/dev/shm共享記憶體dev記憶體
- 共享記憶體分段問題記憶體
- SGA與共享記憶體2記憶體
- 【記憶體管理】Oracle如何使用ASMM自動共享記憶體管理記憶體OracleASM
- nginx中共享記憶體的使用Nginx記憶體
- 程式間通訊---共享記憶體記憶體
- Linux共享記憶體的管理Linux記憶體
- 共享記憶體相關(ipcs/ipcrm)記憶體
- aix 共享記憶體段大小限制AI記憶體
- linux共享記憶體段研究Linux記憶體
- aix 共享記憶體段問題AI記憶體
- 第8章 管理共享記憶體記憶體
- UNIX共享記憶體的程式(轉)記憶體
- OpenResty 和 Nginx 的共享記憶體區是如何消耗實體記憶體的RESTNginx記憶體
- Android匿名共享記憶體(Ashmem)原理Android記憶體
- 程式間通訊之共享記憶體記憶體
- 修改OracleLinux共享記憶體的大小OracleLinux記憶體
- SGA與共享記憶體的關係記憶體
- 程序間通訊(3)-共享記憶體記憶體
- Linux釋放記憶體及手動釋放Oracle共享記憶體段Linux記憶體Oracle
- Golang併發之共享記憶體變數Golang記憶體變數
- Linux共享記憶體的核心實現Linux記憶體
- 解決ORACLE共享記憶體不足的方法Oracle記憶體
- opracle 共享記憶體 /etc/sysctl.conf記憶體
- linux下的記憶體共享引數Linux記憶體