以下几节将讨论系统调用问题。
每次用来从内核向外传递信息的数据结构中的一个或多个字段太小而无法容纳该值时,系统调用中便会返回 EOVERFLOW 返回值。
现在,许多 32 位系统调用在遇到 64 位内核中的大对象时都会返回 EOVERFLOW。在处理大文件时会出现上述情况,由于 daddr_t
、dev_t
、time_t
及其派生类型 struct timeval
和 timespec_t
现在包含 64 位值,因此这可能意味着 32 位应用程序会遇到更多的 EOVERFLOW 返回值。
过去,指定的一些 ioctl(2) 调用非常不当。遗憾的是,ioctl() 完全不执行编译时类型检查,因此,可能难以找到错误的来源。
请考虑使用两个 ioctl() 调用:一个用来处理 32 位值 (IOP32) 的指针,另一个用来处理长值 (IOPLONG) 的指针。
以下代码样例作为 32 位应用程序的一部分来运行:
int a, d; long b; ... if (ioctl(d, IOP32, &b) == -1) return (errno); if (ioctl(d, IOPLONG, &a) == -1) return (errno);
编译此代码段并将其作为 32 位应用程序的一部分运行时,这两个 ioctl(2) 调用均可正常工作。
编译此代码段并将其作为 64 位应用程序的一部分运行时,这两个 ioctl() 调用也将成功返回。但是,这两个 ioctl() 均无法正常工作。第一个 ioctl() 传递的容器太大,并且在大端字节序实现中,内核将从 64 位字的错误部分向外复制数据或向其中复制数据。即使在小端字节序实现中,该容器也可能在高 32 位中包含栈垃圾。第二个 ioctl() 会从字中向外复制或向其中复制过多的数据,从而导致读取错误的值或破坏用户栈上的相邻变量。