|
|
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.