I never really understood why a window system must have a server. Why do desktop environments, display managers and window managers need xorg-server? Is it only to have a layer of abstraction on top of the graphics card? Why do window systems employ a client-server model? Wouldn't inter-process communication via named pipes be simpler?
I think you've already noticed that some sort of "server" is needed. Each client (desktop environment, window manager, or windowed program) needs to share the display with all of the others, and they need to be able to display things without knowing the details of the hardware, or knowing who else is using the display. So the X11 server provides the layer of abstraction and sharing that you mentioned, by providing an IPC interface.
X11 could probably be made to run over named pipes, but there are a two big things that named pipes can't do.
- Named pipes only communicate in one direction.
- If two processes start putting data into the "sending" end of a named pipe, the data will get intermingled.
In fact, most X clients talk to the server using a "new and improved" named pipe called a UNIX-domain socket. It's a lot like a named pipe except that it lets processes talk in both directions, and it keeps track of who said what. These are the same sorts of things that the network has to do, and so UNIX-domain sockets use the same programming interface as the TCP/IP sockets that provide network communications.
But from there, it's really easy to say "What if I ran the server on a different host than the client?" Just use a TCP socket instead of the UNIX socket, and voila: a remote-desktop protocol that predates Windows RDP by decades. I can
ssh to four different remote hosts and run
synaptic (graphical package manager) on each of them, and all four windows appear on my local computer's display.
A window system does not have to have a server, but you can decide to implement window system based on a client-server model. Doing so has several advantages as you clearly separate the activities in the client and the server, they don't need to run on the same machine and it is more easy to service multiple clients. That is currently still very handy (e.g. when you
ssh into another machine), but you have to realise that at the time X was developed, that was seen as a necessity: your local machine might not be powerful enough to run the client.
Named pipes would not give you the automatic advantage of being able to run over the network as a TCP implementation would do. But named pipes were e.g. not available on DOS, with DosExtender running Desqview/X (1992), and AFAIK also not on VMS. For those implementations a Unix specific communication would be a problem.
TCP is not Unix specific and it is possible to have a client run under VAX/VMS (X development started in 1984) and serving the output to your local UNIX based graphics workstation. From the "X Window System: The Complete Reference to Xlib, X Protocol, ICCCM, XLFD"¹:
During the fall of 1986, Digital decided to base its entire desktop workstation strategy for ULTRIX, VMS, and MS-DOS on X. Although this was gratifying to us, it also meant we had even more people to talk to. This resulted in some delay, but, in the end, it also resulted in a better design. Ralph Swick of Digital joined Project Athena during this period and played a vital role thoughout version 11’s development. The last ver- sion 10 release was made available in December 1986.
From the "X Protocol Reference Manual"²:
Division of responsibilities
In the process of designing the X protocol, much thought went into the division of capability between the server and the client, sind this determines what information has to be passed back and forth through requests, replies and events. An excellent source of information about the rationale behind certain choices made in designing the protocol is the article The X Window System, by Robert W. Scheifler and Jim Gettys, published in the Association of Computing Machinery journal Transaction on Graphics, Vol 5, No. 2, April 1986 The decisions ultimately reached were based on portability of client programs, ease of client programming, and performance.
First, the server is designed, as much as possible, to hide differences in the underlying hardware from client applications. ...
I remember the article in TOG being an interesting read. It certainly triggered my interest in X and (this was before the WorldWideWeb) the difficulty we had laying my hands on more information until O'Reilly starting publishing their series X books.
¹ X Version 11, Release 4, page 2-X, PDF available online here
² This is from page 9 in the 2nd edition, published by O'Reilly, that I bought in 1990. There are newer editions but I never bothered to buy these and they are AFAIK only available in paper as well. I don't think they changed the rationale of the division of responsibilities.
A windowing system means that several independent programs share a common resource, the screen and input devices. Shared resources can only safely be implemented in two ways:
- The resource may be controlled by the kernel, and applications make kernel calls to access it.
- The resource may be controlled by a dedicated process (server), and applications contact the server to access it.
Of course, access to the actual display hardware is controlled by the kernel, but that's not sufficient for a windowing system: There must be a way for a process to get assigned a certain part of the display (the window) where it can be reasonably sure that no other process will interfere, and there must be a certain level of protection of what application can access which part of the ressource at which time.
Now the whole thing could have gone into the kernel, which is AFAIK what Windows does. This has the advantage of being faster (usually calling the kernel is much faster than contacting another process), however it has the disadvantage of possibly opening up security holes (any exploit of the system is an exploit at kernel level), and at the same time restricts portability (a system implemented in the kernel is strongly coupled to the kernel; you'll not be able to easily port it to another operating system, and completely unable to do if you have no access to the kernel code).
If you don't want to implement it in the kernel, the only other way to implement it is as a dedicated process, that is, a server. Note that a server that is contacted through named pipes still is a server. Also, when running on the same machine, a lot of the communication between X server and clients happens through shared memory these days; that still doesn't change the fact that the display server is a server.
Now, why is the server contacted using sockets, and not using named pipes? Well, if you do it using sockets, you just need to have one socket for the whole server, which can do all of the communication. If you communicate with pipes, you need two pipes per client. Apart from the fact that managing all those pipes would be quite cumbersome, you might also hit some operating system limits on the number of open pipes if sufficiently many programs try to talk to the server at the same time.
And of course another advantage of sockets over pipes is that with sockets you can have connections across machines, which was especially important at a time where the actual computer was shared by many people sitting on dedicated terminals, so the programs on the computer had to communicate to the different terminals, but it is still very useful even today in networked environments.
X was originally, developed and maintained by M.I.T. And, it was with an open source M.I.T license, not that, that really, matters.
While seen as uncoventional, consider for a moment; how you would explain a choice to use a client-server paradigm in a piece of software? And, perhaps I should say to a C.E.O...
Here's how I learned to appreciate the choice in college. In client-server, the server manages the resources, and especially, any resources that must be shared. So, the X server is the process that serves out, to the client apps, the keyboard, mouse, and framebuffer (or, however you write to the screen on your system).
While not really correct, the window manager is often explained away like this: It's simply, that thing, that put handles, and other decorations on an app's frame, and windows, dialogs, etc.
Client-server models are a popular design for all sorts of applications, even when there's only one server and only one client. They allow a clean, well-defined interface between domains of responsibility.
While there are many ways a server and client could communicate, the choice made by
X (regardless of the advantages mentioned by others) is not superfluous: You can connect to an
X server on a different machine and open windows on your desktop (or on another cooperating desktop). This used to be very common in the days when X was developed, when many Universities and businesses would have a Unix server and many "X terminals" that talked to it. By using an internet-ready communications protocol, X can be seamlessly used within or across hosts.
X was the first GUI environment that could transparently display windows from another machine, consistent with the history of UNIX as a multi-user environment rather than an OS for a single user on a single computer. A lot of UNIX features seem like overkill if you're the only person who ever gets to interact (physically or remotely) with your computer.
I believe the x-server was designed as a client-server architecture because initially computing resources were scarce and mainframes did most of the heavy lifting. X-terminals were just thin clients that connected to x-servers and displayed whatever needed to be displayed to the user.
It does have a lot of benefits (albeit the communication protocol for X is very heavy nowadays), notably you can display the same display on multiple clients, sharing a screen with multiple users is easy in X.