lsof doesn't show anything with
It won't. There's a terminal emulator program built into the Linux kernel. It doesn't manifest as a running process with open file handles. It's layered on top of the framebuffer and the input event subsystem, which it uses internal kernel interfaces to access. It presents itself to application-mode systems as a series of kernel virtual terminal devices,
/dev/tty1 and so forth; a pseudo-file under
/sys that shows the active KVT number; and a series of CGA-style video buffer devices,
/dev/vcsa1 and so forth.
One of those application-mode systems is of course the
login system, which can be configured to operate on these kernel virtual terminals, and (as you have found) is by default. You can easily rid yourself of the
getty processes using documented systemd mechanisms.
In an old System 5
init system, each
getty would be a record in
/etc/inittab. In an BSD
init system, each
getty is a record in
/etc/ttys. In a systemd system, things are a little indirect.
- The "login" dæmon,
logind, knows about things called "seats" in systemd slang. "Seat" zero is the one with the primary framebuffer and all of those kernel virtual terminals.
- For that seat,
logind attempts to start N systemd services, named
email@example.com through to
autovt@ttyN.service. The value of N is set in the
NAutoVTs setting in
- These systemd services are created from a service template unit, named
autovt@.service. The template parameter is, as above, the device name of the kernel virtual terminal's device file, in
autovt@.service is, in the default configuration, a symbolic link to
- It is
getty@.service that describes running a
getty program, set to do its input/output via the kernel virtual terminal device file.
So to stop any of this, visit
/etc/systemd/logind.conf and configure
logind not to auto-start any
autovt services (and not to reserve any virtual terminals, if you want to be thorough about it).
However, that is not the whole of it. The terminal emulator program is still active in the kernel, and everything from log messages directed to a kernel VT through to the regular flashing of the cursor will cause the terminal emulator to interfere with your use of the framebuffer. But that's a matter for coding the program that you have that uses the framebuffer to negotiate with the kernel terminal emulator program, which has already been answered here.
The serial console login happens via a quite different route, by the way. A generator creates an instance of the
serial-getty@.service template unit a boot time, instantiating it once for each kernel console device that it finds, or is told about.