Ich gehe im Folgenden mal davon aus, dass du von POSIX redest. Falls das falsch ist, korrigier mich bitte.
Erstmal dein Beispielszenario, das aber einfacher ist, als du dachtest: Wenn zwei Prozesse gleichzeitig nach stdin schreiben, bekommen sie beide gleichzeitig EBADF.
Wenn du nach stdout schreibst, also mit write() auf FD 1, dann ist irgendjemand zuerst dran und dessen Daten werden dann zuerst geschrieben. Danach kommt der andere Prozess und hängt seine Daten dahinter. Wenn du unter Linux mal einen Prozess in den Hintergrund geschickt hast, der Ausgaben macht, dann kennst du das Ergebnis, dass sich die Ausgaben von der Shell und vom Hintergrundprogramm auf dem Terminal vermischen.
Mit mmap() sieht die Sache anders aus, wobei ich nicht weiß, ob man Character Devices überhaupt sinnvoll mmapen kann. Es soll ja auch irgendwas passieren, nachdem du auf das Gerät geschrieben hast statt dass die Daten nur in einem Cache landen. Du müsstest wahrscheinlich bei jedem Schreibzugriff auf die Page faulten, dir merken, dass da gerade Daten reinkommen, den Prozess weiterlaufen lassen und irgendwann später die Ausgabe machen und die Page wieder schreibschützen. Was passiert, wenn der gemappte Puffer einmal vollgeschrieben ist, finde ich auch nicht ganz klar. Du könntest versuchen, das als Ringpuffer aufzubauen, aber wie bekommst du mit Speicherzugriffen auf einen gemmapten Bereich eine blockierende Operation hin, wenn der Ring voll ist?
Insofern würde ich stark dazu tendieren, mmap nur für normale Dateien und Blockgeräte zuzulassen, aber nicht für Character Devices, Pipes, Sockets usw. (POSIX verlangt: "The mmap() function shall be supported for regular files, shared memory objects, and typed memory objects. Support for any other type of file is unspecified")