茱莉亚打电话给我- libc有问题



我运行以下ccall 's:

status = ccall((:ioperm, "libc"), Int32, (Uint, Uint, Int32), 0x378, 5, 1)
ccall((:outb, "libc"), Void, (Uint8, Uint16), 0x00, 0x378)

在第二个ccall之后,我收到以下错误消息:

ERROR: ccall: could not find function outb in library libc
 in anonymous at no file
 in include at ./boot.jl:245
 in include_from_node1 at loading.jl:128
 in process_options at ./client.jl:285

经过一番研究,我发现了以下信息:

  1. ioperm是在线的,但outb不是
  2. 然而,iopermoutb都定义在同一个头文件<sys/io.h>
  3. C代码的等效版本编译并且运行流畅。glibc中的
  4. outb,而在系统中glibc 被定义为 libc
  5. 完整路径名称/lib/x86_64-linux-gnu/libc.so.6
  6. 同样的问题
编辑:

感谢你的洞察力@受雇俄罗斯人!我没有仔细观察,没有意识到extern的声明。现在,我上面所有的笔记都是有意义的!

很好,我们发现iopermlibc函数,在<sys/io.h>中声明,outb不在libc中,但在<sys/io.h>中定义为易失性汇编指令。

我应该使用哪个库或文件路径?

ccall的实现

但是,ioperm和outb都定义在同一个头文件<sys/io.h>

你所说的"定义"实际上是指"声明"。它们是不同的。在我的系统中:

extern int ioperm (unsigned long int __from, unsigned long int __num,
                   int __turn_on) __attribute__ ((__nothrow__ , __leaf__));
static __inline void
outb (unsigned char __value, unsigned short int __port)
{
  __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port));
}

现在可以调用ioperm而不能调用outb的原因应该很明显了。

更新1

我仍然不知道如何纠正这个错误。

不能从libc导入outb。你必须提供你自己的原生库,例如

void my_outb(unsigned char value, unsigned short port) {
  outb(value, port);
}

并从中导入my_outb。为了对称,你可能应该以同样的方式实现my_ioperm,所以你是从同一个本地库导入两个函数。

更新2

使库工作,但就性能而言,它是可怕的。

我猜这就是为什么原来是作为内联函数实现的:你只执行一条outb指令,所以函数调用的开销是显著的。

未优化的python做得更好。

可能是通过将相同的outb指令内联到里面。

你知道它是否存在于其他库中吗?

这是没有将帮助:您仍然会有一个函数调用开销。我猜,当您调用从Julia导入的函数时,您可能会执行dlopendlsym调用,这将额外增加数百条指令的开销。

可能有一种方法可以动态"绑定"函数一次,然后重复使用它来进行调用(从而避免重复dlopendlsym)。这个应该有帮助。

最新更新