wheeler@IDA.ORG (David Wheeler) (05/23/91)
The original version of Minix did not allow _User Processes_ to pass messages to OTHER user processes. Two questions for the net: 1. Does the current version (or some modified version everyone uses) allow this? (From all I can tell it doesn't). 2. If not, would someone who has the current version of Minix mind trying out the following modification to allow it? Please? Or tell me a better way to do it? ------------------------------------------ Background: all of Minix's implementation is based on send, receive, and send_receive. UNFORTUNATELY user processes are ONLY allowed to do send_receive, and to only two OS processes, not to other user processes. Lots of other OS's _DO_ provide this feature (Mach, System V, QNX, etc), it's VERY useful. Last year Mark Boyd posted the following: mark@ccvr1.ncsu.edu (Mark Boyd): > I'm trying to use messages for process syncronization. I can > find no way to use messages between user processes. Has anyone > done this? I'm working on 68000 based systems ( ST and PT68k ), > but I don't see where the problem would be any different on > PCs. > Mark Boyd > mark@ccvr1.ncsu.edu I then replied a possible solution. Has anyone tried this? Does the current version already include this? Would anyone mind trying this and telling me if things blow up? I've incorporated a modified (improved) version of my reply to him below: ------------------------------------------------------------------- I looked into this problem once.. I think it can be done but haven't tried it myself. I'm not aware of this capability being in the latest version of MINIX, so you'd have to modify the OS. I don't have the latest version of MINIX, so my info is based on the original code in the book. See the MINIX code as published in "Operating Systems: Design & Implementation", page 473. Lines 1987-1988 and 1950-1953 mean that user processes may only execute a sendreceive, and that user processes may only send to FS or MM. A quick & dirty solution would be to remove these two sections, then recompile MINIX. There may be other sections which make this assumption, but those two sections are certainly a minimum. This would mean, unfortunately, that user programs could send to anybody, including internal OS processes. A much better approach would be to make it so that user programs can only call other user programs OR FS OR MM. For this, change kernel/proc.c lines 1950-1953 and 1987-1988 (as numbered in the original MINIX book) to what follows. These lines are checks which currently prohibit user-to-user calls; I replace them with checks that allow users to either call FS & MM (only send_receive to these) *OR* call other user processes any way they wish. Since user processes MUST do a send_receive when they message to FS & MM, FS & MM don't need to change (since they expect send_receive), and other user processes can't spoof as FS & MM (since a process sending to FS & MM will only listen to who it sent to). Any process sending to another process is automatically trusting the sendee- if the sendee never receives from ANY, the process stays blocked! That's normal for this kind of IPC. You can kill the sender, and Minix will automatically clean up this queued request, so no harm done. More interesting is killing a user process to which others are sending (i.e. a user-level server). I don't see any code in Minix to handle this case (ie by restarting those processes waiting to send or receive from this process), though I may have missed it. You shouldn't be killing server-type processes this way anyway; it's much safer to give server processes a ``kill'' command so they can shut down gracefully. FS & MM expect to be BOTH sent & received by users, so calling to FS & MM by users MUST obey that restriction. (Note: I forgot this check in my last post). Lines 1950-1953 need to be changed to the following: ---------------------------------------- if (function != BOTH && caller>=LOW_USER && ( src_dest == FS_PROC_NR || src_dest == MM_PROC_NR ) ) { rp->p_reg[RET_REG] = E_NO_PERM; /* Users only do BOTH to MM & FS */ return; } ---------------------------------------- The mini_send routine currently only allows users to send to MM & FS. You want users to be able to send to MM, FS, or other users. Calling a process greater than the # of possible processes was checked earlier. Change lines 1987-1988 to the following: ---------------------------------------- /* Allow users to send to each other as well as MM and FS */ if (caller >= LOW_USER && (dest != FS_PROC_NR && dest != MM_PROC_NR && dest < LOW_USER)) return(E_BAD_DEST); /* It is illegal to send to ``any'' - complain if it's attempted! */ /* NOTE: This check is new; my last post didn't check for this error. */ if (dest == ANY) return(E_BAD_DEST); ---------------------------------------- One problem is how to get the process id for the process to send to, since unlike MM & FS there's no fixed process id for other processes. In the short run, here's a simple technique: Have your server (user program) store its process id when it starts up in a file with an agreed-on filename. Other programs can read the file to get its name. If there's a possibility that programs could try to read the file while it's being written, have the server create a second file that indicates ``I'm done writing'', and have all the clients look for that file first. A much better solution would be a name server process at a set process id (as FS and MM are now). Serving programs could ``register'' themselves with a short name, and clients could request a program by name and receive its process id. A better approach would be replacing those sections with something more sophisticated, so that certain user processes can talk with certain other processes given certain secure conditions. Other OS's do allow user processes to send & receive messages and have some security checks (perhaps the process sets certain permissions to allow certain other user tasks to send to it, etc, etc). --- David A. Wheeler wheeler@ida.org
philip@cs.vu.nl (Philip Homburg) (05/23/91)
In article <1991May22.235824.6939@IDA.ORG> wheeler@IDA.ORG (David Wheeler) writes:
%
%The original version of Minix did not allow _User Processes_
%to pass messages to OTHER user processes.
%
%
%Two questions for the net:
%
%1. Does the current version (or some modified version everyone uses)
%allow this? (From all I can tell it doesn't).
%
%2. If not, would someone who has the current version of Minix mind
%trying out the following modification to allow it? Please?
%Or tell me a better way to do it?
Please DON'T DO THIS. May be this is too loud and I should whisper "please,
don't do this" but you are looking for trouble.
I have a kernel which allows user processes to send to and receive from
anyone and it is part of minix 1.6.15 but it is for debugging purposes only.
There are a few problems:
- What to do with signals. You didn't get a message but you got a signal.
- What if somebody is sending to you and you die. The kernel doesn't check.
- How does a server find out his process number.
- How do you send messages larger than about 32 bytes.
- How do you know who sent the request, no userids can be checked.
And, last but not least, you can do it with fifos.
Of course the best way to find out about your idea is to implement it, but
I think that for IPC you need a dedicated server like FS or in the kernel
that has access to userids, etc.
Philip
wheeler@IDA.ORG (David Wheeler) (05/25/91)
I wrote: %The original version of Minix did not allow _User Processes_ %to pass messages to OTHER user processes. philip@cs.vu.nl (Philip Homburg) replied: % Please DON'T DO THIS. May be this is too loud and I should whisper "please, % don't do this" but you are looking for trouble. I agree with some of the problems you list, but I'd like to try to fix them.. and thanks for listing some. I think what's needed to make it work is a fair amount of thinking time & relatively little new code. It's essentially like thinking up & verifying communication protocols! There are LOTS of operating systems and languages which already support user-to-user message-passing to some degree, so I disagree that it's _automatically_ a bad idea. They include Mach, QNX, System V, Berkeley, Ada. Many others, too. Communicating sequential processes goes back to Hoare's work & is a very useful capability! This is a fundamental new capability, though, so I completely agree with you that it has to be thought out carefully. What's definitely NOT a good idea is: % And, last but not least, you can do it with fifos. You mean pipes, unnamed or named, right? I want to support user-level servers to other user-level programs. These servers can be started up later, and (rarely) taken down (for example, to replace them with a new & improved version). Unnamed pipes just don't work in this case; there isn't a shared parent who can create a pipe between the client & server. Named pipes are a uniformly AWFUL way to do client/server communication. The server DEFINITELY doesn't know who sent the message, the size of the sent message isn't known, and the server has to do all sorts of work to do named pipe management. All of which is pointless, since the OS itself ``knows'' about all the tasks & is already based on a message-passing system. = There are a few problems: = What to do with signals. You didn't get a message but you got a signal. That's already in the CURRENT SYSTEM. After all, you can send_receive to MM or FS. You can either be sending, server hasn't gotten to you yet, or receiving, your message was received but you haven't been replied to yet. I do need to examine this more carefully, though -- is what the current system does now appropriate? = What if somebody is sending to you and you die. The kernel doesn't check. Actually, the kernel DOES check. Page 473, line 1991. = How does a server find out his process number. getpid(). = How do you send messages larger than about 32 bytes. Some applications won't need more. For those that do: 1. Send multiple messages. or, 2. Modify MM and operations for memory-to-memory moves possible. Clearly this would have to be "agreed to" by both processes, but other OS's do exactly this (I believe Thoth does; anyone know for certain?). = How do you know who sent the request, no userids can be checked. The kernel gets the pid's from the process table (MM's main.c does this). Perhaps calls need to be added to get the process id of the one who sent to you, and/or a uid given a pid. Those would be trivial to add! --- David A. Wheeler wheeler@ida.org
dh4@crosfield.co.uk (damian hamill) (05/28/91)
In article <1991May22.235824.6939@IDA.ORG> wheeler@IDA.ORG (David Wheeler) writes: > >The original version of Minix did not allow _User Processes_ >to pass messages to OTHER user processes. > > >Two questions for the net: > >1. Does the current version (or some modified version everyone uses) >allow this? (From all I can tell it doesn't). > >2. If not, would someone who has the current version of Minix mind >trying out the following modification to allow it? Please? >Or tell me a better way to do it? > [nasty stuff deleted about modifying kernel] > [more nasty stuff deleted about files and things] > Serving programs could ``register'' >themselves with a short name, and clients could request a program by name ^^^^ Now you are on the right track, and what do you know that nice Mr Tannenbaum has already implemented it for you in the network communication tasks (taken from the Amoeba system and referred to as AMOEBA tasks) that came with minix 1.3. Processes simply send and recieve messages to/from a port (which is identified by a character string). There is one distinct advantage with this method, ie you remove location dependancy from your communicating processes. However, one or two subtle issues arise: The network "AMOEBA" tasks (in 1.3 at least) are allocated to processes and thus are associated with one particular instance of IPC, hence the number of processes that can communicate using this method at any one time is limited. The AMOEBA tasks are only BLOCKING processes, this (strictly) supports the client-server model. My final year project was something to do with distributing minix and at times some non blocking primitives would have been appreciated. It's easy peasy lemon squeezy to include the AMOEBA task in your kernel, just read the network documentation that comes with the 1.3 upgrade. I hope this is of interest to you. Damian. -- /*************************************************************************** Damian Hamill Crosfield Electronics ltd, Hemel Hempstead, Herts. UK. dh4@crosfield.co.uk TUNA?? ......NO THANK YOU ***************************************************************************/