【问题标题】:Julia ccall outb - Problems with libcJulia ccall outb - libc 的问题
【发布时间】:2015-08-13 01:14:45
【问题描述】:

我运行以下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 在 libc 中,但 outb 不在
  2. 但是,iopermoutb 都在同一个头文件 <sys/io.h> 中定义
  3. 等效版本的 C 代码编译并顺利运行。
  4. outbglibc 中,但是在系统上 glibc 定义为 libc
  5. 与完整路径名/lib/x86_64-linux-gnu/libc.so.6 相同的问题

编辑:

感谢@Employed Russian 的洞察力!我没有仔细观察以实现extern 声明。现在,我上面所有的笔记都说得通了!

太好了,我们发现ioperm 是在<sys/io.h> 中声明的libc 函数,而outb 不在libc 中,但在<sys/io.h> 中定义为易失汇编指令。

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

ccall 的实现。

【问题讨论】:

    标签: julia glibc libc


    【解决方案1】:

    但是,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 做 x5 更好。

    可能通过将相同的 outb 指令内联到其中。

    你知道outb是否存在于其他库中,而不是libc中

    不会有帮助:你仍然会有函数调用开销。我猜当你从 Julia 调用导入的函数时,你可能会执行 dlopendlsym 调用,这会带来额外的数百条指令的开销。

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

    【讨论】:

    • 错过了extern!虽然这解决了我所有的困惑,但我仍然不知道如何纠正错误。
    • 使库工作,但就性能而言,它是可怕的。未优化的 python 做 x5 更好。你知道outb是否存在于其他库中,而不是libc
    • 大概你实际上并没有只写一个字节,你想要的是一个向量化的函数,它一次输出整个字节数组。用 C 编写(使用 outb)并从 Julia 调用它,然后对于足够大的向量,函数调用开销可以忽略不计。
    • 要在纯 Julia 中执行此操作,您可能应该使用 Base.llvmcall 通过 LLVM 内在函数发出 x86 outb 指令。这样指令可以被内联。 (但它需要你了解一些低级 asm 和 llvm 的东西。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    • 2019-06-19
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多