Linux共享内存实践(2)

来源:互联网 发布:软件变成英文 编辑:程序博客网 时间:2024/06/09 14:51

shmdt函数

功能:将共享内存段与当前进程脱离

原型:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int shmdt(const void *shmaddr);  

参数:

    shmaddr: 由shmat所返回的指针

 

返回值:

    成功返回0;失败返回-1


[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //实践:运行程序,观察ipcs输出  
  2. int main()  
  3. {  
  4.     //获取或者打开共享内存  
  5.     int shmid = shmget(0x15764221, 1024 * sizeof(int), 0666 | IPC_CREAT);  
  6.     if (shmid == -1)  
  7.     {  
  8.         err_exit("shmget error");  
  9.     }  
  10.   
  11.     //将ID为shmid的共享内存连接到该进程  
  12.     int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));  
  13.     if (pArray == (void *)-1)  
  14.     {  
  15.         err_exit("shmat error");  
  16.     }  
  17.   
  18.     sleep(10);  
  19.   
  20.     //将共享内存从当前进程分离  
  21.     if (shmdt(pArray) == -1)  
  22.     {  
  23.         err_exit("shmdt error");  
  24.     }  
  25.     sleep(10);  
  26.   
  27.     return 0;  
  28. }  

注意:将共享内存段与当前进程脱离不等于删除共享内存段

 

shmctl函数

功能:用于调控/获取共享内存属性

原型:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int shmctl(int shmid, int cmd, struct shmid_ds *buf);  

参数:

    shmid:由shmget返回的共享内存标识码

    cmd:将要采取的动作(三个取值见下)

    buf:指向一个保存着共享内存的模式状态和访问权限的数据结构



返回值:

    成功返回0;失败返回-1

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //示例:detach & delete, 请在多个终端中启动该程序,仔细用ipcs观察,该程序的每一步  
  2. int main()  
  3. {  
  4.     //获取或者打开共享内存  
  5.     int shmid = shmget(0x15764221, 1024 * sizeof(int), 0666 | IPC_CREAT);  
  6.     if (shmid == -1)  
  7.     {  
  8.         err_exit("shmget error");  
  9.     }  
  10.   
  11.     //将ID为shmid的共享内存连接到该进程  
  12.     int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));  
  13.     if (pArray == (void *)-1)  
  14.     {  
  15.         err_exit("shmat error");  
  16.     }  
  17.   
  18.     int choice = 0;  
  19.     cout << "Please input your choice: 0-detach, other-continue: ";  
  20.     cin >> choice;  
  21.     if (choice == 0)  
  22.     {  
  23.         //将共享内存从当前进程分离  
  24.         if (shmdt(pArray) == -1)  
  25.         {  
  26.             err_exit("shmdt error");  
  27.         }  
  28.     }  
  29.   
  30.     //     int shmctl(int shmid, int cmd, struct shmid_ds *buf);  
  31.     cout << "\nPlease input your choice: 0-delete, other-quit: ";  
  32.     cin >> choice;  
  33.     if (choice == 0)  
  34.     {  
  35.         //删除共享内存(shmid的引用计数-1)  
  36.         if (shmctl(shmid,IPC_RMID,NULL) == -1)  
  37.         {  
  38.             err_exit("shmctl error");  
  39.         }  
  40.         else  
  41.         {  
  42.             cout << "Delete Success!" << endl;  
  43.         }  
  44.     }  
  45.   
  46.     return 0;  
  47. }  
  48. /** 
  49.   共享内存在内核中使用了引用计数技术:必须等到连接到该共享内存的数目为0时(等到该共享内存的引用计数变为0),才执行真正的删除该共享内存动作!当引用技术不为0时,调用IPC_RMID时,该共享内存的key会变成0(变为私有的); 
  50. */  

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /**示例:查看在其中一个进程执行删除之后(但此时引用计数还不为0),该共享内存是否可读; 
  2. 执行顺序: 
  3.   writeMemory 
  4.   readMemory 
  5.   writeMemory中,键入0 
  6.   readMemory中,键入0 
  7. */  

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //writeMemory.cpp  
  2. int main()  
  3. {  
  4.     const int NUMBER = 36;  
  5.     int shmid = shmget(0x15764221, NUMBER * sizeof(int), 0666 | IPC_CREAT);  
  6.     if (shmid == -1)  
  7.     {  
  8.         err_exit("shmget error");  
  9.     }  
  10.   
  11.     int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));  
  12.     if (pArray == (void *)-1)  
  13.     {  
  14.         err_exit("shmat error");  
  15.     }  
  16.   
  17.     for (int i = 0; i < NUMBER; ++i)  
  18.     {  
  19.         *(pArray+i) = i+1;  
  20.     }  
  21.   
  22.     int choice = 0;  
  23.     cout << "Please input your choice: 0-delete, other-quit: ";  
  24.     cin >> choice;  
  25.     if (choice == 0)  
  26.     {  
  27.         //删除共享内存(shmid的引用计数-1)  
  28.         if (shmctl(shmid,IPC_RMID,NULL) == -1)  
  29.         {  
  30.             err_exit("shmctl error");  
  31.         }  
  32.         else  
  33.         {  
  34.             cout << "Delete Success!" << endl;  
  35.         }  
  36.     }  
  37.   
  38.     return 0;  
  39. }  

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //2:readMemory.cpp  
  2. int main()  
  3. {  
  4.     const int NUMBER = 36;  
  5.     int shmid = shmget(0x15764221, NUMBER * sizeof(int), 0666);  
  6.     if (shmid == -1)  
  7.     {  
  8.         err_exit("shmget error");  
  9.     }  
  10.   
  11.     int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));  
  12.     if (pArray == (void *)-1)  
  13.     {  
  14.         err_exit("shmat error");  
  15.     }  
  16.   
  17.     int choice = 0;  
  18.     cout << "Please input your Choice: 0-read, other-quit: ";  
  19.     cin >> choice;  
  20.     if (!choice)  
  21.     {  
  22.         for (int i = 0; i < NUMBER; ++i)  
  23.         {  
  24.             cout << *(pArray+i) << "\t";  
  25.         }  
  26.         cout << endl;  
  27.     }  
  28.   
  29.     return 0;  
  30. }  



    由上图可知:即使其中一个进程执行了IPC_RMID(只要该共享内存引用计数不为0),该共享内核还是可读的(但此时必须该读进程是已经连接到该共享内存的,不然的话,写进程虽然没有将共享内存真正的删掉,但是其键值已经变为0x00000000(Private),此时其他进程是连接不上的)!

 

总结:

    1.共享内存被别的程序占用,则删除该共享内存时,不会马上删除

    2.此时会出现一个现象:该共享内存的key变为0x00000000,变为私有

    3.此时还可以读,但必须还有办法获取该共享内存的ID(shmid),因为此时试图通过该共享内存的key获取该共享内存,都是白费的!

0 0
原创粉丝点击