Part of the attraction to messing with WINE, beyond its practical benefits, is simply the challenge involved. And there is also my fascination with the inner workings of computers. And then there is also the idea that when you contribute to a really low-level project, the implications can be very broad and far-reaching. In the case of WINE, every feature you add has the potential to open compatibility to dozens or even hundreds of applications. There is also the educational aspect, too, as I've picked up details about Windows and Linux that I wouldn't have learned otherwise.
Foremost of these is the concept of mapped memory. This may be the greatest programming construct that nobody ever talks about. Under the unices, this is accomplished with the mmap() function, and under Windows, the equivalent is CreateFileMapping(). The basic idea is that you can create arbitrary correspondences between a process' address space and a file. That's all. It's very simple, and very useful. Of course, this is especially powerful under the unix-like systems where the devices are all files. So, that earlier statement abstracts to encompass the creation of arbitrary correspondences between address spaces and devices. For example, I can map a one-megabyte block of addresses to /dev/random, and I instantly have a virtual megabyte of random numbers. Because it's mapped to a device, that address space doesn't take up any physical memory. The address-space itself is allocated, but it is private to the process. On a modern 64-bit machine, each and every process has 2^64 bytes of virtual address space, and you can map it to anything you want.
A more useful example is to map a huge address space to an equally huge game world stored on disk, and then the operating system takes care of the details of paging the world in and out of memory while, to your application, it appears exactly as if all twelveteen dozen gigabytes of the file are resident in memory. If you map to things that aren't memory, then there's basically no limit.
Incidentally, this is how Linux and probably other OSes handle shared libraries (dlls). Rather than allocating a chunk of physical memory for each dll for each and every process that uses it, instead, the disk file containing the library is simply mapped into memory, so that in reality all of the processes are referencing the same physical copy. That way, a dll may not even be present in RAM, except when needed, and even then, it may only be the parts of it that are in use.
As a footnote, mmap() seems to work really poorly on /dev/mem. Maybe it involves implicit locking, or something, but you can't simply map the entirety of physical memory, even if you do it read-only.
ReplyDelete