Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!snorkelwacker.mit.edu!bu.edu!xylogics!samsung!zaphod.mps.ohio-state.edu!wuarchive!udel!ee.udel.edu From: new@ee.udel.edu (Darren New) Newsgroups: comp.os.misc Subject: Re: What constitutes a good OS? Message-ID: <42617@nigel.ee.udel.edu> Date: 24 Jan 91 00:21:07 GMT References: <5427@auspex.auspex.com> <42488@nigel.ee.udel.edu> <5461@auspex.auspex.com> Sender: usenet@ee.udel.edu Organization: University of Delaware Lines: 157 Nntp-Posting-Host: estelle.ee.udel.edu In article <5461@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: >That could be done with a separate file - or with *multiple* separate > [...] >The fonts attached to the application's executable could be in separate >files, with no loss that I can see. Except that your applications normally contain dozens or hundreds of different resources, and the system file can contain thousands. Each menu item, each menu, each menu bar, each window, each window type, each button text, each button, each dialog window, each error message, each informative bit of text, etc is each a different resource. Therefore, you would probably want to make each application a directory, in which to hold all these little files, many of which take more disk space for the directory entry and the inode than for the data. (Speaking of which, where do you put the resources associated with a directory?) Then, you need something other than cp to copy applications and documents conveniently. exec() needs to be rewritten, as do your shells, to find the executable resources within the directory. It becomes quite easy to accidentally fubar an application by accidentally giving a bad file name somewhere, because all your applications have write-access and delete-access to all the resources of your application always, unless you want to add more protection bits that say which application owns the directory. Sure, you can do it half way by pretending a directory full of files is actually a keyed file or by adding a set of libraries on top of every program or by making some sort of structure inside the file that is problematic for shared updates, but do you really want the parameters for each X Windows call in your application to be put in a separate file? Of course none of this *needs* a more sophisticated access method. But I'll use a system where the things I need to do my job come with the computer, thanks. Again, I'm not arguing that UNIX should have such things added to the kernel, or even that they should be in there in the first place. Only that when starting from scratch, using essentially 20 year old file access methods seems like a bad idea. >See the comment above concerning menus; I'd rather not modify the >application file, especially if I'm sharing the file with somebody else. Normally, one does not modify the application while it's running. Also, the Mac has only one accessor for a file at a time. However, if it is built into the kernel, shared access can be mediated much more tightly and efficiently than if it is handled through libraries. The example of the WIND resource was for somebody adding a new look for windows at compile-time. The same mechanism might have been used to implement "tear-off menus" in hypercard -- the menu handling code was overridden in the application code at compile-time. >Many systems, including UNIX-flavored ones such as UNIX and Plan 9, >provide, as a "platform", a "file system" that provides access to named >randomly-accessible collections of bytes, and treat text files, keyed >files of various sorts, and data structures of sorts often *not* >provided by various OS's "access methods" as applications atop that file >system. It doesn't bother me that keyed files in those systems aren't >at the lowest level of the file system; I see little if any win to that. But Plan-9 goes much further than that, in that all accessible objects are accessed like files are. It just seems very kludgy to me to say that writing to /proc/1234/zelda will cause the zelda action to be performed by that process. It seems to me to be similar to saying "To create a pipe under UNIX, write your process id to the file called /dev/makepipe and then read that file to get back two integers which are the file handles." You can do it, but it's ugly. I'm not saying that putting everything in the file namespace is bad. I'm not saying that having files accessed as you describe above is particularly bad. I'm saying that having things other than files accessed only as you descibe above seems to me to be shoehorning strange things into the wrong paradigm. If writing to /proc/1234/ctl causes the process to stop, why does the process not have to read it's own ctl to get that information? Why is "cc" a program that you invoke, but "kill" a file you write to? Why do you rm a file to destroy it, close a window to destroy it, and write a string to a process file to destroy the process? Why do you creat() a file but fork() a process since you seem to talk to both the same way? Why is /dev/bitblt implemented as a single stream-oriented file when calls to blit normally have five or six structured arguments? Why not have six files, and another for writing requests and another for reading the responses of requests? When checking for errors, does one look at a global errno, or does one read /dev/errno after every call? Before you bother to answer all this, realise first that hyperbole is being used in some of the above examples, and second that I'm not asking about these specifics, but rather about what basis is used to make these decisions. What is the motivation for such choices, and what *should* be the motivation for such choices? To me it looks like a mishmash of contortions caused by the choice of a UNIX-like filesystem interface as the primary IPC&I/O mechanism with special cases provided for things that are not efficiently handled in that way. It just seems to me that a distributed or remote filesystem is a special case of procedure calls, rather than RPC being a special case of file I/O. Shoehorning RPC into a bytestream model seems like it might lead to *more* device dependancy rather than less. I've seen systems (AmigaDOS and now Amoeba) which both handle communication in a message- and object-oriented way, and both seem to have much cleaner construction. It is clear in Amoeba and in AmigaDOS from just a simple description of how the basic I/O operations work how you would go about acessing remote files and why particular choices were made in that mechanism, just as Ada cannot be described in ten pages but Lisp and FORTH can. There is usually a "straightforward" and obvious method for implementing any capability one might imagine. For example, it isn't clear how processes get migrated (especially since the paper doesn't say :-). Would one copy the /proc/123/* files? Is it a special call? If you copy the /proc files, where do you copy them to? Are names added to the name space by writing to a special file? Or by a creat() call? Or both? Are lightweight threads created with a special call, or by writing to one of the /proc files? None of these are obvious when you look at a simple description (on the order of 10 pages or so) of Plan-9. The answers *are* obvious from a ten-page description of Amoeba or AmigaDOS. Another thing that bothers me is the comment that security is not an integral part of Plan-9. With bigger systems networked more widely, I would not want to place my trust in an OS with security as difficult to get right as it is under UNIX. Under Amoeba, the same mechanism that keeps me from writing your files keeps me from killing your processes and keeps me from tapping you ethernet; the mechanism is simple, elegant, robust, and easy to see is correct. >I haven't seen any good evidence yet that you *can't* build an >"object-oriented" facility for implementing objects including but *not* >limited to the sequential/keyed/etc. files provided by most "acces >methods" atop such a platform, perhaps with some small additions made to >the platform. Sure. I can write recursive algorithms in FORTRAN, too. I can write massively parallel, distributed, object-oriented code in C. However, it would be cleaner, easier to understand, easier to get correct, and probably even more efficient to use the right tool for the right job. Using directories as keyed files is something I consider as "the wrong tool." Restricting servers to only respond to a small number of kinds of requests and forcing non-file-like operations to use only file-like operators also seems like "the wrong tool." $$$$ If you want to discuss only one point further, below is the point I would like to discuss: $$$$ As a matter of fact, I can write the UNIX filesystem on top of the FORTH filesystem, wherein individual disk blocks are read and written by integer index (i.e., disks are just arrays of blocks). I have yet to see any good reason why one should have a filesystem that goes just as far as the UNIX filesystem does, and then stops. I've seen several good reasons for (and examples of) why you would want something *less* complex that the UNIX filesystem, and I've seen several good reasons for (and examples of) something *more* complex than the UNIX filesystem, but as far as something *exactly* as complex as the UNIX filesystem, people usually just say "Oh, put it in libraries." Why not put directories, access-control, allocation, and concurrency controls in libraries? -- Darren -- --- Darren New --- Grad Student --- CIS --- Univ. of Delaware --- ----- Network Protocols, Graphics, Programming Languages, Formal Description Techniques (esp. Estelle), Coffee, Amigas ----- =+=+=+ Let GROPE be an N-tuple where ... +=+=+=