Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!sri-unix!hplabs!sdcrdcf!trwrb!desint!geoff From: geoff@desint.UUCP (Geoff Kuenning) Newsgroups: comp.unix.wizards Subject: Re: Streams Loop-Around driver... Message-ID: <287@desint.UUCP> Date: Fri, 23-Jan-87 02:09:38 EST Article-I.D.: desint.287 Posted: Fri Jan 23 02:09:38 1987 Date-Received: Sat, 24-Jan-87 00:02:06 EST References: <1341@cadovax.UUCP> Reply-To: geoff@desint.UUCP (Geoff Kuenning) Organization: Interrupt Technology Corp., Manhattan Beach, CA Lines: 105 In article <1341@cadovax.UUCP> mitchell@cadovax.UUCP (Mitchell Lerner) writes: > Is the Loop-Around driver as shown in the the System V version 3 Streams > Programmers Guide in chapter 12 a way that I can do inter-process > communication? I'm not sure that you can actually open the driver from streams > on two separate processes (or more?) and have the driver connect the two > streams. Can I use this type of Streams driver as the basis for an inter- > process communications facility? Yes, except that you are better off using the "stream pipe" driver, "sp.c", that comes with V.3. Sp.c works by cross-linking stream structures, so it is more efficient. The sp driver performs the cross-link when an M_PROTO (I think that's the right one) control message is sent. The control message contains a pointer to the other stream which is to be cross-linked; this pointer is generated using the I_PASSFP (pass file pointer) ioctl. (The details are undocumented; what you need to know is that the message contains the file pointer at offset zero and nothing else.) The tricky part is that I_PASSFP needs to be sent by someone who has an fd for the relevant stream. To make things clearer, here is the single-process case (the funny ioctl syntax is because the info actually goes through a structure, and I don't remember details): fd 4 (e.g.) fd 5 (e.g.) | | | V | ioctl (5, I_PASSFP (..., 4)) | | V V Stream A Stream B When the PASSFP of fd 4 is sent on fd 5, the cross-link happens and everything is hunky-dory. This is very easy to arrange in a single process, and you then have a two-way stream pipe that can be used much like a regular pipe, notably by forking children. Careful attention to open modes can even make it into a one-way pipe. The no-common-ancestor case is a bit trickier. What saves you is that the I_PASSFP ioctl can be used to pass a file pointer in a data message, which can be read by another process. Here's how I did it for LX-Windows, for Locus Computing Corp: Server: (1) Open up a pair of well-known sp minor numbers (I use the highest two in the sp minor list, e.g., 30 and 31 for 32 sp's) and cross-link them. (2) Enter main "listening" loop. One of the well-known devices is held open, but otherwise ignored. The other is the "connection request" device; the server listens on this stream for new clients. We will assume that 31 is the device the server listens on. (Actually, I give them mnemonic names in /dev). Client: (3) Open the well-known "request" device (minor 30). Also open up an unused 'sp' minor number, creating it with the clone driver. Say we get minor 0. (4) Send a single byte on the "request" device, minor 30. The contents do not matter. Server: (5) When a request byte arrives on minor 31, open up another unused 'sp' minor number with the clone driver. Call this minor 1, and suppose it gets fd 9. (6) Using an I_PASSFP ioctl, send the address of minor 1 (fd 9)'s data structures back out on minor 31 as a *data* message. Note that, in the case of simultaneous requests by multiple clients, we are not sure which client this will go to. However, it turns out that this doesn't hurt us. Client: (7) Read the PASSFP message from minor 30. Since it is a data message, you will receive the value of a kernel pointer to a stream structure. (8) Using the pointer from step 7, create an M_PROTO message and send it on minor 0, which we opened in step 3. This message is *not* sent with I_PASSFP; instead it is sent as an ordinary M_PROTO control message. The sp driver will see this message and cross-link minor 0 to minor 1 (because minor 1 was the pointer passed in step 6). (9) Close the well-known request device (minor 30). The ugly thing about this is that steps 7 and 8 actually take a kernel pointer and pass it back to the kernel via the client process. The REALLY UGLY thing about this is that the sp driver does not do any checking for the validity of the pointer; it grabs it from the message and promptly dereferences it. This is obviously a security hole that you will want to fix if you plan to ship 'sp.c'. One last note: the stream buffer allocation scheme is simply stupid in combination with the high/low water mechanism. I won't go into details, but if you send a lot of small packets that clog up, you will exhaust the stream buffer pool long before you hit the high-water mark. In our case, the X clients used up the pool with line-drawing requests, and the server then couldn't get a buffer to post a mouse-click event that was necessary to terminate the line-drawing requests! -- Geoff Kuenning {hplabs,ihnp4}!trwrb!desint!geoff