3.5 不安全过程

(loko system unsafe) 库提供了对内核服务、线性内存和 I/O 总线寄存器的原始访问。

Procedure: syscall n arg …

使用参数 arg … 调用内核的系统调用号 n。返回一个 fixnum。

在 Linux amd64 上的 fork 示例:

(when (zero? (syscall 57))     ; __NR_fork
  (display "child process\n")
  (exit))                      ; 子进程成为僵尸进程

Scheme 程序通常不应直接使用系统调用编写,就像 C 程序不应该这样做一样。通常需要考虑与标准库的交互,例如刷新端口以防止重复输出。

Procedure: bytevector-address bytevector

获取 bytevector 的第一个字节的线性地址。

第一个字节保证具有八字节对齐。

对于使用 make-bytevector 创建的 bytevector,使用移动式垃圾回收器。没有办法确保它们在 GC 期间不会移动,因此它们的地址不应用于执行总线主控 DMA。

返回一个 fixnum。

Procedure: get-mem-u8 addr
Procedure: get-mem-u16 addr
Procedure: get-mem-u32 addr
Procedure: get-mem-s61 addr

分别从线性地址 addr 读取 u8、u16、u32 或 s61,并将其作为 fixnum 返回。

  • 如果 addr 未对齐,则引发异常。
  • 在 fixnum 不够宽以容纳结果的目标上,将使用大整数代替,但总线访问将是正确的宽度。
  • 对这些过程的调用不会被编译器优化掉或重新排序。
  • 每次调用对应于一次匹配大小的内存读取指令。对于有符号的 61 位过程,这仅适用于可以发出 64 位内存总线操作的目标。
  • 这些调用可能被处理器乱序执行或进入缓存。这通常仅在内存区域由 RAM 支持时才会成为问题。在 AMD64 上,由于 MTRR,使用这些过程读取内存映射硬件寄存器是安全的。其他情况可能需要锁定指令或内存屏障。
Procedure: put-mem-u8 addr n
Procedure: put-mem-u16 addr n
Procedure: put-mem-u32 addr n
Procedure: put-mem-s61 addr n

分别将 n 作为 u8、u16、u32 或 s61 写入线性地址 addr

  • 如果 addr 未对齐,则引发异常。
  • 对这些过程的调用不会被编译器优化掉或重新排序。
  • 每次调用对应于一次匹配大小的内存写入指令。对于有符号的 61 位过程,这仅适用于可以发出 64 位内存总线操作的目标。
  • 这些调用可能被处理器乱序执行或合并。这通常仅在内存区域由 RAM 支持时才会成为问题。在 AMD64 上,由于 MTRR,使用这些过程读取内存映射硬件寄存器是安全的。其他情况可能需要锁定指令、手动刷新或内存屏障。

返回未指定的值。

Procedure: get-i/o-u8 busaddr
Procedure: get-i/o-u16 busaddr
Procedure: get-i/o-u32 busaddr

分别从 I/O 总线地址 busaddr 读取 u8、u16 或 u32,并将其作为 fixnum 返回。

(<= (fixnum-width) 32) 的目标上,get-i/o-u32 过程可能返回大整数,但总线访问将是 32 位的。

Procedure: put-i/o-u8 busaddr n
Procedure: put-i/o-u16 busaddr n
Procedure: put-i/o-u32 busaddr n

分别将 n 作为 u8、u16 或 u32 写入 I/O 总线地址 busaddr

返回未指定的值。

Procedure: get-i/o-u8-n! busaddr addr n
Procedure: get-i/o-u16-n! busaddr addr n
Procedure: get-i/o-u32-n! busaddr addr n

从 I/O 总线地址 busaddr 读取 n 个 u8、u16 或 u32 单元,并将其写入从线性地址 addr 开始的内存。

地址 addr 必须自然对齐到写入的大小。否则引发 &assertion

返回未指定的值。

Procedure: put-i/o-u8-n busaddr addr n
Procedure: put-i/o-u16-n busaddr addr n
Procedure: put-i/o-u32-n busaddr addr n

n 个 u8、u16 或 u32 单元写入 I/O 总线地址 busaddr,同时从线性地址 addr 开始的内存读取它们。

地址 addr 必须自然对齐到读取的大小。否则引发 &assertion

返回未指定的值。