system V 共享内存区
对于每个共享内存区,内核维护如下的信息结构: <sys/shm.h>
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};
struct shmid_ds
{
struct ipc_perm shm_perm; //权限
size_t shm_segsz ; //共享内存区的大小
pid_t shm_lpid; //pid of last operation
pid_t shm_cpid; //creator pid
shmatt_t shm_nattch; //number of current attaches
time_t shm_atime; //last attach time
time_t shm_dtime; //last dettach time
time_t shm_ctime; //last change time of this structure
};
共享内存操作API:
0. ftok申请一个system v ipc的key
1. shmget: 创建或打开一个system v共享内存区
2. shmat: 把共享内存区映射到进程地址空间
3. shmdt: 把共享内在区解映射
4. shmctl: 对共享内存区进行控制操作
1. shmget: 用来创建或打开一个共享内存区
NAME
shmget - allocates a System V shared memory segment
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
key:system v ipc对象的key
size: 以字节为单位指定内存区的大小。
当实际操作为创建一个新的内存区时,
必须指定一个不为0的size值。如果实际操作
为访问一个已经存在的共享内存区,那么
size应为0. 共享内存区的大小为PAGE_SIZE(4k)的
整数倍。
shmflg: 标志位:
(1) 创建 IPC_CREAT |权限位
(2) 打开 0
返回值:
成功返回打开的共享内存区的ID(不是文件描述符)
失败返回-1, errno被设置
2. shmat
NAME
shmat, shmdt - System V shared memory operations
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
shmat用来把共享内存区映射到进程自己的地址空间。
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid: 要映射的共享内存区
shmaddr:指定映射到进程地址空间具体哪个地址。
如为NULL(一般也为NULL),则让操作系统自动
确定映射地址。
shmflg: 映射标志
(1) SHM_RDONLY 只读
(2) 0 可读可写
返回值:
成功返回映射共享内存区的首地址,
失败返回NULL
3
int shmdt(const void *shmaddr);
shmdt用来解映射的
int shmdt(const void *shmaddr);
4.
NAME
shmctl - System V shared memory control
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
shmctl用来对共享内存区进行控制操作的
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmid: 共享内存区的ID,表示要对哪个共享内存区进行控制操作
cmd: 操作命令。常用有三个:
IPC_RMID: 删除共享内存区.此时,第三个参数为NULL
IPC_STAT:获取共享内存区的属性信息。
获取到的属性信息保存在第三个参数
buf指向的结构体当中。
IPC_SET: 设置共享内存区的属性信息。
通过第三个参数buf指向的结构体来改变。
shmid_ds结构以下三个成员,可以被你改变:
shm_perm. uid, shm_perm.gid, shm_perm.mode.
buf:
返回值:
成功返回0,
失败返回-1, errno被设置
DEMO:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
#define PATH_NAME "/home/klein"
#define PROJ_ID 34
int main(int argc,char** argv){
//1,obtain a key
//key_t ftok(const char *pathname, int proj_id);
key_t key = ftok(PATH_NAME,PROJ_ID);
if(key == -1){
perror("ftok error");
return -1;
}
//2.get shared memory
//int shmget(key_t key, size_t size, int shmflg);
int shm_id = shmget(key,3,IPC_CREAT | 0666);//obtain a pagesize (4k)
if(shm_id == -1){
perror("shmget error");
return -1;
}
//3. void *shmat(int shmid, const void *shmaddr, int shmflg);
char *p = shmat(shm_id,NULL,0);/*If shmaddr is NULL, the system chooses a suitable (unused) address at
which to attach the segment.*/
strcpy(p,"hello,shared memory content.");
shmdt(p);
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <string.h>
#define PATH_NAME "/home/klein"
#define PROJ_ID 34
int main(int argc,char** argv){
//1,obtain a key
//key_t ftok(const char *pathname, int proj_id);
key_t key = ftok(PATH_NAME,PROJ_ID);
if(key == -1){
perror("ftok error");
return -1;
}
//2.get shared memory
//int shmget(key_t key, size_t size, int shmflg);
int shm_id = shmget(key,3,IPC_CREAT | 0666);//obtain a pagesize (4k)
if(shm_id == -1){
perror("shmget error");
return -1;
}
//3. void *shmat(int shmid, const void *shmaddr, int shmflg);
char *p = shmat(shm_id,NULL,0);/*If shmaddr is NULL, the system chooses a suitable (unused) address at
which to attach the segment.*/
//strcpy(p,"hello,shared memory content.");
printf("%s\n",p);
shmdt(p);
return 0;
}