共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
进程1映射到该共享内存区域后,就可以通过映射之后得到的首地址p1,直接对那一片共享内存区域进行操作;
进程2映射到同一块内存区域后,也可以得到映射之后的那一片共享内存的首地址p2,通过p2可以直接对那一片共享内存区域进行操作;
1:创建共享内存
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);key:这个共享内存段名字,可以自己指定,也可以通过ftok函数来生成一个随机的key
#include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id);//随机产生key值
#include <sys/types.h> #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg);shmid: 共享内存标识,就是函数shmget的返回值
#include <sys/types.h> #include <sys/shm.h> int shmdt(const void *shmaddr);shmaddr: 由shmat所返回的指针
4:用于控制共享内存
#include <sys/ipc.h> #include <sys/shm.h> int 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 */ ... }; The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET): 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 and SHM_LOCKED flags */ unsigned short __seq; /* Sequence number */ };
write_shm.cpp
/************************************************************************* > File Name: write_shm.cpp > Author: > Mail: > Created Time: 2015年12月21日 星期一 11时15分23秒 ************************************************************************/ #include <iostream> #include <cstdlib> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #include <string.h> #include <sys/types.h> using namespace std; /* 1: 创建一块共享内存 2:连接到共享内存,并向共享内存中写入数据 3:脱离该共享内存区域 */ #define SHMSIZE 1024 int main(int argc, char *argv[]) { /* if(argc < 2){ cout << "input the pathname fo generate key..."<< endl; exit(-1); }*/ key_t key = 0x1111;//ftok(argv[1], 'a'); int shmid = shmget(key, SHMSIZE, 0666|IPC_CREAT); if(shmid == -1){ cerr << "shmget error ...." << endl; exit(-1); } char * p = (char *)shmat(shmid, NULL, 0); pid_t pid = getpid(); cout << "process " << pid << " write: "; while(cin.getline(p, SHMSIZE)){ if(strcmp(p, "over") == 0){ break; } cout << "process " << pid << " write: "; } //脱离该共享内存区域,并删除该共享内存区域 shmdt(p); shmctl(shmid, IPC_RMID, NULL); cout << "已经删除了共享内存,并退出。\n"; exit(0); }
/************************************************************************* > File Name: read_shm.cpp > Author: > Mail: > Created Time: 2015年12月21日 星期一 11时15分23秒 ************************************************************************/ #include <iostream> #include <cstdlib> #include <sys/ipc.h> #include <string.h> #include <sys/shm.h> #include <unistd.h> #include <sys/types.h> using namespace std; /* 连接到共享内存,并向共享内存中读入数据 脱离该共享内存区域 */ #define SHMSIZE 1024 int main(int argc, char *argv[]) { key_t key = 0x1111; //当共享内存中有数据的时候它才会立刻返回,否则该函数会阻塞在这里 int shmid = shmget(key, SHMSIZE, 0666); if(shmid == -1){ cerr << "shmget error ...." << endl; exit(-1); } pid_t pid = getpid(); char * p = (char *)shmat(shmid, NULL, 0); cout << "process " << pid << " read: "; while(1){ if(strlen(p) != 0) cout << p << endl; else continue; if(strcmp(p, "over") == 0){ break; } cout << "process " << pid << " read: "; memset(p, 0, SHMSIZE); } cout << "进程退出。\n"; exit(0); }