How does GHC implement unsafePerformIO?
Starting from unsafePerformIO
and ending at either the RTS, libc, or an OS API, how does GHC implement IO?
I'm trying to get a sense of how IO works in Haskell when the standard prelude isn't available (eg if we were implementing the standard prelude ourselves for whatever reason).
I was originally expecting to find wrapped calls to C functions in GHC's Haskell code, but that's not the case. unsafePerformIO
is built on top of runRW#
which is where heavy magic begins and we start crashing into functions and types that aren't implemented in Haskell and are instead built into the compiler. runRW#
appears to be able to run an IO action on the state of the real world (ie a State# RealWorld
).
Trying to go from the other direction, I haven't found a foothold in the RTS. It doesn't appear to contain the calls I would expect to functions like fread()
and fwrite()
or read()
and write()
.
Where do I continue following the IO implementation from here? What is the basic roadmap from here onwards?
As far as I can recall, a value of type IO x
is really a function from RealWorld#
to a [strict] tuple of RealWorld#
and x
. In other words, a simple state monad.
You won't find read()
etc in the RTS itself; I believe the usual Prelude interface calls them via FFI. That is, the code to do it is in the base
package, not in the RTS itself. (The RTS does, however, house its own thread-scheduler, which presumably calls pthread
or whatever. And also the garbage collector and memory manager, which probably call mmap
.)
At least, I believe that's how it works, as best as I can remember. Needless to say, this is all highly specific to GHC's particular implementation, rather than part of any official Haskell language specification.
链接地址: http://www.djcxy.com/p/7494.html上一篇: 未提升型产品的缺点?