#include
#include
#include
key_t ftok(const char *pathname, int proj_id);
int shmget(key_t key, int size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
ftok(const char *pathname, int proj_id);用于创建一个关键字,可以用此key关联一个共享内存段shmget(key_t key, int size, int shmflg);用于创建或打开一共享内存段,该内存段由函数的第一个参数唯一创建。*shmat(int shmid, const void *shmaddr, int shmflg);将共享内存段映射到进程空间的某一地址。shmdt(const void *shmaddr);用于将共享内存段与进程空间分离。shmctl(int shmid, int cmd, struct shmid_ds *buf是共享内存的控制函数,可以用来删除共享内存段。struct shmid_ds {struct ipc_perm shm_perm; /* Ownership and permissions */size_t shm_segsz; /* Size of segment (bytes) */time_t shm_atime; /* Last attach time */time_t shm_dtime; /* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid; /* PID of creator */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* No. of current attaches */...
};
struct ipc_perm {key_t __key; /* Key supplied to shmget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions + SHM_DEST andSHM_LOCKED flags */unsigned short __seq; /* Sequence number */
};
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PERM S_IRUSR | S_IWUSR //表示用户可读可写 即 0600int main(int argc,char** argv)
{int shmid = shmget(IPC_PRIVATE,1024,PERM);//只有IPC_PRIVATE情况可以不设置IPC_CREAT,让操作系统来开辟空间if(shmid == -1) {//如果返回的共享内存标识号不为-1,即创建共享内存失败,错误处理fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));exit(1);} if(fork() > 0){ //父进程代码char *p_addr = (char*)shmat(shmid,NULL,0); //将共享内存段地址映射到父进程的进程空间中memset(p_addr,'\0',1024); //设置这段地址空间初始化为0strncpy(p_addr,"share memory", 1024);//将字符串写入内存printf("父进程id:%d,写入缓冲区:%s\n",getpid(),p_addr);sleep(2);wait(NULL); //处理结束的进程,防止僵尸进程shmctl(shmid,IPC_RMID,0);//通过唯一的共享内存标识号,删除共享内存exit(0);}else{ //子进程代码sleep(5); //给父进程留足写数据的时间char* c_addr = (char*)shmat(shmid,NULL,0); //将共享内存段地址映射到子进程的进程空间中,可以读取其中内容printf("子进程id:%d,进程标识号:%d 读缓冲区内容: %s\n",getpid(),shmid,c_addr);exit(0);}return 0;
}
运行结果:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#includeint main()
{key_t key = ftok("./file1",1); //1 写端使用ftok函数获取此文件的唯一关键字if(key == -1){ //获取失败的处理perror("fotk");exit(-1);}int shmid = shmget(key,512,IPC_CREAT|0666); //2 按照key创建512B大小的共享内存段,返回该共享内存段的标识符if(shmid == -1){ //创建失败的处理perror("shmget");exit(-1);}char *pMap = (char *)shmat(shmid,NULL,0); //3 获得共享内存段的首地址memset(pMap,'\0',512);strcpy(pMap,"hello world"); //4 想共享内存段中写入内容if(shmdt(pMap) == -1){ //5 关闭共享内存段perror("shmdt");exit(-1);} return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{key_t key = ftok("./file1",1); //1 读端使用ftok函数获取此文件的唯一关键字if(key == -1){ //获取失败的处理perror("fotk");exit(-1);}int shmid = shmget(key,512,0666|IPC_CREAT); //2 按照key创建4096大小的共享内存段,权限设可读,返回该共享内存段的标识符if(shmid == -1){ //创建失败的处理perror("shmid");exit(-1);}char* pMap = shmat(shmid,NULL,0); //3 获取共享内存段的首地址printf("读到的内容:%s\n",pMap); //4 读取共享内存段的内容if(shmctl(shmid,IPC_RMID,0) == -1){ //5 删除共享内存段,注意和shmdt作区分 perror("shmctl");exit(-1);}return 0;
}
**注意:**如果运行时出错,再运行会出现“错误的参数”、“段错误”等,需要检查共享内存段是否关闭了,可以按如下操作,有可能会出现程序创建了共享内存段,然后没删除的情况,导致想再次运行报错。

再次运行调试就ok了

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct text
{int useful; //是否可用的标志char buf[1024];
};int main()
{int shmid = shmget((key_t)5080,sizeof(struct text),0600|IPC_CREAT);//创建唯一key,大小为text的共享内存段,返回唯一内存标识号if(shmid == -1){ //创建失败的处理perror("shmget");exit(-1);}struct text* ptext = (struct text*)shmat(shmid,NULL,0);//获得shmid共享内存段的首地址ptext->useful = 0;while(1){if(ptext->useful == 0){ //判断此内存段是否被用int iret = read(STDIN_FILENO,ptext->buf,1024); //从标准输入到buf缓冲中,如果read函数不输入会阻塞ptext->useful = 1; //将缓冲区改为占用状态if(strncmp("end",ptext->buf,3) == 0){ //如果输入的end,则结束break;}ptext->useful = 0; //将缓冲区改为未占用状态,新一次传输}sleep(1);}shmdt((void*)ptext); //将此进程和共享内存段分离return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct text
{int useful; //是否可用的标志char buf[1024];
};int main()
{int shmid = shmget((key_t)5080,sizeof(struct text),0600|IPC_CREAT);//创建唯一key,大小为text的共享内存段,返回唯一内存标识号if(shmid == -1){ //创建失败的处理perror("shmget");exit(-1);}struct text* ptext = (struct text*)shmat(shmid,NULL,0);//获得shmid共享内存段的首地址ptext->useful = 0;while(1){if(ptext->useful == 1){write(STDOUT_FILENO,ptext->buf,strlen(ptext->buf));//将缓冲区中的内容打印到标准输出窗口中,如果没有内容write会阻塞ptext->useful = 0;if(strncmp("end",ptext->buf,3) == 0){ //输入end退出循环break;}}sleep(1);}shmdt((void*)ptext); //将此进程和共享内存段分离shmctl(shmid,IPC_RMID,0); //清除该进程空间return 0;
}
演示结果,读者结合代码自行体会,end覆盖了内存空间的起始字符,如何修改可以不覆盖呢?

上一篇:Nginx服务优化与防盗链
下一篇:STL中的函数对象