Pointers
NmpRmpHand locates the RMP handle that contains the selector for the NPN RMP segment.
NPN field npn_link points to the double linked list of NP structures that are instances of the named pipe.
Instances of named pipes are double-lined by np_flink and np_blink.
NP fields np_selector1 and np_selector2 point to associated NPB structures.
The NP is allocated from the system arena.
The NPB is allocated from the kernel resident heap.
NPN owner id is npipenpn (0xff30).
NPB owner id is npipenbuf (0xff9f).
There are four important data structures associated with named pipes: the SFT corresponding to an open named pipe, a pair of kernel internal data structures describing the pipe and one or two allocated memory segments which contain the data buffers for the pipe.
The parts of the SFT specific to named pipes are:
sf_flags SF_NMPIPE and SF_PIPE set sf_np pointer to pipe info. sf_pipmod mode of pipe, per-sft internal state bits Where: sf_np is defined to be sf_fsd+0, the pointer to np structure sf_pipmod is defined to be sf_fsd+4, the mode of pipe, plus internal state
NP Named Pipe data structure
The internal data structure for an instance of a pipe. One of these structures is allocated for each open instance of a particular named pipe.
Allocated NP structures are placed on two lists. The first is headed by ActiveNPList, with list pointer np_next linking together all currently active NP structures.
The second list is headed by the NPN structure defined below and is doubly-linked by the np_flink and np_blink pointers. This list is used to iterate over all instances of a particular pipe name.
┌─────────────────┬──────┬──────┬────┬────────────────────────────────────────┐ │Field Name │Offset│Length│Type│Description │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_state │+0 │1 │B │state of pipe │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_refcnt │+1 │1 │B │SFT reference count for pipe (1 or 2) │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_next │+2 │2 │W │pointer to next in active list │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_flink │+4 │2 │W │pointer to next instance of pipe │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_blink │+6 │2 │W │pointer to previous instance of pipe │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_namkey │+8 │2 │W │RMP key value for npn structure │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_scnt │+a │1 │B │count of servers (max. 1) │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_ccnt │+b │1 │B │count of clients (max. 1) │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_selector1 │+c │2 │W │selector for outgoing data buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_selector2 │+e │2 │W │selector for incoming data buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_pipmod │+10 │2 │W │pipe mode specified at creation time │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_flags │+12 │2 │W │pipe flags │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_ssft │+14 │4 │D │back pointer to server SFT │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_csft │+18 │4 │D │back pointer to client SFT │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_timeo │+1c │4 │D │default timeout for DosWaitNmPipe │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_ssem │+20 │4 │D │server end system semaphore │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_ssemkey │+24 │2 │W │server's semaphore key │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_csem │+26 │4 │D │client end system semaphore │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │np_csemkey │+2a │2 │W │client's semaphore key │ └─────────────────┴──────┴──────┴────┴────────────────────────────────────────┘
NPN Named Pipe Name data structure
The following structure contains the common name for the multiple instances of a pipe. Its key value is used as the ProcBlock key for waiters on the pipe. The key value is also used as an RMP key to look up the name record from the NP structure.
┌─────────────────┬──────┬──────┬────┬────────────────────────────────────────┐ │Field Name │Offset│Length│Type│Description │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npn_link │+0 │4 │D │pointer to first instance │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npn_key │+4 │2 │W │unique serial number of name │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npn_len │+6 │2 │W │total length of structure │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npn_name │+8 │254 │A │name of pipe, null terminated │ └─────────────────┴──────┴──────┴────┴────────────────────────────────────────┘
NPB Named Pipe Buffer data structure
The following variables are used to control the access to a pipe buffer and are part of the allocated buffer for the pipe. In the case of a duplex pipe, two independent data buffers are allocated. Only one buffer will be allocated for a simplex pipe.
┌─────────────────┬──────┬──────┬────┬────────────────────────────────────────┐ │Field Name │Offset│Length│Type│Description │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_selector │+0 │2 │W │selector of buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_first │+2 │2 │W │base of buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_in │+4 │2 │W │next free byte in buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_out │+6 │2 │W │next byte of data in buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_last │+8 │2 │W │end+1 of buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_rdlck │+a │2 │W │read lock sem. │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_wtlck │+c │2 │W │write lock sem. │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_rdsem │+e │2 │W │read sync sem. │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_wtsem │+10 │2 │W │write sync sem. │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_rdcnt │+12 │1 │B │count of readers of buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_wtcnt │+13 │1 │B │count of writers to buffer │ ├─────────────────┼──────┼──────┼────┼────────────────────────────────────────┤ │npb_data │+14 │2 │W │size of data left in pipe │ └─────────────────┴──────┴──────┴────┴────────────────────────────────────────┘
np_state allowable values for named pipe state
Internally, byte stream mode pipes store just a collection of bytes in the data buffer. Message stream mode pipes have individual messages preceeded by a word which indicates the size of the message.
Named pipes may be in one of several states depending on the actions that have been taken on it by the server end and client end. The following state/action table summarizes the valid state transitions:
Current state Action Next state <none> server MakeNmPipe DISCONNECTED DISCONNECTED server connect LISTENING LISTENING client open CONNECTED CONNECTED server disconn DISCONNECTED CONNECTED client close CLOSING CLOSING server disconn DISCONNECTED CONNECTED server close CLOSING <any other> server close <pipe deallocated>
A special internal state, LISTEN2 is used when a client open is in progress (since some operations may block). This is treated the same as the LISTENING state except that a new open or wait will not recognize it as an available pipe.
If a server disconnects his end of the pipe, the client end will enter a special state in which any future operations (except close) on the file descriptor associated with the pipe will return an error.
┌────────────────────┬────────┬────────────────────────────────────────┐ │Name │Bit Mask│Description │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_DISCONNECTED │1 │after pipe creation or Disconnect │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_LISTENING │2 │after DosNmPipeConnect │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_CONNECTED │3 │after Client open │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_CLOSING │4 │after Client close │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_LISTEN2 │0x12 │internal; client open in progress │ └────────────────────┴────────┴────────────────────────────────────────┘
np_pipmod, sf_pipmod bit mask values:
┌────────────────────┬────────┬────────────────────────────────────────┐ │Name │Bit Mask│Description │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_NBLK │0x8000 │non-blocking read/write │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_NBLKR │0x8000 │non-blocking read │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_NBLKW │0x8000 │non-blocking write │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_SERVER │0x4000 │set if server end │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_WMESG │0x0400 │write messages │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_RMESG │0x0100 │read as messages │ ├────────────────────┼────────┼────────────────────────────────────────┤ │NP_TIMOUT │0x3800 │Timeout np_sem_blk & np_sem_wait │ └────────────────────┴────────┴────────────────────────────────────────┘