c - 如何使用 LD_PRELOAD 包装 ioctl(int d, unsigned long request, ...)?

标签 c linux system-calls ld-preload

这是我使用 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);
}

我意识到 ioctl 似乎具有以下签名:

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

鉴于签名中的 ...,我如何以类似的方式包装它?

最佳答案

虽然 John Bollinger 是正确的,根据其在 ioctl.h 中的原型(prototype),ioctl() 是一个可变参数函数,但实际上并非如此。

参见例如 this quote来自书Linux Device Drivers

The prototype stands out in the list of Unix system calls because of the dots, which usually mark the function as having a variable number of arguments. In a real system, however, a system call can't actually have a variable number of arguments. System calls must have a well-defined prototype, because user programs can access them only through hardware "gates." Therefore, the dots in the prototype represent not a variable number of arguments but a single optional argument, traditionally identified as char *argp. The dots are simply there to prevent type checking during compilation.

所以你可以写你的 susbtitute 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);
}

如果您只是想构建一个用于 LD_PRELOAD 的包装器库,那么您的 ioctl 签名与 sys/ioctl.h< 中的签名相矛盾这一事实 是无关紧要的:链接器不检查类型,你的包装器库的假 ioctl 将使用与没有 LD_PRELOAD

关于c - 如何使用 LD_PRELOAD 包装 ioctl(int d, unsigned long request, ...)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28462523/

相关文章:

linux - 如何使用克隆系统调用分配新的 TLS 区域

c - ANSI C 和函数重载

c - 结构指针错误

linux - 使用teamviewer从Windows访问Linux系统?

linux - 无法使用已编译的 php (ubuntu 12) 连接到 mysql ssl

linux - 将 Docker 镜像从 Azure 容器注册表部署到 Web 应用程序容器 "failed to register layer: Error processing tar file(exit status 1)"

c - 如何从指针读取 64 位到 8 位值

c - 将数组作为函数参数传递 c

linux - 当程序打开特定文件时 gdb 中断

linux - 如何检查信号处理程序是否进行了系统调用?