If you are used to the Unix programming with C, then almost the same concepts apply to OCaml using the Unix module, with slightly different syntax for function calls and arguments.
It is pretty straight forward if you have already done some system programming in C before, to compile you should add unix.cma to the arguments of ocamlc.
Example 1: fork, getpid and getppid :
- open Unix;;
- open Printf;;
- let a = fork () in
- match a with
- | 0 -> printf "child -- pid : %d ,ppid : %d\n" (getpid ()) (getppid ())
- | -1 -> printf "%s" "error accured on fork\n"
- | _ -> printf "parent process : %d\n" (getpid ())
- ;;
This example shows how to do a simple fork to create a new process, then each process prints its pId to the console, here we cannot ensure which one will print first, the parent or the child. Here we use the usual function fork, getpid to get the ID of the current process and getppid to get the parent process.
Compile :
- sky@sky-laptop:~/Desktop$ ocamlc unix.cma demo.ml -o demo
Output 1:
- sky@sky-laptop:~/Desktop$ ./demo
- parent process : 3249
- child -- pid : 3250 ,ppid : 3249
Output 2:
- sky@sky-laptop:~/Desktop$ ./demo
- child -- pid : 3250 ,ppid : 3249
- parent process : 3249
Example 2, wait:
To ensure that the child process finish before its parent we use the wait system call, which returns the id of the finished process and the status code returned from the process.
- open Unix;;
- open Printf;;
- let a = fork () in
- match a with
- | 0 -> printf "child -- pid : %d ,parent pid : %d\n" (getpid ()) (getppid ());
- exit 13
- | -1 -> printf "%s" "error accured on fork\n"
- | _ -> let childid, returncode = wait () in
- printf "parent process : %d\n" (getpid ());
- printf "child %d closed with status code %d" childid (let WEXITED(code) = returncode in code)
- ;;
Output :
- sky@sky-laptop:~/Desktop$ ./demo
- child -- pid : 3268 ,parent pid : 3267
- parent process : 3267
- child 3268 closed with status code 13
As you see, the child exits with the code 13, the parent calls wait to wait for its unique child created with fork, then reads the returned code, note that OCaml will generate a warning here because we just check for WEXITED (we know it will exit normally) but we omit WSIGNALED and WSTOPPED. In C you don’t have this flexibility of warnings which can brings you a lot of trouble.
Exemple 3, exec*:
This example demonstrates how to use the exec* calls, these methods replaces the core of the process with the new code of the command to be executed thus the function never returns, when the function fails, an exception is thrown, check the specifications here.
- open Unix;;
- open Printf;;
- let a = fork () in
- match a with
- | 0 -> (try
- execvp "ls" [|"ls"; "-l"|]
- with
- _ -> printf "%s" "error while execv\n"; exit (-1))
- | -1 -> printf "%s" "error accured on fork\n"
- | _ -> ignore (wait ()); printf "%s" "parent exit...\n"
- ;;
Here we fork and replace the child code with the ls command’s, here is the output
- sky@sky-laptop:~/Desktop$ ./demo
- total 136
- -rwxr-xr-x 1 sky sky 82110 2010-04-20 00:26 demo
- -rw-r--r-- 1 sky sky 234 2010-04-20 00:26 demo.cmi
- -rw-r--r-- 1 sky sky 743 2010-04-20 00:26 demo.cmo
- -rw-r--r-- 1 sky sky 291 2010-04-20 00:26 demo.ml
- -rw-r--r-- 1 sky sky 410 2010-04-20 00:26 demo.ml~
- parent exit...