SFU und SUA: Unix unter Windows

Eher zufällig stolperte ich bereits für über 15 Jahren mit meinem damaligen Server 2003 über die interessante Erweiterung “Service for Unix”.

Denn tatsächlich gab es seit NT 4 kein Windows, das gänzlich ohne POSIX Schnittstelle auskam. Windows 10/Server 2016 war hier anfangs die Ausnahme, doch bereits im Server 2019 kehrte der Nachfolger mit Windows Subsystem for Linux zurück.


Während der damalige Microsoft-Chef Steve Ballmer anfangs der 2000er noch kräftig gegen die OpenSource Bewegung wetterte und außer Windows am Wolkenhimmel nichts anderes zu sehen vermochte, war Unix kein Feind der Windows Welt.

NT 4 hatte bereits eine primitive POSIX-Schicht eingezogen, damit man Windows als Universalsystem vermarkten konnte.
Doch offen gesagt bin ich mit dieser Variante nie in Berührung gekommen.

Ab Windows 2000, XP und Server 2003 konnte man den POSIX-Nachfolger “Services for Unix” nachinstallieren. Allerdings nur für die 32-bit Version von Windows. Wer Server 2003 X64 oder WinXP 64 einsetzte, war von der Installation ausgeschlossen.

Mit Windows Vista und Server 2008 war das Subsystem innerhalb des regulären Feature-Setups möglich und brachte auch X64 Support mit. Man musste nur das umbenannte Feature “Subsystem for UNIX-based Applications” (kurz SUA) aktivieren und schon bekam Windows unixoide Eigenschaften.

Hier fehlten dann allerdings die Unix Tools, wie auch das SDK um Software dafür zu bauen. Um das zu erhalten musste man von Microsoft weiter einen Installer herunterladen, der eben diese Dateien nachlieferte.

Ich nutzte für meine Tests meinen Windows Server 2012 und die dazugehörigen SUA SDK Tools.

SFU/SUA’s produktiver Nutzen

In meinen Arbeitsbereichen kamen SFU und SUA nie vor.
Wenn jemand Unix oder Linux-Tools nutzen wollte, installierte er Cygwin und erhielt auf diese Weise die üblichen Unix/Linux Tools.

Denn meistens ging es immer nur um die Ausführung von Scripts, und bevor sich in der zweiten Hälfte der 2000er die PowerShell unter Windows durchsetzen konnte, war Scripting unter Windows mangelhaft oder einfach unbekannt.

Aufgaben wie das tägliche automatische Herunterladen von Dateien von HTTP oder FTP Servern war mit VBScript oder BATCH Dateien unter Windows nicht direkt möglich, während Unix-Shellscripts besonders mit Linux für administrative Aufgaben schon 10 Jahre vorher “standard” waren.

SFU/SUA Dateisystem

Die Standardinstallation legt unter XP/2003 C:\SFU an, was innerhalb der Umgebung das Root-Dateisystem darstellt. So kann man von Windows aus direkt Dateien austauschen, z.B.: in C:\SFU\usr oder C:\SFU\tmp.
Die neueren Varianten (wie auch mein Server 2012) nutzen C:\Windows\SUA als Basis.

Umgekehrt ist das Windows-Dateisystem in SFU über /dev/fs/C/ erreichbar. Das gilt auch für alle anderen Windows Laufwerksbuchstaben.

/home existiert hier nicht, aber die HOME Variable zeigt auf /dev/fs/C/Documents and Settings/username bzw. /dev/fs/C/Users/username womit man auch hier wieder zwischen Win32 und SFU/SUA Programmen Dateien austauschen kann.

Interessant sind auch noch symbolische Links. Die werden im Windows Dateisystem als normale Datei angelegt, deren Inhalt aber mit dem magischen Token IntxLNK beginnt, gefolgt vom verlinkten Dateipfad in UTF-16. Die SFU Umgebung meldet sie jedoch wie übliche Links und löst den Pfad intern auf.

Programme für SFU/SUA erstellen.

In jedem MSVC Win32 Programm kann man ja ein Linker-Subsystem festlegen und das ist entweder CONSOLE oder WINDOWS. Doch wer die Liste genau betrachtet, findet auch POSIX unter den Möglichkeiten. Genau dieses Subsystem erstellt eine SFU/SUA Binärdatei.
Doch beim ersten Versuch eine Hello-World-App zu kompilieren, erscheint:

LINK : error LNK2001: unresolved external symbol ___PosixProcessStartup

Man muss also die C-Runtime und Link-Libraries auch noch etwas anpassen:

  • Wir müssen die Standard-C-Runtime ausschließen.
  • Und explizit gegen die SFU/SUA Libraries linken.

Die entsprechenden Linker-Kommandos sind

  • Linker-System-Subsystem:
    /SUBSYSTEM:POSIX
  • Linker-Input-Ignore Specific Default Libraries:
    /NODEFAULTLIB:LIBCMT
  • VC++ Directories-Library Directories:
    /LIBPATH:C:\Windows\SUA\usr\lib\ für X64
    oder /LIBPATH:C:\Windows\SUA\usr\lib\x86 für X86
  • Linker-Input-Additional Dependencies:
    psxlibc.lib;crtexe.o;libpsxdll.a;libc.a

Die crtexe.o ist für mein ausführbares Programm notwendig. Allerdings liegen auch noch crt0.o und crtdll.o vor, die vermutlich für DLLs oder mit statischer/dynamischer Runtime notwendig sind.

Am Ende erhält man eine EXE, die man im SFU/SUA Kontext ausführen kann.

Im Dependency Walker kann man dann auch nachweisen, dass die EXE wirklich gegen die PSXDLL.DLL gelinkt ist, die wiederum alle POSIX Funktionen implementiert und in die Windows Welt übersetzt.

PSXDLL

Randnotiz: Im WinXP SFU war sogar ein uralter GCC 3.3 integriert, doch ohne CMake wollte ich mir nicht die Mühe machen, hierfür ein Testprogramm zu kompilieren. However … ich wette, es hätte funktioniert.

Fazit

Nachdem ich Lust und Laune hatte, mir ein SFU/SUA Setup anzusehen, hat mir vor allem der Blog Artikel blog.ret2.io/2017/09/20/subsystem-posix super weitergeholfen, meinen Linkerfehler wegzubekommen.
Danke an den Autor!

Genau solche Infos gehen leider Stück für Stück verloren, denn SFU/SUA Installationsdateien mögen noch weiter viele Jahre im Netz auffindbar sein, doch die Dokus hat Microsoft schon lange zurückgezogen.

Ich bezweifle zwar, dass ich jemals wieder mit dieser Technologie arbeiten werde, doch es ist gut zu wissen, wie es funktioniert hat.

Schade ist, dass Microsoft seine “Verbindung” zur Unix Welt so lange verleugnet hat und erst 2017 mit WSL eine Idee hat wiederaufleben lassen, die es eigentlich schon im Jahr 2000 gab.