|
|
1.1 ! root 1: .so ../ADM/mac ! 2: .XX ipc 523 "Interprocess Communication" ! 3: .ND ! 4: .TL ! 5: Interprocess Communication ! 6: .br ! 7: in the Ninth Edition ! 8: .UX ! 9: System ! 10: .AU ! 11: D. L. Presotto ! 12: D. M. Ritchie ! 13: .AI ! 14: AT&T Bell Laboratories ! 15: Murray Hill, New Jersey 07974 ! 16: .AB ! 17: .PP ! 18: When processes wish to communicate, they must first establish communication, ! 19: and then decide what to say. ! 20: The stream mechanisms introduced in the Eighth Edition Unix system, ! 21: which have now become part of AT&T's Unix System V|reference(systemv streams), ! 22: provide a flexible way for processes ! 23: to speak with devices and with ! 24: each other: ! 25: an existing stream connection is named by a file descriptor, ! 26: and the usual read, write, and I/O control requests apply. ! 27: Processing modules may be inserted dynamically ! 28: into a stream connection, so ! 29: network protocols, terminal processing, and device drivers separate ! 30: cleanly. ! 31: .PP ! 32: Simple extensions provide new ways of establishing communication. ! 33: In our system, the traditional Unix IPC mechanism, the pipe, is ! 34: a cross-connected stream. ! 35: A new request associates a stream with a named file. ! 36: When the file is opened, ! 37: operations on the file are operations on the ! 38: stream. ! 39: Open files may be passed from ! 40: one process to another over a stream. ! 41: .PP ! 42: These low-level mechanisms allow ! 43: construction of flexible and general ! 44: routines for connecting local and remote processes. ! 45: .AE ! 46: .2C ! 47: .NH 1 ! 48: Introduction ! 49: .PP ! 50: The work reported here provides convenient ways ! 51: for programs to establish communication with unrelated ! 52: processes, on the same or different machines. ! 53: The communication we are interested in is conducted by ! 54: ordinary read and write calls, occasionally supplemented ! 55: by I/O control requests, so that it resembles\(emand, where possible, ! 56: is indistinguishable from\(emI/O to files. ! 57: Moreover, we wish to commence communication in ways that resemble ! 58: the opening of ordinary files, or at least takes advantage of ! 59: the properties of the file system name space. ! 60: .PP ! 61: In particular, we study how to ! 62: .IP 1) ! 63: provide objects nameable as files that invoke useful services, ! 64: such as connecting to other machines over various media, ! 65: .IP 2) ! 66: make it easy to write the programs that provide the services. ! 67: .NH 2 ! 68: Recapitulation ! 69: .PP ! 70: The Eighth Edition system introduced a new way of communicating with ! 71: terminal and network devices|reference(ritchie bltj stream), ! 72: and a generalization of the internal interface to the ! 73: file system|reference(weinberger remote)|reference(killian processes). ! 74: Because the new mechanisms build on these ideas, we ! 75: review the nomenclature and mechanisms ! 76: of our I/O and file systems. ! 77: .NH 2 ! 78: Streams ! 79: .PP ! 80: A ! 81: .I "stream ! 82: is a full-duplex connection between a process and a device ! 83: or another process. ! 84: It consists of several linearly connected processing modules, ! 85: and is analogous to a Shell pipeline, except that ! 86: data flows in both directions. ! 87: The modules in a stream communicate ! 88: by passing messages to their neighbors. ! 89: A module provides only one entry point to each neighbor, namely ! 90: a routine that accepts messages. ! 91: .PP ! 92: At the end of the stream closest to the process ! 93: is a set of routines that provide the interface to the rest of the system. ! 94: A user's ! 95: .I "write ! 96: and ! 97: I/O control requests are turned into messages sent along the stream, ! 98: and ! 99: .I read ! 100: requests take data from the stream and pass it to the user. ! 101: At the other end of the stream is either a ! 102: device driver module, or another process. ! 103: Data arriving from the stream at a driver module ! 104: is transmitted to the device, and ! 105: data and state transitions detected by the device are ! 106: composed into messages and sent into the stream towards the user process. ! 107: Pipes, which are streams connecting processes, ! 108: are bidirectional; ! 109: a writer at either end generates stream messages that are picked up by the reader ! 110: at the other. ! 111: .PP ! 112: Intermediate modules process messages in various ways. ! 113: They come in pairs, for handling messages ! 114: in each of the two directions, and each pair is symmetrical; ! 115: their read and write interfaces are identical. ! 116: .PP ! 117: The end modules in a device stream become connected automatically when ! 118: the process opens the device; ! 119: streams between processes are created by a ! 120: .I pipe ! 121: call. ! 122: Intermediate modules are attached dynamically by request of the user's program. ! 123: They are addressed like a stack with its top close to the process, ! 124: so installing one is called `pushing' a new module. ! 125: .PP ! 126: For example, ! 127: Figure 1 shows a stream device that has just ! 128: been opened. ! 129: The top-level routines, drawn as a pair of half-open rectangles ! 130: on the left, are invoked by users' ! 131: .I read ! 132: and ! 133: .I write ! 134: calls. ! 135: The ! 136: writer ! 137: routine sends messages to the device driver shown on the right. ! 138: Data arriving from the device becomes ! 139: messages sent to the top-level ! 140: reader ! 141: routine, which returns the data to the user process ! 142: when it executes ! 143: .I read . ! 144: .1C ! 145: .so pfig1 ! 146: .2C ! 147: .PP ! 148: Figure 2 shows a stream with intermediate modules. ! 149: This arrangement might be used when a terminal is connected to the computer ! 150: through a network. ! 151: The leftmost intermediate module carries out processing ! 152: (such as character-erase and line-kill) needed for terminals, while ! 153: the rightmost intermediate module does the ! 154: flow- and error-control ! 155: protocol needed to interface to the network. ! 156: .1C ! 157: .so pfig2 ! 158: .2C ! 159: .PP ! 160: Finally, Figure 3 ! 161: shows the connections for a pipe. ! 162: .1C ! 163: .so pfig3 ! 164: .2C ! 165: .NH 2 ! 166: File Systems ! 167: .PP ! 168: Weinberger|reference(weinberger remote) ! 169: generalized the file system ! 170: by identifying a small set of primitive operations on files ! 171: (read, write, look up name, truncate, get status, etc.: a total of 11) ! 172: and modifying the ! 173: .I mount ! 174: request so that it specifies a file system type and, where appropriate, ! 175: a stream. ! 176: When file operations are requested, the calls to the underlying ! 177: primitives are routed through a switch table indexed by the ! 178: type. ! 179: Where the standard file system type performs operations directly ! 180: on a disk, ! 181: a second type generates remote procedure calls ! 182: across the associated stream. ! 183: At the other end of the stream, which usually goes over ! 184: a network to another machine, is a server process ! 185: that answers the calls to read and write data and perform the other operations. ! 186: This scheme thus provides a remote file system. ! 187: In general structure, this arrangement is analogous ! 188: to that used by AT&T's RFS|reference(RFS att remote file system) ! 189: and Sun Microsystems' NFS|reference(NFS sun remote file system). ! 190: .PP ! 191: Pike's `face server'|reference(pike face) ! 192: appears to be an ordinary remote file system, ! 193: but his server simulates a hierarchy containing images classified by ! 194: machine, person name, and resolution. ! 195: The apparent structure of the hierarchy as viewed by ! 196: a client differs considerably from ! 197: its actual layout on the server's machine. ! 198: .PP ! 199: Killian|reference(killian processes) ! 200: added a file system type that ! 201: appears to be a directory containing the names (process ID numbers) ! 202: of currently running processes. ! 203: Once a process file is opened, its memory may be read or written, ! 204: and control operations can start it or stop it. ! 205: This simplifies the construction of sophisticated debuggers, ! 206: for example Cargill's process-inspector ! 207: .I pi |reference(cargill blit pi 1983). ! 208: .NH 1 ! 209: Establishing Communication ! 210: .PP ! 211: Traditional Unix systems provide few ways for a process ! 212: to establish communication with another. ! 213: The oldest one, the pipe, has proved astonishingly valuable ! 214: despite its limitations, and indeed remains central in the design ! 215: we shall describe. ! 216: Its cardinal limitation is, of course, that it is anonymous, ! 217: and cannot be used to create a channel between unrelated processes. ! 218: .PP ! 219: More recently, ! 220: AT&T's System V has offered a variety of communication mechanisms including ! 221: semaphores, messages, and shared memory. ! 222: They are all useful in certain circumstances, but programs that ! 223: use them are all special-purpose; they know that they are communicating ! 224: over a certain kind of channel, and must use special calls and techniques. ! 225: System V also provides named pipes (FIFOs). ! 226: They reside in the file system, and ordinary I/O operations ! 227: apply to them. ! 228: They can provide a convenient place for processes to meet. ! 229: However, because the messages of all writers are intermingled, ! 230: writers must observe a carefully designed, application-specific protocol ! 231: when using them. ! 232: Moreover, FIFOs supply only one-way communication; ! 233: to receive a reply from a process reached through ! 234: a FIFO, a return channel must be constructed somehow. ! 235: .PP ! 236: Berkeley's 4.2 BSD system introduced ! 237: .I sockets ! 238: (communication connection points) ! 239: that exist in domains (naming spaces). ! 240: The design is powerful enough to provide most of the needed facilities, ! 241: but is uncomfortable in various ways. ! 242: For example, unless extensive libraries are used, creating a new ! 243: domain implies additions to the kernel. ! 244: Consider the problem of adding a `phone' domain, in which the addresses ! 245: are telephone numbers. ! 246: Should complicated negotiations with various kinds of ! 247: automatic dialers be added to the kernel? ! 248: If not, how can the required code be invoked in user mode ! 249: when a program calls ! 250: 4.2 BSD's ! 251: .I connect ! 252: primitive? ! 253: .PP ! 254: Another problem with the socket interface is that it exposes ! 255: peculiarities of the domain; ! 256: various domains support very different kinds of name ! 257: (for example, 32-bit Internet address versus character string), and it is difficult ! 258: to deal with the names in a general way. ! 259: Similarly, the details of option processing and other aspects of ! 260: each domain's protocols complicate an interface that attempts generality. ! 261: .NH 1 ! 262: New System Mechanisms ! 263: .PP ! 264: Two small additions to the operating system allowed us to build ! 265: a variety of communication mechanisms, which will be ! 266: described below. ! 267: .NH 2 ! 268: Generalized Mounting ! 269: .PP ! 270: Traditionally, the ! 271: .I mount ! 272: request attaches a disk containing ! 273: a new piece of the file system tree at a leaf of the existing structure. ! 274: In the Ninth Edition, it takes the form ! 275: .P1 ! 276: mount(type, fd, name, flag); ! 277: .P2 ! 278: in which ! 279: .I type ! 280: identifies the kind of file system, ! 281: .I fd ! 282: is a file descriptor, ! 283: .I name ! 284: is a string identifying a file, and ! 285: .I flag ! 286: may specify a few options. ! 287: Like its original version, this call attaches a new file system structure ! 288: atop the file ! 289: .I name ! 290: in the existing file hierarchy. ! 291: The operating system gains access to the contents of newly-attached file tree ! 292: by communicating over the descriptor ! 293: .I fd, ! 294: according to a protocol appropriate for the new file system ! 295: .I type. ! 296: For example, ordinary disk volumes have type ! 297: .I ordinary, ! 298: and the file descriptor is the special file for ! 299: the disk, while ! 300: remote file systems use type ! 301: .I remote, ! 302: and the descriptor ! 303: refers to a stream connection to a server that understands ! 304: the appropriate RPC messages. ! 305: Some types are handled entirely internally; ! 306: for example, the `proc' type ignores the file descriptor. ! 307: .PP ! 308: We added a new, very simple, file system type. ! 309: Its ! 310: .I mount ! 311: request merely attaches the file descriptor (which must be a stream) to ! 312: the file. ! 313: Subsequently, when processes open and do I/O on that file, ! 314: their requests refer to the stream mounted on the file. ! 315: Often, the stream is one end of a pipe created by a server ! 316: process, but it can equally well be a connection to a device, ! 317: or a network connection to a process on another machine. ! 318: The effect is similar to a System V FIFO that has already been opened ! 319: by a server, but more general: communication is full-duplex, ! 320: the server can be on another machine, and (because the connection is a stream), ! 321: intermediate processing modules may be installed. ! 322: .NH 2 ! 323: Passing Files ! 324: .PP ! 325: By itself, a mounted stream shares an important difficulty ! 326: of the FIFO; ! 327: several processes attempting to use it simultaneously must ! 328: somehow cooperate. ! 329: Another addition facilitates this cooperation: ! 330: an open file may be passed ! 331: from one process to another across a pipe connection. ! 332: The primitives may be written ! 333: .P1 ! 334: sendfile(wpipefd, fd); ! 335: .P2 ! 336: in the sender process, and ! 337: .P1 ! 338: (fd1, info) = recvfile(rpipefd); ! 339: .P2 ! 340: in the receiver. ! 341: By using ! 342: .I sendfile, ! 343: the sender transmits a copy of its file descriptor ! 344: .I fd ! 345: over the pipe to the receiver; ! 346: when the receiver accepts it by ! 347: .I recvfile, ! 348: it gains a new open file denoted by ! 349: .I fd1. ! 350: (Other information, such as the user- and group-id of the sender, ! 351: is also passed.) ! 352: The facility may be used only locally, over a pipe; ! 353: we do not attempt to extend it to remote systems. ! 354: .PP ! 355: A similar facility is available in the 4.3 BSD system|reference(bsd43manual), ! 356: but is little-used, possibly because in earlier versions ! 357: the related socket facilities were buggy. ! 358: It will appear in future versions of Unix System V. ! 359: .NH 1 ! 360: Simple Examples ! 361: .PP ! 362: A graded set of examples will illustrate how these mechanisms ! 363: can solve problems that vex other systems. ! 364: .NH 2 ! 365: Talking to Users ! 366: .PP ! 367: When a user logs in to traditional Unix systems, an entry is made in the ! 368: .CW /etc/utmp ! 369: file, recording the login name and the terminal or network channel ! 370: being used. ! 371: Although this file is often used merely to show who is where, ! 372: it is also used to establish communication with the user. ! 373: For example, the ! 374: .I write ! 375: command and the mail-notification service look up ! 376: a user's name, and send a message ! 377: to the corresponding terminal. ! 378: This simple scheme does not work well with windowing terminals, ! 379: because the messages disturb the protocol between ! 380: the host and the terminal, and because there is no obvious way ! 381: to relate the terminal's special file to a particular window. ! 382: Even without windows, there are security problems and other difficulties ! 383: that follow from letting users write on each other's terminals. ! 384: .PP ! 385: We use stream-mounting to interpose a program ! 386: between a terminal special file and the terminal itself. ! 387: The program, called ! 388: .I vismon , ! 389: mounts one end of a pipe on the user's terminal. ! 390: Normally it occupies an inconspicuous window, displaying system ! 391: activity and announcing arriving mail. ! 392: When some other process opens and writes on the special file ! 393: for the terminal, the mounted stream receives the data; ! 394: .I vismon ! 395: creates a new window, and copies this data to it. ! 396: The new window has a shell, so that if the message was ! 397: from a ! 398: .I write ! 399: command, the recipient can write back. ! 400: .PP ! 401: Communication between the terminal and the windowing ! 402: multiplexor on the host is not disturbed; ! 403: it continues to flow to the terminal itself, not to ! 404: .I vismon, ! 405: because the ! 406: .I mount ! 407: operation affects only the interpretation of file names, ! 408: not existing file descriptors. ! 409: .NH 2 ! 410: Network Calling: Simple Form ! 411: .PP ! 412: Making a network connection is a complicated activity. ! 413: There is often name translation of various kinds, ! 414: and sometimes negotiations with various entities. ! 415: With the Datakit\(rg VCS network|reference(datakit asynchronous), ! 416: for example, a call is placed ! 417: by negotiating with a node controller. ! 418: When dialing over the switched telephone system, one must talk ! 419: to any of several kinds of automatic dialers. ! 420: Setting up a connection on an Internet ! 421: under any of the extant protocols requires translation of ! 422: a symbolic name to a net address, and then special communication ! 423: with the remote host. ! 424: These setup protocols should certainly not be in kernel code, so ! 425: most systems package them in user-callable libraries. ! 426: .PP ! 427: With our primitives, it is straightforward to encapsulate a ! 428: network-connection algorithm to a single executable program. ! 429: A application desiring to make an outward connection calls a simple routine ! 430: that creates a pipe, forks, and in the child process executes the ! 431: network dialer program. ! 432: The dialer passes back either an error code, or a file descriptor ! 433: referring to an open connection to the other machine. ! 434: The pseudo-code for this library routine, ! 435: neglecting error-checking and closing down the pipe, is: ! 436: .P1 0 ! 437: netcall(address) ! 438: { int p[2]; ! 439: ! 440: pipe(p); ! 441: if (fork()!=0) ! 442: execute("/etc/netcaller", ! 443: address, p[0]); ! 444: .P3 ! 445: status = wait(); ! 446: if (bad(status)) ! 447: return(errcode); ! 448: passedinfo = recvfile(p[1]); ! 449: return(passedinfo.fd); ! 450: } ! 451: .P2 ! 452: The ! 453: .CW /etc/netcaller ! 454: program can be arbitrarily complicated, but does not occupy the ! 455: same address space as its caller. ! 456: In this way, if something in the network interface changes, ! 457: only one program needs to be fixed and reinstalled. ! 458: Its job is to create the connection, and pass its descriptor ! 459: for the open connection; it then terminates, and is no ! 460: longer involved in the connection. ! 461: Along the way, it may negotiate permissions and provide the caller's ! 462: identity reliably, because it can be a privileged (set-uid) program. ! 463: Thus, the segregation of the program that does the actual call setup ! 464: from its client is important. ! 465: When connections are made by library routines, ! 466: the operating system must know enough about ! 467: the call setup protocols to authenticate the caller to the target system. ! 468: In the method described above, this task need not be done in kernel code. ! 469: Even shared libraries, which do reduce the bulk of ! 470: code included with each program that makes network connections, ! 471: run in the protection domain of the person who ! 472: executes them. ! 473: .NH 2 ! 474: Process Connections ! 475: .PP ! 476: Suppose you are writing a multi-player game, ! 477: in which several people interact with each other. ! 478: One design uses a pair of programs: ! 479: a controller process that runs throughout the game and ! 480: coordinates ! 481: the play, and a player program, with one instance for each player, ! 482: that communicates with the controller. ! 483: .PP ! 484: When the controller starts, ! 485: it creates a conventionally-located file, stream-mounts ! 486: one end of a pipe on this file, ! 487: and waits for connection messages to arrive from players. ! 488: When the player program is run, it opens ! 489: the communication file, and creates its own pipe. ! 490: It starts communication by sending one end of this pipe to the ! 491: game controller over the communication file. ! 492: .PP ! 493: As each passed pipe appears on the controller's connection stream, ! 494: it accepts the connection with ! 495: .I recvfile. ! 496: Thereafter, each player transmits moves and receives replies ! 497: over its end of the pipe; ! 498: the controller reads players' moves and transmits replies ! 499: over the end it received. ! 500: It maintains the global state of the game, and uses the ! 501: .I select (2) ! 502: mechanism ! 503: to multiplex connection requests and the communication with the ! 504: player programs. ! 505: .NH 1 ! 506: The Connection Server ! 507: .PP ! 508: The final example illustrates a general ! 509: connection server. ! 510: It combines ideas used by the initial network-calling ! 511: scheme and the game design, described above, ! 512: to create a flexible switchboard ! 513: through which programs can connect to remote or local services. ! 514: .PP ! 515: Two things are necessary for handling server-client relationships: ! 516: first, some program must establish itself as a server, ! 517: and wait for requests for the service; ! 518: and second, programs must make requests. ! 519: We will first describe the external appearance of the scheme (the ! 520: library entry points), then the addressing and naming, and then the implementation. ! 521: .PP ! 522: A program that desires to make a connection calls the routine ! 523: .I ipcopen, ! 524: passing a string ! 525: of characters that specifies the address and the desired service at ! 526: that address. ! 527: .P1 ! 528: fd = ipcopen(service); ! 529: .P2 ! 530: The ! 531: .I ipcopen ! 532: routine returns a file descriptor connected to the requested server. ! 533: If it fails, a string describing the error is available. ! 534: .PP ! 535: In order to announce a service, ! 536: .I ipccreat ! 537: is used; ! 538: its argument is a string that names the service. ! 539: The return value is a file descriptor ! 540: .I fd ! 541: that is a channel on which connection requests will be sent. ! 542: .P1 ! 543: fd = ipccreat(service); ! 544: .P2 ! 545: To wait for requests, the server uses the ! 546: .I ipclisten ! 547: routine. Its argument is the same ! 548: .I fd ! 549: returned by ! 550: .I ipccreat: ! 551: .P1 ! 552: ip = ipclisten(fd); ! 553: .P2 ! 554: .I Ipclisten ! 555: returns when some program calls ! 556: .I ipcopen ! 557: with an argument corresponding to the service, in a way discussed below. ! 558: The return value ! 559: is a structure containing ! 560: information about the caller, such as the user name, and, ! 561: where relevant, the name of the machine from which the call was placed. ! 562: This new connection may be rejected: ! 563: .P1 ! 564: ipcreject(ip, errcode); ! 565: .P2 ! 566: or it may be accepted: ! 567: .P1 ! 568: fd = ipcaccept(ip, cfd); ! 569: .P2 ! 570: If the server itself is capable of handling all communication with ! 571: its client, it passes a null file descriptor as ! 572: .I cfd, ! 573: and uses the return value of ! 574: .I ipcaccept ! 575: as a file descriptor to communicate with its client. ! 576: Depending on the locations of the server and the client, ! 577: this may be either a pipe, or a stream connection to a remote machine. ! 578: .PP ! 579: Sometimes, the purpose of a server is not to communicate directly, ! 580: but to set up another connection on behalf of its client. ! 581: A network dialing server, for example, receives the desired address ! 582: in the ! 583: .I ip ! 584: structure returned by ! 585: .I ipclisten, ! 586: and connects to this address with network-specific primitives. ! 587: If the connection succeeds, the server sends the descriptor ! 588: for the connection to the client using the ! 589: .I cfd ! 590: argument of ! 591: .I ipcaccept. ! 592: .PP ! 593: The various file descriptors in these calls all work properly ! 594: with the ! 595: .I select ! 596: system call, so a single program may issue several ! 597: .I ipccreat ! 598: calls, and wait for a connection to appear before committing ! 599: itself to using ! 600: .I ipclisten ! 601: on any one of them. ! 602: .NH 2 ! 603: Addresses ! 604: .PP ! 605: The arguments supplied to ! 606: .I ipcopen ! 607: and ! 608: .I ipccreat ! 609: are strings with several components ! 610: separated by exclamation mark `!' characters. ! 611: The first part is interpreted as a file name. ! 612: If it is absolute, it is used as is; otherwise, it is interpreted as ! 613: a file in the directory ! 614: .CW /cs , ! 615: which we use, conventionally, to collect rendezvous points. ! 616: For example, a game controller like that discussed ! 617: in a previous section might announce itself with ! 618: .P1 ! 619: ipccreat("mazewar"); ! 620: .P2 ! 621: The player program could then connect to the controller with ! 622: .P1 ! 623: ipcopen("mazewar"); ! 624: .P2 ! 625: In this simple case, the IPC routines merely accomplish a convenient ! 626: packaging of the scheme discussed above. ! 627: .PP ! 628: When a multi-component argument is given to ! 629: .I ipcopen, ! 630: the server selected by the first component receives the remaining ! 631: components ! 632: as part of the ! 633: .I ip ! 634: structure returned by its ! 635: .I ipclisten, ! 636: and interprets them according to its own conventions. ! 637: For example, there is a dialing server for each kind of network. ! 638: If the first component of an ! 639: .I ipcopen ! 640: specifies a network server, ! 641: the remaining components conventionally supply an address ! 642: within that network, and possibly a service obtainable at that address. ! 643: We have three kinds of networks: ! 644: .I tcp ! 645: (TCP/IP connection), ! 646: .I dk ! 647: (Datakit connection), and ! 648: .I phone ! 649: (dial-up telephone). ! 650: Each network server adopts the convention that a missing service name ! 651: means a connection to an end-point that allows one to log in by hand. ! 652: Therefore, calling ! 653: .I ipcopen ! 654: with the strings ! 655: .P1 ! 656: tcp!research.att.com ! 657: dk!nj/astro/research ! 658: phone!201-582-5940 ! 659: .P2 ! 660: gets connections over which one will receive a `login:' greeting, ! 661: each over a different kind of network. ! 662: The servers are responsible for the details of name translation, ! 663: performing the appropriate connection protocol, and so forth. ! 664: Some examples of named services at particular locations are ! 665: .P1 ! 666: tcp!dutoit.att.com!whoami ! 667: dk!research!smtp ! 668: .P2 ! 669: The first is a debugging service that echoes facts about the ! 670: connection and the user ID of the person who requests it. ! 671: The second illustrates how remote mail is sent; ! 672: by connecting to the ! 673: .I smtp ! 674: server (mail receiver) on the appropriate machine. ! 675: .NH 2 ! 676: IPC Implementation ! 677: .PP ! 678: For a simple service, the ! 679: .I ipccreat ! 680: routine works just like the ! 681: game-manager program described above; it first creates a file in the ! 682: .CW /cs ! 683: directory corresponding to the name of the service, then makes ! 684: a pipe and stream-mounts one end of the pipe on this file. ! 685: For complex services, which have a `!' in their names, the ! 686: simple service named to the left of the `!' must be created first; ! 687: when ! 688: .I ipccreat ! 689: is handed the name of such a service, it uses ! 690: a version of ! 691: .I ipcopen ! 692: referring to the simple, underlying server, and passes it the remainder ! 693: of the name. ! 694: In either case, ! 695: .I ipccreat ! 696: returns its own end of its pipe, ready to receive requests. ! 697: .PP ! 698: The ! 699: .I ipcopen ! 700: routine uses a technique that resembles that used by the ! 701: simple network calling routine described above, but differs ! 702: in detail. ! 703: It opens the file in ! 704: .CW /cs ! 705: corresponding to the desired service, makes a pipe, and hands ! 706: one end of the pipe to the server. It then sends the actual contents ! 707: of the request (the full address) to its end of the pipe, ! 708: and waits for an acceptance or rejection message to appear on ! 709: this pipe. ! 710: .PP ! 711: The server ! 712: .I ipclisten ! 713: call waits for a stream (passed by someone's ! 714: .I ipcopen ) ! 715: to appear on the file descriptor mounted on its ! 716: .CW /cs ! 717: communication file; as each appears, ! 718: it reads the request block from the passed stream, ! 719: and returns it to the server. ! 720: .PP ! 721: After analyzing the request, the server calls either ! 722: .I ipcaccept ! 723: or ! 724: .I ipcreject; ! 725: each sends an appropriate message back to the client over the passed ! 726: stream. ! 727: .I Ipcaccept ! 728: has two cases: ! 729: when its ! 730: .I cfd ! 731: argument is empty, the same pipe sent to ! 732: the server by the client is used for communication; when ! 733: .I cfd ! 734: is non-empty, ! 735: that file descriptor is sent back to the client. ! 736: .I Ipcopen ! 737: returns the appropriate descriptor. ! 738: .NH 2 ! 739: Network Managers ! 740: .PP ! 741: The IPC routines discussed above handle both clients and servers ! 742: that are local to a single system, and are also sufficient to accomplish ! 743: outgoing network connections. ! 744: One missing piece is how to write the programs ! 745: that accept connections from a network, and arrange to invoke ! 746: the appropriate local services. ! 747: We call such programs ! 748: .I managers. ! 749: .PP ! 750: The networking part of a manager is specific to its ! 751: network, and usually must conduct dialogues both with the ! 752: operating system and with its remote client. ! 753: For example, the manager for TCP/IP must arrange ! 754: to receive IP packets sent to certain port numbers, ! 755: and analyze the packets to determine what service is being ! 756: requested; ! 757: then it must select a port number for ! 758: the conversation, communicate it to the peer, and arrange to collect ! 759: packets on this port number. ! 760: Finally, the manager must supply the selected local service. ! 761: Each network manager could have ! 762: .I "ad hoc" ! 763: code for this part of the job; ! 764: instead, they depend on a more general program called the ! 765: .I "service manager. ! 766: .NH 2 ! 767: The Service Manager ! 768: .PP ! 769: By using ! 770: .I ipccreat, ! 771: a process establishes itself as a server and prepares to receive requests. ! 772: While it is serving, it must remain in existence. ! 773: For some servers, like the multi-player game controller that ! 774: continues to run as users enter and leave the game, ! 775: the longevity of the server is appropriate. ! 776: However, many, or even most, useful services do not necessarily ! 777: need individual long-lived servers, because the service merely involves ! 778: execution of a particular program. ! 779: For example, services like ! 780: .I rlogin, ! 781: .I telnet, ! 782: .I smtp ! 783: and ! 784: .I ftp, ! 785: as well as simpler ones that merely provide the ! 786: date, or send a file to a line printer, can all ! 787: be accomplished merely by running the appropriate program ! 788: with input and output connected to the right place. ! 789: Even when the characteristics of such services differ ! 790: in detail, there are general patterns. ! 791: Some, for example, require no authentication, some require checking ! 792: of authentication according to an automatic scheme, and others ! 793: always insist on a password. ! 794: .PP ! 795: The observation that many services share a common structure ! 796: suggested a common solution: the Service Manager. ! 797: It is started when the operating system is booted, and is ! 798: driven by a specification file; ! 799: each entry in the file ! 800: contains the name of the service, and a list of actions ! 801: to be performed when that service is requested. ! 802: The service manager issues ! 803: .I ipccreat ! 804: for the name given in each entry; when another process uses ! 805: .I ipcopen ! 806: to request the service, the service manager carries out each ! 807: encoded action. ! 808: .PP ! 809: The most important action specifies a command to be executed; ! 810: for example, the line ! 811: .P1 0 ! 812: date cmd(date) ! 813: .P2 ! 814: means that connecting to the service ! 815: .I date ! 816: would run the `date' command. ! 817: Other actions may specify the user ID under which the program ! 818: is run: ! 819: .P1 0 ! 820: uucp user(uucp)+cmd(/usr/lib/uucp/uucico) ! 821: .P2 ! 822: This service specifies a passwordless connection to the ! 823: .I uucp ! 824: file-transfer program; ! 825: a locally-conventional TCP/IP port ! 826: number is used for such connections, and a corresponding convention ! 827: is used on our Datakit network. ! 828: There are other built-in actions: ! 829: .P1 0 ! 830: login ttyld+password ! 831: .P2 ! 832: means that the ! 833: .I login ! 834: service needs to install the line discipline module for terminal ! 835: processing, and also to execute the ! 836: .I login ! 837: command; ! 838: .P1 0 ! 839: oklogin auth+ttyld+login ! 840: .P2 ! 841: is similar, but allows passwordless login. ! 842: Authorization is checked by the ! 843: .I auth ! 844: specification, which determines whether the call came from a ! 845: trusted host on a trusted network, so that the passed user ID ! 846: can be believed. ! 847: .NH 1 ! 848: Uses ! 849: .PP ! 850: The techniques described in this paper permit a general approach ! 851: to network and local connections in which most of the work ! 852: is done in a few user-mode programs. ! 853: As an example of the benefits of the scheme, we have unified ! 854: various commands that do remote login over two kinds of networks ! 855: (TCP/IP and Datakit). ! 856: A single command, ! 857: .I con, ! 858: tries various networks and uses the first over which a connection ! 859: can be made. ! 860: The traditional names (like ! 861: .I rlogin ) ! 862: are retained as links, but the only effect of using them is to ! 863: influence the order in which networks are tried. ! 864: The stream implementation makes the transport layers of the networks ! 865: sufficiently similar ! 866: that the same code can be used once the connection is established; ! 867: the techniques described here make even the connection interface uniform. ! 868: .PP ! 869: These same techniques extend well to inter-network connectivity. ! 870: For example, all our machines have a ! 871: Datakit interface, but only a few have Ethernet connections. ! 872: Nevertheless, from a Datakit-only machine, ! 873: it is easy to connect to another machine that ! 874: has only Ethernet, even one that does not run the ! 875: Ninth Edition system. ! 876: There are two schemes. ! 877: In the first, ! 878: the local operating system contains the TCP/IP protocol ! 879: code, and below the TCP/IP level, the `device' interface is ! 880: actually a Datakit connection to another local machine on both networks. ! 881: Because Datakit channels and the network layer expected by ! 882: TCP/IP have stream interfaces, they are easily connected; ! 883: on the gateway machine, ! 884: the IP packets are routed appropriately. ! 885: This approach transparently handles other services, like UDP, ! 886: that use the IP protocol. ! 887: .PP ! 888: The other scheme uses the methods described in this paper. ! 889: On the Datakit-only machine, ! 890: the TCP network dialout program does not ! 891: use TCP/IP at all, and indeed TCP/IP code need not be configured into ! 892: the operating system; ! 893: instead, it creates a Datakit transport-level connection ! 894: to a protocol-conversion server on a gateway machine. ! 895: A complementary server on the gateway accepts TCP/IP ! 896: connections on behalf of the Datakit-only machine, and forwards them. ! 897: The difference between the two schemes is invisible to ! 898: users of connection-oriented protocols, although it does not support ! 899: connectionless protocols like UDP. ! 900: .NH 1 ! 901: Conclusion ! 902: .PP ! 903: Unix has always had a rich file system structure, ! 904: both in its naming scheme (hierarchical directories) ! 905: and in the properties of open files (disk files, devices, pipes). ! 906: The Eighth Edition exploited the file system even more insistently ! 907: than its predecessors ! 908: or contemporaries of the same genus. ! 909: Remote file systems, process files, and the face server ! 910: all create objects with names that can ! 911: be handed as usefully to an existing tool ! 912: as to a new one designed to take advantage of the object's special ! 913: properties. ! 914: Similarly, the stream I/O system ! 915: provides a framework for making file descriptors ! 916: act in the standard way most programs already expect, ! 917: while providing a richer underlying behavior, ! 918: for handling network protocols, or processing appropriate ! 919: for terminals. ! 920: .PP ! 921: The developments described here follow the same path; ! 922: they encourage use of the file name space ! 923: to establish communication between processes. ! 924: In the best of cases, ! 925: merely opening a named file is enough. ! 926: More complicated situations require more involved negotiations, ! 927: but the file system still supplies the point of contact. ! 928: Moreover, the necessary negotiations ! 929: may be encapsulated in a common form that hides the differences between ! 930: local and any of a variety of remote connections. ! 931: .NH 1 ! 932: References ! 933: .LP ! 934: |reference_placement
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.