共享内存(改编)
System V共享内存区,先调用shmget,得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符,然后再调用shmat,连接共享内存标识符位shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后即可像本地空间一样访问。
对于每一个共享内存区。内核维护如下的信息结构,其定义在
文件中
struct shmid_ds{
struct ipc_perm shm_perm;//operation permission struct
size_t shm_segsz;//segment size
pid_t shm_lpid;//pid of last operation
pid_t shm_cpid;//creator pid
shmatt_t shm_nattach;//current attached
shmat_t shm_cnattch;///in-core attached
time_t shm_atime;//last attach time
time_t shm_dtime;//last detach time
time_t shm_ctime;//last change time of this structure
}
shmget
shmget函数创建一个新的共享内存区,或者访问一个已存在的共享内存区。其定义如下
int shmget(key_t key,size_t size,int oflag)
若创建成功则返回内存区对象,若出错则返回-1。返回的对象为内存区标识符的整数,其他三个函数就是用这个整数来指代这个内存区。
key既可以是IPC_PRIVATE也可以是ftok的返回值。
size若为首次创建则不为0,若要访问已经存在的则为0。
oflag为读写权限的组合。它还可以与 IPC_CREAT 或IPC_CREAT | IPC_EXCL按位或。
shmat
由shmget函数创建或打开一个共享内存区后,通过shmat把它附接到调用进程的地址空间
void *shmat(int shmid,const void *shmaddr,int flag)
若成功则返回映射区的起始地址,失败返回-1。
shmid为shmget返回的标识符。
shmaddr为空指针则系统替调用者选择地址,若为非空指针则取决于调用者是否给flag指定了SHM_RND的值(略)。
flag参数用来指定SHM_RDONLY的值,它限定只读访问。
shmdt
shmdt用来释放调用者对共享内存的所有权。
int shmdt(const void *shmaddr)
若返回0则成功,若返回-1则表示出错。
当进程终止,则自动释放所有权。
shmctl
shmctl用来指定对共享内存的操作方式。
int shmctl(int shmid,int cmd,struct shmid_ds *buff);
成功返回0,失败返回-1。
shmid为shmget返回的标识符。
cmd为操作方式,IPC_RMID为从系统删除共享内存区并删除它,IPC_SE为给所指定的共享内存区设置其shmid_ds结构的以下三个成员shm_perm.uid shm_perm.gid和 shm_perm.mode,它们的值来自buff参数指向的数据结构中相应的成员。shm_ctime的值也可以用当前时间替换。IPC_STAT向调用者返回所指向的共享内存区当前的shmid_ds结构。
下面给出一个读写分开的例子。
写
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/shm.h>
int main(){
struct shmid_ds buff;
key_t my_path_name = ftok("/home/pcx/Desktop",1);
auto oflag = IPC_CREAT | 0666;
int tmp = shmget(my_path_name,4096,oflag);
char *ptr =(char *) shmat(tmp,NULL,0);
shmctl(tmp,IPC_STAT,&buff);
std::string tmp_data = "name:pcx\ngender:male\nclass:1703018\n";
for(int i=0;i<buff.shm_segsz;i++){
*ptr++ = tmp_data[i];
}
shmdt(ptr);
return 0;
}
读
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/shm.h>
int main(){
struct shmid_ds buff;
key_t my_path_name = ftok("/home/pcx/Desktop",1);
auto oflag = IPC_CREAT | 0666;
int tmp = shmget(my_path_name,0,oflag);
char *ptr =(char *) shmat(tmp,NULL,0);
shmctl(tmp,IPC_STAT,&buff);
char tmp_data[4096] = {0};
for(int i=0;i<buff.shm_segsz;i++){
tmp_data[i] = *ptr++;
}
printf("%s",tmp_data);
shmdt(ptr);
return 0;
}