LinuxCNC — the whole system on one page
From the operator's screen down to the machine. Domains are marked by lines, never by
frames — a frame asserts membership and can be contradicted by its own geometry, while
a line cannot. Two dotted grey lines bracket what is inside the computer; between them, two
dashed red ones bracket the scheduling boundary, and what lies in that band is the two
shared-memory segments every machine has, which is what shared memory is — a configuration
can create more, and the band says which. The frames that do exist assert
process and thread membership — a fact about the running system, not a domain — and each lies
wholly on one side of every line. Everything drawn here was read in the source; the revision it
was read at, and where the evidence for it lives, are named at the foot of this page.
HAL shared memory · key 0x48414C32
2 MiB · pins · signals · params · functions · threads
every hal_init() attaches it — halcmd too
emcmot · RTAPI shmem key 100 — not NML, not a FIFO
command · SINGLE SLOT · mutex · commandNum → Echo
status · seqlock head / tail
error · MPSC ring 32 × 1024 · newest lost
HAL files
loadrt · addf · net · setp
read once at startup by halcmd
they BUILD HAL memory; no live link after
INI file
[KINS] · periods · limits · which GUI
read by task at startup — one way, never written back
Machine hardware
drives · encoders · limit and home switches · spindle · field I/O
Wizards
pncconf / stepconf
they GENERATE the INI and HAL files, one way
you run them before the machine, not with it
emcCommand
8192 B
queue
clients W
task R
emcStatus
20480 B
overwritten
task W
clients R
emcError
8192 B
queue
task W
clients R
linuxcncsvr — master of the three channels
creates the segments · starts first
NML servers, TCP 5005 — its clients are remote
remote NML client
another computer; nothing realtime runs there
needs libnml — in practice another Linux with LinuxCNC
a GUI-only control PC; task, motion and HAL stay here
AXIS there needs AXIS_NO_HAL=1 — HAL is local memory —
and loses jog pins, pyvcp panels, classicladder
config: client.nml on it · server.nml on the machine
no authentication on TCP 5005 — anything that reaches it writes
client.nml / server.nml are NOT INSTALLED — source tree only
and declare emcStatus at 10240 B against 20480 — NML halves it again
unverified — run tool_watch to settle it
halcmd / halshow
HAL clients — hal_init() attaches HAL memory
a hand tool, not part of the cycle
setp writes a pin, getp reads one — live
they never touch NML
halui
no display at all — knobs and switches
[HAL]HALUI — adds, never replaces
92 IN + 56 OUT pin sites
LOCAL GUI
axis · gmoccapy · touchy · gscreen · qtvcp screens (qtdragon…)
each screen exports its OWN pins — and the count differs
axisui 16 · qtdragon 18
milltask — the task process
tool, coolant, estop — no NML channel left for I/O
RS-274 interpreter
librs274.so — one class, TWO instances
task's: canon → interp_list → motion
iocontrol.0.*
14 HAL pins
former io process
sequencing
the task state machine —
decides what runs next
interp_list
std::deque
throttled at 1000
[TASK]INTERP_MAX_LEN
REMOTE GUI
telnet · nc · any socket client — plain text, not NML
a human or a program, on another machine
two passwords, but sent in the clear — man warns twice
G-code program — .ngc
the job, not the configuration
read TWICE, by two instances of the same interpreter:
task's — canon → interp_list → motion
the GUI's — canon → a drawing callback, the path on screen
tool table — mmap'd FILE, not RTAPI shm
milltask creates · GUIs and halui attach
read-write on both sides, under a mutex
wholly non-realtime — never crosses the line
rtapi_app — the process these threads run in
started by halcmd: loadrt runs "rtapi_app load <mod>"
a component is a shared object dlopen'd into it
uspace flavours only, the default; under RTAI-kernel they are kernel modules
servo-thread — servo_period_nsec · members, not execution order (addf order is config data)
both exported by motmod
via hal_export_funct()
JOINT 1…16 — a motor, not an axis · 9 separate Cartesian axes
to HAL memory: joint.N.motor-pos-cmd OUT · motor-pos-fb IN
④ HAL components in the same thread — wired by the integrator
pid.N.do-pid-calcs · encoder · stepgen.capture-position · pwmgen · limit3 · estop_latch
124 .comp + 25 .c source files
② motion-command-handler
inside the controller
TC_QUEUE — ring · 2000 segments ≈ 1 MB
spindle.N.* pins × 8
JOINT 1…16: cubic interpolator
→ backlash + screw comp → motor_pos_cmd pin
tpmod — cruckig · finite jerk
homemod · one of 19 *kins
separate modules (loadrt), called from motmod's functs:
controller RUNS it — tpRunCycle each period
handler FEEDS it — tpAddLine / tpAddCircle / tpSetVmax
③ motion-controller
base-thread
created only when servo_base_ratio > 1
the servo thread hands it work through
stepgen's own state — not through pins
stepgen.make-pulses
① read · ⑤ write — hardware drivers
hostmot2 (Mesa) · lcec (EtherCAT) · hal_parport · gpio
loaded by loadrt like motmod — rtapi_app_main()
their functs are addf'd into whichever thread the integrator picks
23 driver files · hostmot2 alone: 42 modules, one driver
every driver is a HAL component — its pins live in HAL memory
halrmt — a THIRD network door, onto HAL itself
telnet · TCP 5006 · it attaches HAL like any component
LoadRt · Unload · AddF · Net · SetP · Shutdown
— full control of the realtime config, over a socket
default passwords EMC / EMCTOO · sessions unlimited
nothing starts it: no config or script launches it
its man page: "It is not known if this interface currently works"
linuxcncrsh
telnet server · TCP 5007
a local NML client here
any telnet client
no LinuxCNC-provided client exists:
the man page says telnet, and the tree
contains none — same as the 5007 door
a human or a script, on another machine
LEGEND — the colour says WHAT A THING IS
position says where it lives; the arrows say what moves
NML · the only triplet
SHMEM — shared memory,
like the two below
but this one never crosses
the boundary
ordinary scheduling
NOT REALTIME
REALTIME
SCHED_FIFO · rtapi_app
streamer / sampler — the same kind of memory, optional
RTAPI segments of their own, created in realtime and
attached by halstreamer / halsampler, ordinary processes
— so they cross this band too
keys 0x48535430+n (into HAL) · 0x48534130+n (out of HAL), 8 each
loaded, they are addf'd into a thread and run in the cycle
shipped configs: streamer 0 of 332 · sampler 1 (the panelui demo)
a scheduling boundary, not a kernel boundary
kernel modules only on the RTAI-kernel flavour — 1 of the 5 RTAPI flavours;
uspace/RTAI is user space too
everything under this line is software
INSIDE THE COMPUTER
REMOTE DESKTOP
over network
①②③④⑤ is one shipped CONVENTION, not a rule. Of the 55 shipped configs that addf both a hardware read and motion-command-handler, 54 put the read first — and one does not:
configs/by_interface/general_mechatronics/GM6-PCI/3-axis-servo.hal reads its board after the controller has run. Reorder the addf lines and you reorder the machine's cycle.
INPUTS — files, not processes
detached on purpose: nothing here runs, and nothing here is
on the machine's cycle. They are read, then their arrows would
only add crossings. Kept as text.
everything ABOVE this line is software
INSIDE THE COMPUTER
THE MACHINE ITSELF
physical - no scheduling class applies to it
a PROCESS — something the kernel schedules
SHARED MEMORY — created on one side, attached from the other
REALTIME CODE — a shared object dlopen'd into rtapi_app by loadrt
a THREAD — its members are config data, not code
a FILE — read, never a running thing
NOT ON THIS COMPUTER
THE MACHINE — not software at all
no fill — a container, or a subdivision of its parent
Why it is coloured this way: so the colour can be checked, not admired.
• every GREEN box must sit inside rtapi_app
• every GREY box must sit above the remote line
• the ORANGE box must sit below the machine line
• every WHITE box must carry at least one link
All four hold as drawn. And one trap: "process" and "non-realtime" are not the
same thing — rtapi_app is a process and it lives below the line.
The letters on the NML strip say what each side DOES: the file declares task RW on
emcCommand, a permission it never uses.