Feedback Search Top Backward Forward
EDM/2

IPC Between DOS Processes

Written by Leif Eriksen

 

Introduction

Pipes is one of three forms of interprocess communication (IPC) supported by OS/2, and the only one that can be used in connection with DOS processes. A pipe is a named or unnamed memory buffer used to pass data between processes.

An unnamed pipe require that there is a parent-child relationship between the two processes using it. DOS processes are in their nature unrelated and they can only work with named pipes.

With pipes, processes can communicate with each other, as if they were reading from and writing to a file. Named pipes takes it even further, in that they support this feature - not just within one station - but even between different stations across a network. This makes it a simple alternative to a NetBIOS protocol, for example, when you have to establish communication between DOS and/or OS/2 programs.

The pipe is set-up in a server-client model. Communication can only be between a server and its client(s). When the server has created and connected to the pipe, this is available to the client just as any other file. A named pipe will be created by the server with a name, e.g. "\\PIPE\\MyPipe". The client connects to it by opening a file with the name "\\PIPE\\MyPipe".

When a client has closed its connection to the pipe or it simply terminates without doing a DosClose(), the pipe will not be available to other clients before the server has disconnected and reconnected again using the DosDisConnectNPipe() and DosConnectNPipe() functions. Unfortunately, the OS/2 program will not be able to see that the pipe has been broken when reading from it. Only when performing a DosWrite() will it get a return code ERROR_BROKEN_PIPE, which tells it that it will have reconnect the pipe before it can be used again.

If you want to be able to reuse broken pipes, the server must supervise the status of these. To be able to do this, the server will have to perform a DosWrite() on each one. Even though you may only want to read from it, you will still have to create some additional logic (read/write operations) in both server and client to deal with the supervision of the pipe-status.

When working with DOS processes

DOS processes will only be able to connect to a pipe as client, and will as such not be able to create it. This means that DOS processes requires a least one OS/2 program to establish IPC. Communication is only between server and client, there can be no direct client-to-client communication.

DOS & OS/2 source code.

The following program examples shows how it can be programmed within both DOS and OS/2. To keep it simple (and stupid), the example only deals with one-way communication, and it does not deal the problem of detecting - and responding to - a broken pipe. Data is flowing from one DOS process (ProcOne) to the OS/2 program, which receives it and retransmit it to the second DOS process (ProcTwo). The concept can easily be extended to full duplex communication.

The following bits of code is a part of the DOS program that writes data to the pipe:


void main(void)
{
  :
  rc = _dos_open("\\PIPE\\ProcOne",O_WRONLY, &hF );
                                            // Open pipe for writing
  :
  rc = _dos_write( hF,&ch,1024,&Count);     // Write to pipe
  :
  _dos_close( hF );                         // Close (disconnect) pipe
  :
}
The following bits of code is a part of the DOS program that reads data from the pipe:

void main(void)
{
  :
  rc = _dos_open( "\\PIPE\\ProcTwo", O_RDONLY, &hF );
                                             // Open pipe for reading
  :
  rc = _dos_read( hF, ch, 1024, &Count );    // Read from pipe
  :
  _dos_close( hF );                          // Close (disconnect) pipe
  :
}
The following bits of code is a part of the OS/2 program that establish the interprocess communication between the DOS processes. All data that it reads from the input pipe is just echoed to the output pipe.

#define  BuffSize  2048               /* Size of input and output buffers */

void main ( void )
{
  UCHAR PipeOne[] = "\\PIPE\\ProcOne";
  UCHAR	PipeTwo[] = "\\PIPE\\ProcTwo";
  ULONG	BytesRead, BytesWritten, InputBufSize, OutputBufSize;
  UCHAR	*Buffer;
  HPIPE	hDosProcOne, hDosProcTwo;     /* Pipe handle (returned) */
  ULONG	PipeMode;                     /* Pipe-mode parameters */
  ULONG	TimeOut;                      /* Default value for DosWaitNPipe
                                         time-out parameter  */
  :
  Buffer = (UCHAR *)malloc( BuffSize );

/****************************************************************************
******                           Create pipes                          ******
****************************************************************************/
  /*
  NP_WAIT           : wait for data
  NP_TYPE_BYTE      : type of pipe
  NP_READMODE_BYTE  : pipe is transferring bytes
  0x01              : allow only one instance of pipe
  */
  PipeMode = NP_WAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 0x01;

  OutputBufSize = BuffSize;
  InputBufSize  = BuffSize;
  TimeOut       = 10000;   /* Time-out (msec.) for DosWaitNPipe to timeout */
  DosCreateNPipe ( PipeOne, &hDosProcOne, NP_ACCESS_INBOUND, PipeMode, 0,
                   InputBufSize, TimeOut );
  DosCreateNPipe ( PipeTwo, &hDosProcTwo, NP_ACCESS_OUTBOUND, PipeMode,
                   OutputBufSize, 0, TimeOut );

/****************************************************************************
******                         Connect to pipes                        ******
****************************************************************************/
  DosConnectNPipe ( hDosProcOne );
  DosConnectNPipe ( hDosProcTwo );

/****************************************************************************
******                       Read / Write forever                      ******
****************************************************************************/
  while ( TRUE ) {

  DosRead ( hDosProcOne, Buffer, BuffSize, &BytesRead );
                                     // Read from "\\PIPE\\ProcOne"
  DosWrite ( hDosProcTwo, Buffer, BytesRead, &BytesWritten );
                                     // Write to "\\PIPE\\ProcTwo"
  }
  :
}