Linux is an active and evolving UNIX implementation that is gaining wide acceptance. However, Linux currently has several major limitations that prevent it from being a contender in any arena other than the small-server segment. Whereas Windows NT and all leading commercial operating systems (OSs) implement kernel-mode threads, Linux does not. The Linux scheduler does not divide CPU time among threads but among processes. Each process in Linux has an implied execution state that, on other UNIX variants, is the equivalent of a thread. Thus, a Linux process is similar to a process on other UNIX versions that has exactly one thread and cannot create more.
Linux's omission of kernel-mode threads seriously affects application developers' ability to write software that takes maximum advantage of a CPU. Linux application developers must use user-mode threads that the system implements in user space. User-mode threads are also called cooperatively scheduled threads, because kernel schedulers do not know that the threads exist, and therefore the schedulers do not divide CPU time among the threads. Instead, applications map multiple user-mode threads onto a common kernel-mode thread. Then, an application can cause the execution focus of the common kernel-mode thread to move around the application's code. The drawback of this method is that if a user-mode thread calls a kernel function that then blocks the thread (e.g., by waiting for I/O input), then the application cannot get any other work done. In implementations based on kernel-mode threads, blocking one thread of an application does not stop other threads that the application created from doing useful work.
Another limitation of the Linux kernel is that the scheduler cannot preempt the kernel, as can the scheduler in most modern UNIX variants and in NT. Because Linux's kernel is not preemptible, it is not as responsive to high-priority processes as other OS kernels are. When a high-priority process in Linux is ready to execute--for example, after it finishes an I/O operation on which it was blocked--the process must wait until the currently executing process reaches a well-defined preemption point in the kernel (if that process is executing in the kernel). On other UNIX systems, the high-priority process (or thread, on other OSs) would preempt the executing thread almost immediately.
Finally, the Linux kernel is not reentrant, which means that only one processor in a multiprocessor Linux system can execute kernel code at a time. This limitation is perhaps the biggest impediment to Linux's scalability on multiprocessors, because Linux serializes all its kernel services on a multiprocessor, making them run as if they were on a uniprocessor. Thus, I/O-intensive applications or applications that make heavy use of kernel services will not gain a significant performance benefit from executing on a multiprocessor. Linux is not reentrant because Linux's creator originally wrote Linux to run on uniprocessors. Making a kernel run efficiently on a multiprocessor means implementing relatively complex data structure-locking hierarchies, a task that is time-consuming on a structure that is difficult to retrofit.
How do these various limitations affect Linux's chance to compete with NT in the enterprise? With adequate OS support, enterprise server applications--including Web servers, database servers, and email servers--can efficiently use multiprocessors. For the next couple of years, Linux is stuck with being a valid choice for only small uniprocessor servers. None but the most CPU-intensive Linux applications will scale past one CPU, which makes Linux unacceptable as a multiprocessor OS, and therefore as an enterprise-class OS.