6

Here's the template I use for wrapping a function using LD_PRELOAD:

int gettimeofday(struct timeval *tv, struct timezone *tz) {
  static int (*gettimeofday_real)(struct timeval *tv, struct timezone *tz)=NULL;
  if (!gettimeofday_real) gettimeofday_real=dlsym(RTLD_NEXT,"gettimeofday");
  return gettimeofday_real(tv, tz);
}

I realized though that ioctl seems to have the following signature:

   int ioctl(int d, unsigned long request, ...);

How could I wrap it in a similar way, given the ... that's in the signature?

4

2 回答 2

7

尽管 John Bollinger 是正确的,因为根据它的原型,ioctl.h,ioctl()是一个可变参数函数,但实际上并非如此。

参见例如Linux Device Drivers一书中的这句话

由于点,原型在 Unix 系统调用列表中脱颖而出,这些点通常将函数标记为具有可变数量的参数。然而,在实际系统中,系统调用实际上不能有可变数量的参数。系统调用必须有明确定义的原型,因为用户程序只能通过硬件“门”访问它们。因此,原型中的点表示的不是可变数量的参数,而是单个可选参数,传统上标识为 char *argp。这些点只是为了防止编译期间的类型检查。

所以你可以写你的替代品ioctl()如下:

int ioctl(int d, unsigned long request, char *argp)
{
  /* follow the same recipe as for your example gettimeofday() */
  return ioctl_real(d, request, argp);
}

如果您只想构建一个与 一起使用的包装器库,那么您的签名与 in 的签名相矛盾的LD_PRELOAD事实是无关紧要的:链接器不检查类型,并且您的包装器库的假货将使用与真实的完全相同的参数调用没有ioctlsys/ioctl.hioctlLD_PRELOAD

于 2015-02-12T00:08:12.080 回答
1

一个可变参数函数没有可移植的方法将其可变参数转发给另一个可变参数函数。部分原因是编译器必须在编译时知道实际参数的数量和大小才能构造可变参数调用,但它们在被调用函数内部不是静态已知的(甚至不是以参数方式)。

于 2015-02-11T19:41:17.723 回答