Julia ccall outb - libc 的问题
Julia ccall outb - Problems with libc
我运行以下ccall
的:
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
经过一番研究和摸索,我发现了以下信息:
ioperm
在 libc 中,但 outb
不是
- 但是,
ioperm
和outb
都定义在同一个头文件中<sys/io.h>
- C 代码的等效版本 可以顺利编译 和 运行。
outb
在 glibc
中,然而在系统上 glibc
被定义为 libc
- 完整路径名也有同样的问题
/lib/x86_64-linux-gnu/libc.so.6
编辑:
感谢@Employed Russian 的洞察力!我没有仔细观察以了解 extern
声明。现在,我上面的所有笔记都很有意义!
很好,我们发现 ioperm
是 <sys/io.h>
中声明的 libc
函数,而 outb
不在 libc
中,但是在 <sys/io.h>
中定义为可变汇编指令。
我应该使用哪个库或文件路径?
实施ccall
。
However, both ioperm and outb are defined in the same header file <sys/io.h>
"defined" 实际上是指 "declared"。它们是不同的。在我的系统上:
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
I am still lost as to how to correct the error.
您无法从 libc
导入 outb
。您必须提供自己的本地库,例如
void my_outb(unsigned char value, unsigned short port) {
outb(value, port);
}
并从中导入 my_outb
。为了对称,您可能应该以相同的方式实现 my_ioperm
,这样您就可以从同一个本地库中导入这两个函数。
更新 2
Making a library worked, but in terms of performance it is horrible.
我想这就是为什么将原始函数实现为内联函数的原因:您只执行一条 outb
指令,因此函数调用的开销很大。
Unoptimized python does x5 better.
可能是通过将相同的 outb
指令内联到其中。
Do you know if outb exist in some other library, not in libc
那是没有的帮助:您仍然会有函数调用开销。我猜想当您从 Julia 调用导入的函数时,您可能会执行 dlopen
和 dlsym
调用,这会带来额外的数百条指令的开销。
可能有一种方法可以动态"bind"函数一次,然后重复使用它进行调用(从而避免重复dlopen
和dlsym
)。 应该会有帮助。
我运行以下ccall
的:
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
经过一番研究和摸索,我发现了以下信息:
ioperm
在 libc 中,但outb
不是- 但是,
ioperm
和outb
都定义在同一个头文件中<sys/io.h>
- C 代码的等效版本 可以顺利编译 和 运行。
outb
在glibc
中,然而在系统上glibc
被定义为libc
- 完整路径名也有同样的问题
/lib/x86_64-linux-gnu/libc.so.6
编辑:
感谢@Employed Russian 的洞察力!我没有仔细观察以了解 extern
声明。现在,我上面的所有笔记都很有意义!
很好,我们发现 ioperm
是 <sys/io.h>
中声明的 libc
函数,而 outb
不在 libc
中,但是在 <sys/io.h>
中定义为可变汇编指令。
我应该使用哪个库或文件路径?
实施ccall
。
However, both ioperm and outb are defined in the same header file
<sys/io.h>
"defined" 实际上是指 "declared"。它们是不同的。在我的系统上:
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
I am still lost as to how to correct the error.
您无法从 libc
导入 outb
。您必须提供自己的本地库,例如
void my_outb(unsigned char value, unsigned short port) {
outb(value, port);
}
并从中导入 my_outb
。为了对称,您可能应该以相同的方式实现 my_ioperm
,这样您就可以从同一个本地库中导入这两个函数。
更新 2
Making a library worked, but in terms of performance it is horrible.
我想这就是为什么将原始函数实现为内联函数的原因:您只执行一条 outb
指令,因此函数调用的开销很大。
Unoptimized python does x5 better.
可能是通过将相同的 outb
指令内联到其中。
Do you know if outb exist in some other library, not in libc
那是没有的帮助:您仍然会有函数调用开销。我猜想当您从 Julia 调用导入的函数时,您可能会执行 dlopen
和 dlsym
调用,这会带来额外的数百条指令的开销。
可能有一种方法可以动态"bind"函数一次,然后重复使用它进行调用(从而避免重复dlopen
和dlsym
)。 应该会有帮助。