.
contact contact

Connecting unrelated HP-UX processes with FIFOs

 
.
  A FIFO combines features of a file and a pipe. Like a file, it has a name, and any process with the appropriate permissions may open it for reading or writing. Unlike with a pipe, then, unrelated processes may communicate over FIFO, since they need not rely on inheritance to access it. Once opened, however, a FIFO acts more like a pipe than a file. Written data is read back in first-in-first-out order, and single write and read system calls are garanteed to be atomic, provided the amount read or write doesn't exceed the capacity of the FIFO, which is the same as the capacity of a pipe (implementation dependent, but at least 4096 bytes). Data once read can't be read again, nor is it possible to position into FIFO.

Normally, when a FIFO is opened for reading, the open waits until it is also opened for writing, usually by another process. Similary, an open for writing blocks until the FIFO is opened for reading. Hence whichever process, reader or writer, executes the open first will wait for the other one. This allowes the processes to synchronize themselves before the actual data transmission starts.

Some statements and functions known from the "File storage" section will behave different operating on FIFOs.

ASSIGN
ASSIGN statement won't lock a FIFO file (it's intended to be used concurrently) unless you explicy use the LOCK# or UNLOCK # statements.

If you close a FIFO file, and you're the last process opened the FIFO in write mode, an EOF condition (which may be trapped using and ON END statement) will be raised.

NOTE: ASSIGNing an FIFO file may result in blocking the program if not executed in the appropritate order

PRINT #, READ #
READ # and WRITE # statements will behave like operating on a HP-UX sequential file. However any attempt to position into FIFO file will be ignored.

NOTE: All data in a single PRINT# statement will be cached in an internal buffer. To flush this buffer just issue an PRINT# statement with an END keyword.

SIZE
The SIZE function will return the number of bytes in the FIFO file. You might check this value to avoid blocking due to overflow.


A FIFO must be created using the HP-UX mkfifo command.

COMMAND "!mkfifo FIFO.DATA"
will create the FIFO file FIFO.DATA.


Example unidirectional message passing

To execute the example program, start eloq, ATTACH to secondary task and run FIFO program. Then DETACH back to foreground and run FIFO program. After termination ATTACH to secondary task and inspect the messages.

1000 ! RE-STORE "FIFO,TEST"
1010 !  SAMPLE UNIDIRECTIONAL MESSAGE PASSING
1011 ! 
1012 !  To execute sample program, start eloq, ATTACH to secondary task
1013 !  and run FIFO program. Then DETACH back to foreground and run
1014 !  FIFO program. After termination ATTACH to secondary task and
1015 !  inspect the messages.
1016 !  With little modification this could also be executed too by
1017 !  different (unrelated) tasks.
1020 ! 
1030 ! INITIAL ------------------------------------
1040 ! name of fifo file
1050       Fifo$="FIFO,TEST"
1060 ! create fifo, ignore any error
1070       COMMAND "!mkfifo "&MAPFNAME$(Fifo$)&".DATA; exit 0"
1080 ! execute slave part if secondary task
1090       IF OWNID THEN Slave
1100 ! 
1110 ! MASTER PART --------------------------------
1120 Master:! 
1130 ! open fifo
1140       ASSIGN #1 TO Fifo$
1150       ON KEY #1:"SEND" GOSUB Send
1160       ON KEY #8:"EXIT" GOTO Exit
1170       WAIT 
1180 Exit:! 
1190 ! this will cause an eof on slave side
1200       ASSIGN * TO #1
1210 ! remove fifo file
1220       COMMAND "!rm "&MAPFNAME$(Fifo$)&".DATA"
1230       STOP
1240 Send:! 
1250       LDISP "Sending message ..."
1260 ! write to fifo
1270 ! note: this will block if no more space in fifo
1280 !       SIZE may be checked before
1290       PRINT #1;"Ok"
1300       RETURN 
1310 ! 
1320 ! SLAVE PART ---------------------------------
1330 Slave:! 
1331 ! DETACH to primary task
1335       DETACH
1340 ! open fifo
1350 ! note: this will block until master side has been opened
1360       ASSIGN #1 TO Fifo$;READONLY
1370 ! catch eof
1380       ON END #1 GOTO Eof
1390       LOOP
1400          LDISP "waiting for message ..."
1410 ! read data from fifo, this will block until data are available
1420          READ #1;A$
1430          LDISP TIME$;":";A$
1440       END LOOP
1450 Eof:  LDISP ""
1460       END

Bi-directional pipes

This example program, will pass some data to the HP-UX cat command and read the output again.

1000 ! RE-STORE "FIFO2,TEST"
1010 ! Bi-directional pipes
1020       DIM A$[256]
1030       Fifo$="FIFO,TEST"
1040       R=1
1050       W=2
1060 ! 
1070 !     LOAD SUB "COUTIL,TEST"
1080       LDISP "Creating co process ..."
1090       C=CLOCK
1100       CALL Co_create(Fifo$,"cat",#W,#R)
1110       DISP (CLOCK-C)/1000;"Seconds"
1120 ! 
1130       C=CLOCK
1140       FOR I=1 TO 9
1141 ! 
1142 ! Send data to connected process
1150          FOR J=1 TO I
1160             A$="I="&VAL$(I)&",J="&VAL$(J)
1170             CALL Co_send(#W,A$)
1180          NEXT J
1181 ! 
1182 ! Flush buffer to avoid overflow in send
1190          CALL Co_flush(#W)
1210 ! 
1220 ! now check for anything in receive buffer to prevent blocking
1230          WHILE SIZE(R)
1240             IF NOT FNCo_read(#R,A$) THEN Eof
1250             GOSUB Data
1260          END WHILE
1270       NEXT I
1280 ! 
1290 ! send eof to connected process
1300       CALL Co_send_eof(#W)
1301 ! 
1302 ! wait for eof condition
1310       DISP "Waiting for EOF"
1320       WHILE FNCo_read(#R,A$)
1330          GOSUB Data
1340       END WHILE
1350       DISP (CLOCK-C)/1000;"Seconds"
1360 ! 
1370 Eof:! 
1380       CALL Co_delete(Fifo$,#1,#2)
1390       END
1391 ! 
1392 Data:! 
1393 LDISP ">";A$
1394 RETURN 
1400 ! 
1410 ! ------------------------------------------------------------------------
1420 ! SUB ROUTINES
1430 ! ------------------------------------------------------------------------
1431 ! 
1432 ! ** create co-process and connect to fifos
1440       SUB Co_create(Fifo$,Cmd$,#1,#2)
1450          DIM Fifo_r$[80],Fifo_w$[80]
1460          CALL Fifo_name(Fifo$,Fifo_w$,Fifo_r$)
1470          COMMAND "!mkfifo "&MAPFNAME$(Fifo_w$)&".DATA "&MAPFNAME$(Fifo_r$)&".DATA"&"; exit 0"
1480          ASSIGN #1 TO Fifo_w$
1490          ASSIGN #2 TO Fifo_r$
1500          COMMAND "!"&Cmd$&" <"&MAPFNAME$(Fifo_w$)&".DATA >"&MAPFNAME$(Fifo_r$)&".DATA 2>&1 &"
1510          ASSIGN #2 TO Fifo_r$;READONLY
1520       SUBEND
1530 ! 
1540 ! ** close and remove fifo files
1550       SUB Co_delete(Fifo$,#1,#2)
1560          DIM Fifo_r$[80],Fifo_w$[80]
1570          CALL Fifo_name(Fifo$,Fifo_w$,Fifo_r$)
1580          COMMAND "!rm -f "&MAPFNAME$(Fifo_w$)&".DATA "&MAPFNAME$(Fifo_r$)&".DATA"
1590          ASSIGN * TO #1
1600          ASSIGN * TO #2
1610       SUBEND
1620 ! 
1630 ! ** Build r/w fifo filename
1640       SUB Fifo_name(Fifo$,W$,R$)
1650          P=POS(Fifo$,":")
1660          IF NOT P THEN P=POS(Fifo$,",")
1670          IF NOT P THEN P=LEN(Fifo$)+1
1680          R$=Fifo$[1,P-1]&"R"&Fifo$[P]
1690          W$=Fifo$[1,P-1]&"W"&Fifo$[P]
1700       SUBEND
1710 ! 
1720 ! ** Write data to co-process (into buffer)
1730       SUB Co_send(#1,A$)
1740          PRINT #1;A$
1750       SUBEND
1760 ! 
1770 ! ** Flush buffers
1780       SUB Co_flush(#1)
1790          PRINT #1;END
1800       SUBEND
1810 ! 
1820 ! ** Send eof to co-process
1830       SUB Co_send_eof(#1)
1840          ASSIGN * TO #1
1850       SUBEND
1860 ! 
1870 ! ** Read line from co-process, returns 0 on eof
1880       DEF FNCo_read(#2,A$)
1890          ON END #2 GOTO Eof
1900          READ #2;A$
1910          RETURN 1
1920 Eof:! 
1930          RETURN 0
1940       FNEND

Another using Bi-directional pipes

This example program, will pass some data to the HP-UX sort command and read the output again.

1000 ! RE-STORE "FIFO3,TEST"
1010       DIM A$[256]
1020       Fifo$="FIFO,TEST"
1030       R=1
1040       W=2
1050 ! 
1060       LOAD SUB "COUTIL,TEST"
1070       LDISP "Creating co process ..."
1080       C=CLOCK
1090       CALL Co_create(Fifo$,"sort",#W,#R)
1100       DISP (CLOCK-C)/1000;"Seconds"
1110 ! 
1120       LDISP "Sending data ..."
1130       ASSIGN #3 TO "TACPR,FILES"
1140       ON END #3 GOTO Eof_3
1150       C=CLOCK
1160       Cnt=0
1170       LOOP
1180          READ #3;A$
1190          CALL Co_send(#W,A$)
1200          Cnt=Cnt+1
1210       END LOOP
1220 Eof_3:ASSIGN * TO #3
1230       CALL Co_send_eof(#W)
1240       DISP (CLOCK-C)/1000;"Seconds"
1250       DISP "# lines =";Cnt
1260 ! 
1270       LDISP "Receiving results ..."
1280       C=CLOCK
1290       Cnt=0
1300       WHILE FNCo_read(#R,A$)
1310 !            LDISP A$
1320          Cnt=Cnt+1
1330       END WHILE
1340       DISP (CLOCK-C)/1000;"Seconds"
1350       DISP "# lines =";Cnt
1360       CALL Co_delete(Fifo$,#1,#2)
1370       END
1380 !

 
 
.
 
 
  Privacy | Webmaster | Terms of use | Impressum Revision:  1999-06-29  
  Copyright © 1995-2002 Marxmeier Software AG