package miou

  1. Overview
  2. Docs

Module Miou_unixSource

The Unix layer of Miou.

This module offers a re-implementation of the I/O according to Miou's model. This module is essentially concerned with reading and writing Unix.file_descr from sockets, pipes, fifos, terminals (and pseudo-terminals) and probably devices. For all these types of file_descr, reading/writing can block (waiting for bytes or waiting for the system's internal buffer to be free).

This is not generally the case for files and folders where read/write does not block. So, as far as files/folders are concerned, there is no point in using the suspend/resume mechanisms offered by Miou. These mechanisms (and the use of Unix.select) could actually degrade performance. It is therefore advisable to use the Unix module directly rather than Miou_unix for files/folders.

It should be noted, however, that reading/writing files can take a long time. So, in a cooperative context (with Miou.async), it may be worthwhile to increase the availability of other tasks to run with Miou.yield - so associate a Miou.yield with these operations. However, in the case of parallelization (Miou.call), it is not necessary to cooperate with the other tasks as they run in parallel. In this sense, and depending on the design of your application, these operations should, or should not, be associated with a Miou.yield.

How to spawn & handle processes with Miou_unix?

The Miou_unix module essentially only provides suspension points for reading and writing blocking file_descr (such as sockets). But users would probably like another type of suspension: namely, suspension until a launched program (via Unix.create_process) has finished.

The underlying mechanism provided by the system to signal the end of a program's execution is not related to file_descr but to signals. Here is an example of how to launch and wait for the end of a program using signals and the Miou.Computation module.

  let pid =
    Unix.create_process "sleep" [| "sleep"; "1" |] Unix.stdin Unix.stdout
      Unix.stderr
  in
  let c = Miou.Computation.create () in
  let handler _sigchld =
    match Unix.waitpid [ WNOHANG ] pid with
    | 0, _ -> ()
    | pid', status when pid' = pid ->
        ignore (Miou.sys_signal Sys.sigchld Sys.Signal_default);
        assert (Miou.Computation.try_return c status)
  in
  ignore (Miou.sys_signal Sys.sigchld (Sys.Signal_handle handler));
  match Miou.Computation.await_exn c with
  | Unix.WEXITED _ -> ()
  | Unix.WSIGNALED _ -> ()
  | Unix.WSTOPPED _ -> ()

Here are some explanations of the code above.

  1. There is no reference to the Miou_unix module (although there are references to Unix). As we said, Miou_unix only manages type:file-descr. In the code above, it is more about signal management.
  2. First, a program is launched with Unix.create_process and a handler is installed on the SIGCHLD signal. Please refer to the Miou.sys_signal documentation.
  3. This handler then fills in a Miou.Computation.t value c which, at the same time, is suspended further on with Miou.Computation.await_exn.

The suspension performed by Miou.Computation.await_exn can cooperate with the execution of other Miou tasks. In this way, the termination of the program is no longer blocking and you can, at the same time, execute tasks cooperatively and/or in parallel.

The handler function (which completes our Miou.Computation.t) is always executed by dom0 (as specified in the Miou.sys_signal documentation).

Finally, it is entirely possible to extend this code in order to associate our Miou.Computation.t with the PIDs of several launched programs (in a Hashtbl, for example) in order to define a more generic handler capable of unblocking several suspension points.

Why not integrate such a mechanism into Miou_unix?

This code currently has a global side effect: it installs a handler to manage the SIGCHLD signal. Miou and Miou_unix are libraries that should only slightly modify the global state of your program.

Therefore, it is your responsibility to install such a handler in order to enforce the explicit nature of what your program does — and to prevent Miou and Miou_unix from doing things implicitly just because you want to depend on these libraries.

Sourcetype file_descr

Type of file-descriptors.

Sourceval of_file_descr : ?non_blocking:bool -> Unix.file_descr -> file_descr

of_file_descr ?non_blocking ?owner fd creates a new file_descr. Depending on non_blocking (defaults to true), we set the given fd to non-blocking mode or not.

Sourceval to_file_descr : file_descr -> Unix.file_descr

to_file_descr fd returns the real Unix.file_descr.

Sourceval tcpv4 : unit -> file_descr

tcpv4 () allocates a new IPv4 socket.

Sourceval tcpv6 : unit -> file_descr

tcpv6 () allocates a new IPv6 socket.

Sourceval bind_and_listen : ?backlog:int -> ?reuseaddr:bool -> ?reuseport:bool -> file_descr -> Unix.sockaddr -> unit

bind_and_listen fd sockaddr binds the given socket to the given sockaddr and set up the given fd for receiving connection requests. backlog is the maximal number of pending requests. The optional argument reuseaddr (defaults to true) sets the REUSEADDR socket option on the given fd. The optional argument reuseport (defaults to true sets the REUSEPORT socket option on the given fd.

Sourceval accept : ?cloexec:bool -> file_descr -> file_descr * Unix.sockaddr

accept ?cloexec fd is a Miou friendly Unix.accept which returns file descriptors in non-blocking mode.

Sourceval connect : file_descr -> Unix.sockaddr -> unit

connect fd sockaddr is a Miou friendly Unix.connect. The function accepts only file_descrs in non-blocking mode.

Sourceval read : file_descr -> ?off:int -> ?len:int -> bytes -> int

read fd buf ~off ~len reads up to len bytes (defaults to Bytes.length buf - off from the given file-descriptor fd, storing them in byte sequence buf, starting at position off in buf (defaults to 0). It returns the actual number of characters read, between 0 and len (inclusive).

Sourceval really_read : file_descr -> ?off:int -> ?len:int -> bytes -> unit

really_read fd buf ~off ~len reads len bytes (defaults to Bytes.length buf - off) from the given file-descriptor fd, storing them in byte sequence buf, starting at position off in buf (defaults to 0). If len = 0, really_read does nothing.

Sourceval write : file_descr -> ?off:int -> ?len:int -> string -> unit

write fd str ~off ~len writes len bytes (defaults to String.length str - off) from byte sequence buf, starting at offset off (defaults to 0), to the given file-descriptor fd.

Sourceval close : file_descr -> unit

close fd closes properly the given fd.

Sourceval sleep : float -> unit

sleep v suspends the current task and sleeps v seconds.

Sourceval run : ?g:Random.State.t -> ?domains:int -> (unit -> 'a) -> 'a
Sourcemodule Ownership : sig ... end

/

Sourceval blocking_read : Unix.file_descr -> unit
Sourceval blocking_write : Unix.file_descr -> unit
OCaml

Innovation. Community. Security.