Linux共享内存实践(1)

共享内存基本概念

    共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据(如图)。

 

 

共享内存 VS. 其他IPC形式

    用管道/消息队列传递数据

 

 

 

    用共享内存传递数据

 


(内核为每个IPC对象维护一个数据结构)

    共享内存生成之后,传递数据并不需要再走Linux内核,共享内存允许两个或多个进程共享一个给定的存储区域,数据并不需要在多个进程之间进行复制,因此,共享内存的传输速度更快!!

 

System V共享内存数据结构与基本API

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //基本数据结构  
  2. struct shmid_ds  
  3. {  
  4.     struct ipc_perm shm_perm;    /* Ownership and permissions */  
  5.     size_t          shm_segsz;   /* Size of segment (bytes) */  
  6.     time_t          shm_atime;   /* Last attach time */  
  7.     time_t          shm_dtime;   /* Last detach time */  
  8.     time_t          shm_ctime;   /* Last change time */  
  9.     pid_t           shm_cpid;    /* PID of creator */  
  10.     pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */  
  11.     shmatt_t        shm_nattch;  /* No. of current attaches */  
  12.     ...  
  13. };  

共享内存函数 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <sys/ipc.h>  
  2.   
  3. #include <sys/shm.h>  
  4.   
  5. int shmget(key_t key, size_t size, int shmflg);  
  6.   
  7. void *shmat(int shmid, const void *shmaddr, int shmflg);  
  8.   
  9. int shmdt(const void *shmaddr);  
  10.   
  11. int shmctl(int shmid, int cmd, struct shmid_ds *buf);  

 

shmget函数

功能:创建共享内存,并将该内存的内容初始化为0

原型:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Courier New;">int shmget(key_t key, size_t size, int shmflg);</span>  

参数:

    key:这个共享内存段名字

    size:共享内存大小

    shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的

 

返回值:

    成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //实验1:打开已经存在的共享内存  
  2. int main()  
  3. {  
  4.   // int shmget(key_t key, size_t size, int shmflg);  
  5.   //打开已经存在的共享内存  
  6.     int shmid = shmget(0x225,1024,0666);  
  7.     if (shmid == -1)  
  8.     {  
  9.         if (errno == ENOENT)  
  10.         {  
  11.             cout << "ENOENT = " << errno << endl;  
  12.         }  
  13.         err_exit("shmget error");  
  14.     }  
  15.     return 0;  
  16. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //实验2:共享内存如若存在,则直接使用;若不存在,则创建. [IPC_CREAT选项作用]  
  2. int main()  
  3. {  
  4.     // int shmget(key_t key, size_t size, int shmflg);  
  5.     int shmid = shmget(0x225,1024,0666|IPC_CREAT);  
  6.     if (shmid == -1)  
  7.     {  
  8.         if (errno == ENOENT)  
  9.         {  
  10.             cout << "ENOENT = " << errno << endl;  
  11.         }  
  12.         err_exit("shmget error");  
  13.     }  
  14.     else  
  15.     {  
  16.         cout << "shmid = " << shmid << endl;  
  17.     }  
  18.     return 0;  
  19. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //实验3:共享内存如果没有,则创建;如果存在,则返回错误. [IPC_CREAT|IPC_EXCL组合作用]  
  2. int main()  
  3. {  
  4.     // int shmget(key_t key, size_t size, int shmflg);  
  5.     int shmid = shmget(0x225,1024,0666|IPC_CREAT|IPC_EXCL);  
  6.     if (shmid == -1)  
  7.     {  
  8.         if (errno == ENOENT)  
  9.         {  
  10.             cout << "ENOENT = " << errno << endl;  
  11.         }  
  12.         else if (errno == EEXIST)  
  13.         {  
  14.             cout << "File is exits... EEXIST = " << errno << endl;  
  15.         }  
  16.         err_exit("shmget error");  
  17.     }  
  18.     else  
  19.     {  
  20.         cout << "shmid = " << shmid << endl;  
  21.     }  
  22.     return 0;  
  23. }  

 

 

shmat函数

功能:将共享内存段连接到进程地址空间

原型:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void *shmat(int shmid, const void *shmaddr, int shmflg);  

参数:

    shmid: 共享内存标识

    shmaddr:指定连接的地址

    shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

 

返回值:

    成功返回一个指针,指向共享内存第一个节;失败返回-1

 

Shmaddr与shmflg组合说明

    shmaddr为NULL,Linux内和将自动为进程连接到该内存(推荐使用)

    shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。

    shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)

    shmflg=SHM_RDONLY,表示连接操作用来只读共享内存


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //示例1  
  2. int main()  
  3. {  
  4.     // int shmget(key_t key, size_t size, int shmflg);  
  5.     //获取或者打开共享内存  
  6.     int shmid = shmget(0x1576422, sizeof(Student), 0666 | IPC_CREAT);  
  7.     if (shmid == -1)  
  8.     {  
  9.         err_exit("shmget error");  
  10.     }  
  11.   
  12.     //将ID为shmid的共享内存连接到该进程  
  13.     Student *pStudent = static_cast<Student *>(shmat(shmid, NULL, 0));  
  14.     //向内存中写入数据  
  15.     Student studentA = {"xiaofang",2012};  
  16.     memcpy(pStudent,&studentA,sizeof(Student));  
  17.   
  18.     cout << pStudent ->name << " " << pStudent ->number << endl;  
  19.   
  20.     //亦可获取该内存内容(其实跟本地内存没有什么区别)  
  21.     Student *pNewStudent = pStudent;  
  22.     cout << pNewStudent -> name << " " << pNewStudent -> number << endl;  
  23.   
  24.     return 0;  
  25. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //示例2:将共享内存当成数组  
  2. int main()  
  3. {  
  4.     // int shmget(key_t key, size_t size, int shmflg);  
  5.     //获取或者打开共享内存  
  6.     int shmid = shmget(0x15764221, 1024 * sizeof(int), 0666 | IPC_CREAT);  
  7.     if (shmid == -1)  
  8.     {  
  9.         err_exit("shmget error");  
  10.     }  
  11.   
  12.     //将ID为shmid的共享内存连接到该进程  
  13.     int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));  
  14.     if (pArray == (void *)-1)  
  15.     {  
  16.         err_exit("shmat error");  
  17.     }  
  18.   
  19.     for (int i = 0; i != 1024; ++i)  
  20.     {  
  21.         pArray[i] = i+1;  
  22.     }  
  23.   
  24.     for (int i = 0; i != 1024; ++i)  
  25.     {  
  26.         cout << pArray[i] << endl;  
  27.     }  
  28.   
  29.     return 0;  
  30. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值