共享内存应用中的问题及解决方法
来源:互联网 发布:java增删改查实例项目 编辑:程序博客网 时间:2024/06/09 15:23
System V 进程间通信(IPC)包括3种机制:消息队列、信号量、共享内存。消息队列和信号量均是内核空间的系统对象,经由它们的数据需要在内核和用户空间进行额外的数据拷贝;而共享内存和访问它的所有应用程序均同处于用户空间,应用进程可以通过地址映射的方式直接读写内存,从而获得非常高的通信效率。
System V 为共享内存定义了下列API接口函数:
# include <sys/types.h># include <sys/ipc.h># include <sys/shm.h>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(void *shmaddr);int shmctl(int shmid, int cmd, struct shmid_ds *buf);ftok 函数用于生成一个键值:key_t key,该键值将作为共享内存对象的唯一性标识符,并提供给为shmget函数作为其输入参数;ftok 函数的输入参数包括一个文件(或目录)路径名:pathname,以及一个额外的数字:proj_id,其中pathname所指定的文件(或目录)要求必须已经存在,且proj_id不可为0; shmget 函数用于创建(或者获取)一个由key键值指定的共享内存对象,返回该对象的系统标识符:shmid; shmat 函数用于建立调用进程与由标识符shmid指定的共享内存对象之间的连接; shmdt 函数用于断开调用进程与共享内存对象之间的连接; shmctl 函数用于对已创建的共享内存对象进行查询、设值、删除等操作;
2. ftok的陷阱
根据pathname指定的文件(或目录)名称,以及proj_id参数指定的数字,ftok函数为IPC对象生成一个唯一性的键值。在实际应用中,很容易产生的一个理解是,在proj_id相同的情况下,只要文件(或目录)名称不变,就可以确保ftok返回始终一致的键值。然而,这个理解并非完全正确,有可能给应用开发埋下很隐晦的陷阱。因为ftok的实现存在这样的风险,即在访问同一共享内存的多个进程先后调用ftok函数的时间段中,如果pathname指定的文件(或目录)被删除且重新创建,则文件系统会赋予这个同名文件(或目录)新的i节点信息,于是这些进程所调用的ftok虽然都能正常返回,但得到的键值却并不能保证相同。由此可能造成的后果是,原本这些进程意图访问一个相同的共享内存对象,然而由于它们各自得到的键值不同,实际上进程指向的共享内存不再一致;如果这些共享内存都得到创建,则在整个应用运行的过程中表面上不会报出任何错误,然而通过一个共享内存对象进行数据传输的目的将无法实现。
AIX、Solaris、HP-UX均明确指出,key文件被删除并重建后,不保证通过ftok得到的键值不变,比如AIX上ftok的man帮助信息即声明:
Attention: If the Path parameter of the ftok subroutine names a file that has been removed while keys still refer to it, the ftok subroutine returns an error. If that file is then re-created, the ftok subroutine will probably return a key different from the original one.
Linux没有提供类似的明确声明,但我们可以通过下面的简单例程test01.c,得到相同的印证:
#include <stdio.h>#include <sys/ipc.h>void main(int argc, char* argv[]){if (argc !=2 ) {printf("Usage: %s KeyFile/n e.g. %s /tmp/mykeyfile/n", argv[0], argv[0]);return;}printf("Key generated by ftok: 0x%x/n", ftok(argv[1], 1));}
将上述例程在Red Hat Enterprise Linux AS release 4平台上编程成可执行程序test01,并且通过touch命令在 /tmp目录下创建一个新文件mykeyfile,然后为该文件生成键值:
# touch /tmp/mykeyfile# ./test01 /tmp/mykeyfileKey generated by ftok: 0x101000b
然后,将/tmp/mykeyfile删除,并且通过vi命令重新创建该文件,再次生成键值:
# ./test01 /tmp/mykeyfileKey generated by ftok: 0x1010017
我们可以看到,虽然文件名称都是 /tmp/mykeyfile,并未改变,但由于中间发生了文件删除并重新创建的操作,前后两次所得到的键值已经不再相同。
避免此类问题最根本的方法,就是采取措施保证pathname所指定的文件(或目录)在共享内存的使用期间不被删除,不要使用有可能被删除的文件;或者干脆直接指定键值,而不借助ftok来获取键值。
- 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- UNIX 共享内存应用中的问题及解决方法
- 网上邻居共享问题及解决方法
- ubuntu apt-get dpkg应用中的一些问题及解决方法
- ubuntu apt-get dpkg应用中的一些问题及解决方法
- yourphp应用过程中的一些问题及解决方法
- ubuntu apt-get dpkg应用中的一些问题及解决方法
- 总结yourphp应用过程中的一些问题及解决方法
- ubuntu apt-get dpkg应用中的一些问题及解决方法
- Linux共享内存使用中的问题
- 虚拟机中的问题及解决方法
- C++内存越界问题及解决方法
- C++内存越界问题及解决方法
- 如何使Struts的本地信息文件ApplicationResources.properties支持中文
- java不是天生低能
- 去掉字符串空格
- UNIX 共享内存应用中的问题及解决方法
- NFS ( Network FileSystem ) (转)
- 共享内存应用中的问题及解决方法
- JSTL语法及参数
- OpenAjax,WPF,Apollo激战RIA
- 《C#入门经典》学习笔记(集合、比较和转换)
- 《C#入门经典》学习笔记(其他OOP技术)
- java与模式笔记(6.3) 缤纷的模式世界之工厂模式——现实中的实例
- 《C#入门经典》学习笔记(Web 编程基础)
- 研究生课程教给我什么?
- JAVA程序员面试32问