UNIX 共享内存应用中的问题及解决方法( 二 )


Linux没有提供类似的明确声明,但我们可以通过下面的简单例程test01.c,得到相同的印证:
#include
#include
void main(int argc, char* argv[])
{
if (argc !=2 ) {
printf("Usage: %s KeyFilen e.g. %s /tmp/mykeyfilen", argv[0], argv[0]);
return;
}
printf("Key generated by ftok: 0x%xn", ftok(argv[1], 1));
}
将上述例程在Red Hat Enterprise Linux AS release 4平台上编程成可执行程序test01,并且通过touch命令在 /tmp目录下创建一个新文件mykeyfile,然后为该文件生成键值:
# touch /tmp/mykeyfile
# ./test01 /tmp/mykeyfile
Key generated by ftok: 0x101000b
然后,将/tmp/mykeyfile删除,并且通过vi命令重新创建该文件,再次生成键值:
# ./test01 /tmp/mykeyfile
Key generated by ftok: 0x1010017
我们可以看到,虽然文件名称都是 /tmp/mykeyfile,并未改变,但由于中间发生了文件删除并重新创建的操作,前后两次所得到的键值已经不再相同 。
避免此类问题最根本的方法,就是采取措施保证pathname所指定的文件(或目录)在共享内存的使用期间不被删除,不要使用有可能被删除的文件;或者干脆直接指定键值,而不借助ftok来获取键值 。
3. AIX中shmat的问题
【UNIX 共享内存应用中的问题及解决方法】AIX系统中,System V各类进程间通信机制在使用中均存在限制 。区别于其它UNIX操作系统对IPC机制的资源配置方式,AIX使用了不同的方法;在AIX中定义了 IPC 机制的上限, 且是不可配置的 。就共享内存机制而言,在4.2.1及以上版本的AIX系统上,存在下列限制:
对于64位进程,同一进程可连接最多268435456个共享内存段;
对于32位进程,同一进程可连接最多11个共享内存段,除非使用扩展的shmat;
上述限制对于64位应用不会带来麻烦,因为可供连接的数量已经足够大了;但对于32位应用,却很容易带来意外的问题,因为最大的连接数量只有11个 。在某些事件触发的多线程应用中,新的线程不断地为进行事件处理而被创建,这些线程如果都需要去连接特定的共享内存,则极有可能造成该进程连接的共享内存数量超过11个,事实上同时拥有几十个甚至上百个处理线程的应用并不少见 。一旦超个这个限制值,则所有后续的处理线程都将无法正常工作,从而导致应用运行失败 。
下面的例程test02.c演示了这个问题,为了精简代码,它反复连接的是同一个共享内存对象;实际上,无论所连接的共享内存对象是否相同,该限制制约的是连接次数:
#include
#include
#include
#include
#include
#define MAX_ATTACH_NUM 15
void main(int argc, char* argv[])
{
key_tmem_key;
longmem_id;
void*mem_addr[MAX_ATTACH_NUM];
int i;
if ( ( mem_key = ftok("/tmp/mykeyfile", 1) ) == (key_t)(-1) ) {
printf("Failed to generate shared memory access key, ERRNO=%dn",
errno);
goto MOD_EXIT;
}
if ( ( mem_id = shmget(mem_key, 256, IPC_CREAT) ) == (-1) ) {
printf("Failed to obtain shared memory ID, ERRNO=%dn", errno);
goto MOD_EXIT;
}
for ( i=1; i<=MAX_ATTACH_NUM; i) {
if ( ( mem_addr[i] = (void *)shmat(mem_id, 0, 0) ) == (void *)(-1) )
printf("Failed to attach shared memory, times [d], errno:%dn", i,
errno);
else
printf("Successfully attached shared memory, times [d]n", i);
}
MOD_EXIT:
shmctl(mem_id, IPC_RMID, NULL);
}
在AIX系统上,我们将其编译为test02,并运行,可以看到如下输出:
Successfully attached shared memory, times [01]
Successfully attached shared memory, times [02]
Successfully attached shared memory, times [03]

推荐阅读