|
|
1.1 ! root 1: Using Fifo's: ! 2: ! 3: ! 4: ! 5: Fifo's (first-in first-out pipes) are actually very easy to ! 6: ! 7: use. Here are a couple of things to keep in mind: ! 8: ! 9: ! 10: ! 11: (1) The server program (the one that's going to be listening ! 12: ! 13: for requests from clients) should create the fifo with ! 14: ! 15: Fcreate(). The file descriptor returned from Fcreate is ! 16: ! 17: the "server" descriptor; descriptors returned by Fopen will ! 18: ! 19: be "client" descriptors. Data written to the server descriptor ! 20: ! 21: can be read by client descriptors, and vice-versa. ! 22: ! 23: (2) Fifos are by default bidirectional. You can create a single ! 24: ! 25: directional fifo by creating the fifo "read only"; in this case, ! 26: ! 27: only the server descriptor can be written to, and only client ! 28: ! 29: descriptors can be read from. ! 30: ! 31: (3) Be careful not to mix data up; if two clients are trying to ! 32: ! 33: read from the same fifo at the same time, they each may read ! 34: ! 35: data intended for the other. The easiest way to avoid this is ! 36: ! 37: by having every client lock the fifo before accessing it, ! 38: ! 39: and unlock the fifo when finished. It's also possible (if you're ! 40: ! 41: careful) to use the fact that all writes of <1024 bytes are atomic ! 42: ! 43: (i.e. take place in one "chunk") to avoid interleaving of data; ! 44: ! 45: but locks are probably safer. ! 46: ! 47: ! 48: ! 49: The flags to the Fcreate() system call used to create the fifo can ! 50: ! 51: be used to control the way the fifo works. For most applications, ! 52: ! 53: the flags should probably be 0, i.e. the call should look like ! 54: ! 55: serverfd = Fcreate("U:\\PIPE\\FIFO", 0); ! 56: ! 57: but for some specialized applications it may be useful to use one ! 58: ! 59: or more of the following flags (they may be or'd together: ! 60: ! 61: ! 62: ! 63: FA_RDONLY: Make the fifo unidirectional; the server fd will be write ! 64: ! 65: only, and the client fd read only. ! 66: ! 67: FA_HIDDEN: Make reads from the fifo return "end of file" if no other ! 68: ! 69: process has the fifo open for writing. This is normally not desired ! 70: ! 71: for server processes, since the server's read will often occur ! 72: ! 73: when nobody has the fifo open, and should wait until some client ! 74: ! 75: does want to use the fifo. ! 76: ! 77: FA_SYSTEM: Make the fifo a "pseudo-terminal". This type of fifo behaves ! 78: ! 79: just like a terminal, and most of the terminal control Fcntl calls ! 80: ! 81: can operate on it. Also, data can be passed through the fifo in long ! 82: ! 83: words rather than in bytes, if the Fputchar() system call is used. ! 84: ! 85: This allows the server program to pass the extended BIOS information ! 86: ! 87: (such as the shift key status and scan code) to be returned by Bconin() ! 88: ! 89: calls on the client side of the pipe. The 'extra' 3 bytes of the longword ! 90: ! 91: could also be used for other out of band data as well. ! 92: ! 93: FA_CHANGED: Make the fifo return from an Fread() call as soon as any data are ! 94: ! 95: available (just like a terminal). This isn't necessary if the FA_SYSTEM ! 96: ! 97: bit is set (since pseudo-terminals already act like terminals), but is ! 98: ! 99: useful for making ordinary fifo's emulate Unix pipe semantics. ! 100: ! 101: ! 102: ! 103: Here is a sample pair of applications. The server program ("fortserv.c") ! 104: ! 105: creates a fifo and listens on it for requests. When it receives a ! 106: ! 107: request, it writes a cute saying (a "fortune cookie") back to the fifo. ! 108: ! 109: The client program ("fortune.c") opens the fifo, writes a request, ! 110: ! 111: reads the response, and prints the result on the terminal. These are ! 112: ! 113: very simple minded applications, but it should give you an idea of ! 114: ! 115: the flavour of how to use fifos for interprocess communication. ! 116: ! 117: -------------------------- fortserv.c ------------------------- ! 118: ! 119: /* fortune server: send cookies to clients */ ! 120: ! 121: /* illustrates server side use of fifos */ ! 122: ! 123: ! 124: ! 125: /* ! 126: ! 127: * This program opens a fifo ("U:\PIPE\FORTUNE") ! 128: ! 129: * and listens to requests on that fifo. When it ! 130: ! 131: * gets a request (consisting of a single '?' ! 132: ! 133: * character) it writes back as a reply a 1 byte ! 134: ! 135: * "length" followed by a randomly selected saying. ! 136: ! 137: * BUGS: ! 138: ! 139: * - maximum of 255 characters for a fortune ! 140: ! 141: * - the fortunes aren't particularly interesting ! 142: ! 143: */ ! 144: ! 145: ! 146: ! 147: #ifdef __GNUC__ ! 148: ! 149: #include <minimal.h> ! 150: ! 151: #endif ! 152: ! 153: #include <osbind.h> ! 154: ! 155: #include <mintbind.h> ! 156: ! 157: #include <string.h> ! 158: ! 159: ! 160: ! 161: #define FIFONAME "U:\\PIPE\\FORTUNE" ! 162: ! 163: #define MAXSIZE 255 ! 164: ! 165: ! 166: ! 167: /* witty (?) sayings */ ! 168: ! 169: ! 170: ! 171: char * sayings[] = { ! 172: ! 173: "Core fault -- program dumped.", ! 174: ! 175: "Don't worry, be happy!", ! 176: ! 177: "Help! I'm trapped in a fortune cookie factory!", ! 178: ! 179: "\"Home is where you wear-a your hat.\"", ! 180: ! 181: "I want a cookie.", ! 182: ! 183: "MS-DOS: just say \"no\".", ! 184: ! 185: "Never play leapfrog with a unicorn.", ! 186: ! 187: "No matter where you go, there you are.", ! 188: ! 189: "Sorry, I'm out of short, pithy sayings today.\r\nTry again later.", ! 190: ! 191: "They say that playing NetHack is like walking into a death trap.", ! 192: ! 193: "Vision hazy, try again later.", ! 194: ! 195: "What? You expected something funny?", ! 196: ! 197: "Why is it that UFO's always seem to visit idiots?", ! 198: ! 199: "Your puny intellect is no match for our superior weapons.", ! 200: ! 201: }; ! 202: ! 203: #define NUMSAYINGS (sizeof(sayings) / sizeof(char *)) ! 204: ! 205: ! 206: ! 207: /* file descriptor for the fortune fifo */ ! 208: ! 209: int fd; ! 210: ! 211: ! 212: ! 213: ! 214: ! 215: /* send a witty saying out through the fifo */ ! 216: ! 217: ! 218: ! 219: void ! 220: ! 221: send_saying() ! 222: ! 223: { ! 224: ! 225: int i; ! 226: ! 227: char *s; ! 228: ! 229: char tmpbuf[MAXSIZE+1]; ! 230: ! 231: ! 232: ! 233: /* pick a saying at random */ ! 234: ! 235: i = ((unsigned)Random() >> 1) % NUMSAYINGS; ! 236: ! 237: s = sayings[i]; ! 238: ! 239: ! 240: ! 241: /* construct the message to send */ ! 242: ! 243: i = (int)strlen(s); ! 244: ! 245: tmpbuf[0] = i; ! 246: ! 247: strcpy(tmpbuf+1,s); ! 248: ! 249: ! 250: ! 251: /* we really should check for an error */ ! 252: ! 253: (void)Fwrite(fd, (long)i+1, tmpbuf); ! 254: ! 255: } ! 256: ! 257: ! 258: ! 259: /* main function: create the fifo, then sit around ! 260: ! 261: * listening for requests ! 262: ! 263: */ ! 264: ! 265: ! 266: ! 267: int ! 268: ! 269: main(argc, argv, envp) ! 270: ! 271: int argc; ! 272: ! 273: char **argv, **envp; ! 274: ! 275: { ! 276: ! 277: char c; ! 278: ! 279: long r; ! 280: ! 281: ! 282: ! 283: fd = Fcreate(FIFONAME, 0); ! 284: ! 285: if (fd < 0) { ! 286: ! 287: Cconws("Couldn't create "); ! 288: ! 289: Cconws(FIFONAME); ! 290: ! 291: Cconws("!\r\n"); ! 292: ! 293: Pterm(1); ! 294: ! 295: } ! 296: ! 297: ! 298: ! 299: for(;;) { ! 300: ! 301: r = Fread(fd, 1L, &c); ! 302: ! 303: if (r != 1) { /* read error?? */ ! 304: ! 305: break; ! 306: ! 307: } ! 308: ! 309: if (c == '?') { /* request for saying */ ! 310: ! 311: send_saying(); ! 312: ! 313: } ! 314: ! 315: /* could have other requests here */ ! 316: ! 317: } ! 318: ! 319: return 0; ! 320: ! 321: } ! 322: ! 323: ------------------------ fortune.c ---------------------- ! 324: ! 325: /* fortune client: get a fortune cookie from ! 326: ! 327: * the fortune server ! 328: ! 329: */ ! 330: ! 331: ! 332: ! 333: /* illustrates client side use of fifos */ ! 334: ! 335: ! 336: ! 337: #ifdef __GNUC__ ! 338: ! 339: #include <minimal.h> ! 340: ! 341: #endif ! 342: ! 343: #include <osbind.h> ! 344: ! 345: #include <mintbind.h> ! 346: ! 347: ! 348: ! 349: #define FIFONAME "U:\\PIPE\\FORTUNE" ! 350: ! 351: #define BUFSIZ 256 ! 352: ! 353: #define F_SETLKW 7 ! 354: ! 355: ! 356: ! 357: struct flock { ! 358: ! 359: short l_type; /* type of lock */ ! 360: ! 361: #define F_RDLCK 0 ! 362: ! 363: #define F_WRLCK 1 ! 364: ! 365: #define F_UNLCK 3 ! 366: ! 367: short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ ! 368: ! 369: long l_start; /* start of locked region */ ! 370: ! 371: long l_len; /* length of locked region */ ! 372: ! 373: short l_pid; /* pid of locking process ! 374: ! 375: (F_GETLK only) */ ! 376: ! 377: }; ! 378: ! 379: ! 380: ! 381: int ! 382: ! 383: main(argc, argv, envp) ! 384: ! 385: int argc; ! 386: ! 387: char **argv, **envp; ! 388: ! 389: { ! 390: ! 391: int fd; ! 392: ! 393: char buf[BUFSIZ]; ! 394: ! 395: unsigned char len; ! 396: ! 397: struct flock lock; ! 398: ! 399: long r; ! 400: ! 401: ! 402: ! 403: /* open the fifo */ ! 404: ! 405: fd = Fopen(FIFONAME, 2); ! 406: ! 407: if (fd < 0) { ! 408: ! 409: Cconws("Couldn't open "); ! 410: ! 411: Cconws(FIFONAME); ! 412: ! 413: Cconws("!\r\n"); ! 414: ! 415: Pterm(1); ! 416: ! 417: } ! 418: ! 419: ! 420: ! 421: /* get a lock; this makes sure that two fortune ! 422: ! 423: * programs don't try to send requests and read ! 424: ! 425: * replys at the same time ! 426: ! 427: */ ! 428: ! 429: ! 430: ! 431: lock.l_type = F_WRLCK; ! 432: ! 433: ! 434: ! 435: /* lock the whole file -- only thing that makes sense ! 436: ! 437: * for a fifo ! 438: ! 439: */ ! 440: ! 441: lock.l_whence = 0; ! 442: ! 443: lock.l_start = lock.l_len = 0L; ! 444: ! 445: ! 446: ! 447: r = Fcntl(fd, &lock, F_SETLKW); ! 448: ! 449: if (r != 0) { ! 450: ! 451: Cconws("Couldn't get a lock!\r\n"); ! 452: ! 453: Pterm(r); ! 454: ! 455: } ! 456: ! 457: ! 458: ! 459: /* write the request */ ! 460: ! 461: Fwrite(fd, 1L, "?"); ! 462: ! 463: /* wait for a reply */ ! 464: ! 465: /* the fortune server writes a 1 byte length, followed by ! 466: ! 467: * the fortune itself ! 468: ! 469: */ ! 470: ! 471: r = Fread(fd, 1L, &len); ! 472: ! 473: if (r != 1L || len != Fread(fd, (long)len, buf)) { ! 474: ! 475: Cconws("Error reading fortune!\r\n"); ! 476: ! 477: Pterm(1); ! 478: ! 479: } ! 480: ! 481: buf[len] = 0; ! 482: ! 483: ! 484: ! 485: /* unlock the fifo */ ! 486: ! 487: ! 488: ! 489: lock.l_type = F_UNLCK; ! 490: ! 491: (void) Fcntl(fd, &lock, F_SETLKW); ! 492: ! 493: ! 494: ! 495: Fclose(fd); ! 496: ! 497: ! 498: ! 499: /* now write the fortune to the screen */ ! 500: ! 501: Cconws(buf); ! 502: ! 503: Cconws("\r\n"); ! 504: ! 505: ! 506: ! 507: return 0; ! 508: ! 509: } ! 510:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.