采用ftok来生成key的情况下,如果ftok的参数pathname指定文件被删除后重建,则文件系统会赋予这个同名文件(或目录)新的i节点信息,于是这些进程所调用的ftok虽然都能正常返回,但得到的键值却并不能保证相同。
2)3. AIX中shmat的问题
AIX系统中,System V各类进程间通信机制在使用中均存在限制。区别于其它UNIX操作系统对IPC机制的资源配置方式,AIX使用了不同的方法;在AIX中定义了 IPC 机制的上限, 且是不可配置的。就共享内存机制而言,在4.2.1及以上版本的AIX系统上,存在下列限制:
对于64位进程,同一进程可连接最多268435456个共享内存段;
对于32位进程,同一进程可连接最多11个共享内存段,除非使用扩展的shmat;
上述限制对于64位应用不会带来麻烦,因为可供连接的数量已经足够大了;但对于32位应用,却很容易带来意外的问题,因为最大的连接数量只有11个。
下面的例程test02.c演示了这个问题,为了精简代码,它反复连接的是同一个共享内存对象;实际上,无论所连接的共享内存对象是否相同,该限制制约的是连接次数:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define MAX_ATTACH_NUM 15
void main(int argc, char* argv[])
{
key_t mem_key;
long mem_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=%d\n",
errno);
goto MOD_EXIT;
}
if ( ( mem_id = shmget(mem_key, 256, IPC_CREAT) ) == (-1) ) {
printf("Failed to obtain shared memory ID, ERRNO=%d\n", 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 [%02d], errno:%d\n", i,
errno);
else
printf("Successfully attached shared memory, times [%02d]\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]
Successfully attached shared memory, times [04]
Successfully attached shared memory, times [05]
Successfully attached shared memory, times [06]
Successfully attached shared memory, times [07]
Successfully attached shared memory, times [08]
Successfully attached shared memory, times [09]
Successfully attached shared memory, times [10]
Successfully attached shared memory, times [11]
Failed to attach shared memory, times [12], errno:24
Failed to attach shared memory, times [13], errno:24
Failed to attach shared memory, times [14], errno:24
Failed to attach shared memory, times [15], errno:24
说明超出11个连接之后,所有后续的共享内存连接都将无法建立。错误码24的定义是EMFILE,AIX给予的解释是:
The number of shared memory segments attached to the calling process exceeds the system-imposed limit。
解决这个问题的方法是,使用扩展的shmat;具体而言就是,在运行相关应用之前(确切地说,是在共享内存被创建之前),首先在shell中设置EXTSHM环境变量,通过它扩展shmat,对于源代码本身无需作任何修改:
export EXTSHM=ON
值得注意的是,虽然设置环境变量,在程序中也可通过setenv函数来做到,比如在程序的开始,加入下列代码:
setenv("EXTSHM", "ON", 1);
但实践证明这样的方法在解决这个问题上是无效的;也就是说唯一可行的办法,就是在shell中设置EXTSHM环境变量,而非在程序中。
在AIX上配置32位DB2实例时,也要求确保将环境变量 EXTSHM 设为 ON,这是运行 Warehouse Manager 和 Query Patroller 之前必需的操作:
export EXTSHM=ON
db2set DB2ENVLIST=EXTSHM
db2start
其原因即来自我们刚刚介绍的AIX中32位应用连接共享内存时,存在最大连接数限制。这个问题同样普遍存在于AIX平台上Oracle等软件产品中。
3)HP-UX中shmget和shmat的问题
3.1 32位和64位应用兼容问题
在HP-UX平台上,如果同时运行32位应用和64位应用,而且它们访问的是一个相同的共享内存区,则会遇到兼容性问题。
在HP-UX中,应用程序设置IPC_CREAT标志调用shmget,所创建的共享内存区,只可被同类型的应用所访问;即32位应用程序所创建的共享内存区只可被其它的32位应用程序访问,同样地,64位应用程序所创建的共享内存区只可被其它的64位应用程序访问。
如果,32位应用企图访问一个由64位应用创建的共享内存区,则会在调用shmget时失败,得到EINVAL错误码,其解释是:
A shared memory identifier exists for key but is in 64-bit address space and the process performing the request has been compiled as a 32-bit executable.
解决这一问题的方法是,当64位应用创建共享内存时,合并IPC_CREAT标志,同时给定IPC_SHARE32标志:
shmget(mem_key, size, 0666 | IPC_CREAT | IPC_SHARE32)
对于32位应用,没有设定IPC_SHARE32标志的要求,但设置该标志并不会带来任何问题,也就是说无论应用程序将被编译为32位还是64位模式,都可采用如上相同的代码;并且由此解决32位应用和64位应用在共享内存访问上的兼容性问题。