linuc IPC 之共享内存

1.原理及实现:system V IPC 机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。

 
2.
1 #include <sys/types.h>
2 #include <sys/ipc.h> 
3 #include <sys/shm.h>
 
   1 key_t ftok(const char *pathname,int proj_id);
用于创建一个关键字,可以用该关键字关联一个共享内存段。
参数 pathname 为一个全路径文件名,并且该文件必须可访问。
参数 proj_id 通常传入一非 0 字符
通过 pathname 和 proj_id 组合可以创建唯一的 key
如果调用成功,返回一关键字,否则返回-1
1 #include<func.h>
2 int main(int argc,char *argv[])
3 {
4 ARGC_CHECK(argc,2);
5 key_t key;
6 key=ftok(argv[1],1);
7 printf   key
8 return 0;
9 }
 
 
以下四个函数都是系统调用
  1 int shmget(key_t key,int size,int shmflg); 
用于创建或打开一共享内存段,该内存段由函数的第一个参数唯一创建。函数成功,则返回一个唯一的共享内存标识号(相当于进程号,唯一的标识着共享内存),失败返回-1。
参数 shmflg 是一掩码合成值,可以是访问权限值与(IPC_CREAT 或 IPC_EXCL)的合成。IPC_CREAT 表示如果不存在该内存段,则创建它。IPC_EXCL 表示如果该内存段存在,则函数返回失败结果(-1)。如果调用成功,返回内存段标识,否则返回-1。
1 int shmid;//4k的整数倍 
2 shmid=shmget(1000,4094,0600|IPC_CREAT); 
3 ERROR_CHECK();
 
 
  1 void *shmat(int shmid,const void *shmaddr,int shmflg); 
将共享内存段映射到进程空间的某一地址。
参数 shmid 是共享内存段的标识 通常应该是 shmget 的成功返回值
参数 shmaddr 指定的是共享内存连接到当前进程中的地址位置。通常是 NULL,表示让系统来选择共享内存出现的地址。
参数 shmflg 是一组位标识,通常为 0 即可。
如果调用成功,返回映射后的进程空间的首地址,否则返回(char *)-1。
不能偏移
 1 int shmid=shmget(1000,4094,0600|IPC_CREAT);
 2 ERROR_CHECK();
 3 //先链接在fork,进程地址空间起始地址相同,先fork在链接,可能会不同
 4 int *p=(int *)shmat(shmid,NULL,0);//创建共享内存时设定好了,所以填0
 5 if(!fork()))
 6 {
 7     printf("i am child p[0]=%d\n",p[0]);
 8 }
 9 else
10 {
11     p[0]=100;
12     wait(NULL);
13     return 0;
14 }
15 //使用另外一个没有血缘关系的进程链接共享内存,也可以得到100 
 
加1000万:
 1 int main()
 2 {
 3     int shmid = shmget(1000, 4096, 0666 | IPC_CREAT);
 4     ERROR_CHECK(shmid, -1, "shmget");
 5     int *p = (int *)shmat(shmid, NULL, 0);
 6     int i;
 7     * p = 0;
 8     if (!fork())
 9     {
10         for (i = 0; i<10000000; i++)
11         {
12             * p += 1;
13         }
14         return 0;
15      }
16     else
17     {
18         for (i = 0; i<10000000; i++)
19         {
20             * p += 1;
21          }
22         wait(NULL);
23         printf("sum=%d\n", *p);
24         return 0;
25     }
26 }
结果小于等于2000万的随机数
并发 从内存写到寄存器,再从寄存器写到内存不是原子操作。
 
 
并发:两个或者两个以上继承操作同一个资源
并行:A进程写A文件,B进程写B进程
 
  1 int shmdt(const void *shmaddr); 
用于将共享内存段与进程空间分离。
参数 shmaddr 通常为 shmat 的成功返回值。
函数成功返回 0,失败时返回-1.注意,将共享内存分离并没删除它,只是使得该共享内存对当前进程不在可用。
 
  1 int shmctl(int shmid,int cmd,struct shmid_ds *buf); 
是共享内存的控制函数,可以用来删除共享内存段。
参数 shmid 是共享内存段标识 通常应该是 shmget 的成功返回值
参数 cmd 是对共享内存段的操作方式,可选为 IPC_STAT,IPC_SET,IPC_RMID。通常为 IPC_RMID,表示删除共享内存段。
有进程连接,执行返回 0,标记删除成功,但是最后一个进程解除连接后,共享内存真正被删除。
有人链接共享内存时,删除时无法删除,statue dest。标记删除。。最后一个进程解除链接时删除。标记删除只成功不失败。
 
  1 int ret=shmctl(shmid,IPC_STAT,&buf);//这里存在结构体时,自己定义的,优先使用栈空间 

猜你喜欢

转载自www.cnblogs.com/stumn/p/11032323.html