95 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| fhandler tutorial
 | |
| 
 | |
| This document will show how to add a new "fhandler" to cygwin, by
 | |
| showing an example of /dev/zero.
 | |
| 
 | |
| Files to note:
 | |
| 
 | |
| fhandler.h - must define a new derived class here and FH_*
 | |
| devices.in - to notice "/dev/zero" and mark it
 | |
| fhandler_zero.cc - new
 | |
| dtable.cc - to create the fhandler instance
 | |
| 
 | |
| OK, first we have to define what this new fhandler will do.  In our
 | |
| example case, we're going to implement the unix "/dev/zero" device,
 | |
| which has the following characteristics:
 | |
| 
 | |
| * writes to /dev/zero are silently discarded
 | |
| * reads from /dev/zero return all zero bytes
 | |
| * mmap()ing /dev/zero maps a chunk of zero'd out memory.
 | |
| 
 | |
| Since windows doesn't have a device that acts like this, we'll be
 | |
| simulating everything.  Thus:
 | |
| 
 | |
| * writes simply return a success status
 | |
| * reads memset() the buffer and return success
 | |
| * we take advantage of the fact that CreateFileMapping can take a
 | |
|   handle of -1, which (1) maps swap memory, and (2) zeros it out for
 | |
|   us (at least, on NT).
 | |
| 
 | |
| OK, let's start with devices.h.
 | |
| 
 | |
| We have to create a new entry in the enum fh_devices.  The new
 | |
| devices must get a major and a minor ID.  As a rule of thumb, just
 | |
| copy the ones that are used on a linux system.
 | |
| 
 | |
| Now, let's continue with fhandler.h.
 | |
| 
 | |
| First, update the fhandler_union near the end of the file with a
 | |
| line for the new device.  Use existing members, in this case __dev_null
 | |
| as a template.  This union is sorted alphabetically.
 | |
| 
 | |
| Earlier in that file, we'll copy fhandler_dev_null and edit it to be
 | |
| fhandler_dev_zero.  I chose that one because it's small, but we'll add
 | |
| more members as we go (since we're simulating the whole thing).  In
 | |
| fact, let's copy the I/O methods from fhandler_windows since we'll
 | |
| need all those anyway, even though we'll go through the full list
 | |
| later.
 | |
| 
 | |
| OK, next we need to edit devices.in.  There is a section where each device
 | |
| is listed with its cygwin path, its structure and its windows path.
 | |
| "/dev/zero", FH_ZERO, "\\dev\\zero"
 | |
| This is needed to recognize when the user is trying to open "/dev/zero".
 | |
| You have to build devices.cc from devices.in now.
 | |
| There is a script 'gendevices' in the winsup/cygwin directory which may
 | |
| be called at some time in the future if you use 'make' to build the DLL.
 | |
| This should rebuild the devices.cc file.  You have to have shilka
 | |
| available to do that; this is part of the cygwin cocom package.
 | |
| 
 | |
| To go along with that change, we'll need to change dtable.cc.  Look for
 | |
| FH_NULL and add a case for FH_ZERO as well.
 | |
| 
 | |
| Now we get to fhandler_zero.cc itself.  Create the empty file and copy
 | |
| the "usual" header/copyright/includes from some other fhandler_*.cc
 | |
| source file.  Also, edit Makefile.in to build this new file.  Add one
 | |
| new entry to DLL_OFILES, and a new line for the winsup.h dependencies.
 | |
| 
 | |
| Since we changed fhandler.h, when you type "make" it will rebuild
 | |
| everything.  Go ahead and do that when you get a chance to let it run,
 | |
| since we're not changing the headers any more.  Note that you won't be
 | |
| able to link the new dll, as we haven't added all the methods for the
 | |
| new fhandler class yet, but at least you'll get a lot of compilation
 | |
| out of the way.
 | |
| 
 | |
| Next we start adding in the fhandler methods themselves.
 | |
| 
 | |
| Constructor: This takes a name, and all we do is pass that name back
 | |
| to the base class, along with the FH_ZERO value.  We call set_cb
 | |
| because all fhandlers call this (it's for exec to copy the fd).
 | |
| 
 | |
| open: we override the one that takes a name because there are no real
 | |
| windows devices like /dev/zero, but we ignore the name.  We call
 | |
| set_flags to save the flags.
 | |
| 
 | |
| write: writes are discarded; we return success.
 | |
| 
 | |
| read: reads read NUL bytes, so fill the buffer with NULs and return
 | |
| success.
 | |
| 
 | |
| lseek/close: just return success.
 | |
| 
 | |
| dump: this is just for debugging, so we just print something.
 | |
| 
 | |
| select_*: we don't support this yet, see the myriad examples in
 | |
| select.cc for examples.  The base fhandler's methods will do for now.
 |