👤
Home Man
Search
Today's Posts
Register

Linux & Unix Commands - Search Man Pages
Man Page or Keyword Search:
Select Section of Man Page:
Select Man Page Repository:

Linux 2.6 - man page for driver_entry (linux section 3erl)

driver_entry(3erl)		       C Library Functions		       driver_entry(3erl)

NAME
       driver_entry - The driver-entry structure used by erlang drivers.

DESCRIPTION
       As  of  erts  version 5.5.3 the driver interface has been extended (see extended marker ).
       The extended interface introduces version management , the possibility to pass  capability
       flags  (see  driver  flags  ) to the runtime system at driver initialization, and some new
       driver API functions.

   Note:
       Old drivers (compiled with an erl_driver.h from an earlier erts version than  5.5.3)  have
       to be recompiled (but do not have to use the extended interface).

       The driver_entry structure is a C struct that all erlang drivers define. It contains entry
       points for the erlang driver that are called by	the  erlang  emulator  when  erlang  code
       accesses the driver.

       The erl_driver driver API functions need a port handle that identifies the driver instance
       (and the port in the emulator). This is only passed to the start function, but not to  the
       other  functions. The start function returns a driver-defined handle that is passed to the
       other functions. A common practice is to have the start function  allocate  some  applica-
       tion-defined  structure	and  stash the port handle in it, to use it later with the driver
       API functions.

       The driver call-back functions are called synchronously from the erlang emulator. If  they
       take too long before completing, they can cause timeouts in the emulator. Use the queue or
       asynchronous calls if necessary, since the emulator must be responsive.

       The driver structure contains the name of the driver and some 15 function pointers.  These
       pointers are called at different times by the emulator.

       The  only  exported  function  from  the driver is driver_init . This function returns the
       driver_entry structure that points to the other functions in the driver.  The  driver_init
       function  is  declared  with  a macro DRIVER_INIT(drivername) . (This is because different
       OS's have different names for it.)

       When writing a driver in C++, the driver entry should be of "C" linkage.  One  way  to  do
       this is to put this line somewhere before the driver entry: extern "C" DRIVER_INIT(driver-
       name); .

       When the driver has passed the driver_entry over  to  the  emulator,  the  driver  is  not
       allowed to modify the driver_entry .

   Note:
       Do not declare the driver_entry const . This since the emulator needs to modify the handle
       , and the handle2 fields. A statically allocated, and const declared driver_entry  may  be
       located in read only memory which will cause the emulator to crash.

DATA TYPES
	 ErlDrvEntry  :

	 typedef struct erl_drv_entry {
	     int (*init)(void); 	 /* called at system start up for statically
					    linked drivers, and after loading for
					    dynamically loaded drivers */

	 #ifndef ERL_SYS_DRV
	     ErlDrvData (*start)(ErlDrvPort port, char *command);
					 /* called when open_port/2 is invoked.
					    return value -1 means failure. */
	 #else
	     ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts);
					 /* special options, only for system driver */
	 #endif
	     void (*stop)(ErlDrvData drv_data);
					 /* called when port is closed, and when the
					    emulator is halted. */
	     void (*output)(ErlDrvData drv_data, char *buf, int len);
					 /* called when we have output from erlang to
					    the port */
	     void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
					 /* called when we have input from one of
					    the driver's handles) */
	     void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event);
					 /* called when output is possible to one of
					    the driver's handles */
	     char *driver_name; 	 /* name supplied as command
					    in open_port XXX ? */
	     void (*finish)(void);	 /* called before unloading the driver -
					    DYNAMIC DRIVERS ONLY */
	     void *handle;		 /* Reserved -- Used by emulator internally */
	     int (*control)(ErlDrvData drv_data, unsigned int command, char *buf,
			    int len, char **rbuf, int rlen);
					 /* "ioctl" for drivers - invoked by
					    port_control/3) */
	     void (*timeout)(ErlDrvData drv_data);	  /* Handling of timeout in driver */
	     void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev);
					 /* called when we have output from erlang
					    to the port */
	     void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data);
	     void (*flush)(ErlDrvData drv_data);
					 /* called when the port is about to be
					    closed, and there is data in the
					    driver queue that needs to be flushed
					    before 'stop' can be called */
	     int (*call)(ErlDrvData drv_data, unsigned int command, char *buf,
			    int len, char **rbuf, int rlen, unsigned int *flags);
					 /* Works mostly like 'control', a syncronous
					    call into the driver. */
	     void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
			   ErlDrvEventData event_data);
					 /* Called when an event selected by
					    driver_event() has occurred */
	     int extended_marker;	 /* ERL_DRV_EXTENDED_MARKER */
	     int major_version; 	 /* ERL_DRV_EXTENDED_MAJOR_VERSION */
	     int minor_version; 	 /* ERL_DRV_EXTENDED_MINOR_VERSION */
	     int driver_flags;		 /* ERL_DRV_FLAGs */
	     void *handle2;		 /* Reserved -- Used by emulator internally */
	     void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor);
					 /* Called when a process monitor fires */
	     void (*stop_select)(ErlDrvEvent event, void* reserved);
					 /* Called to close an event object */
	  } ErlDrvEntry;

	   int (*init)(void) :
	     This is called directly after the driver has been loaded by erl_ddll:load_driver/2 .
	     (Actually when the driver is added to the driver list.) The driver should return  0,
	     or if the driver can't initialize, -1.

	   ErlDrvData (*start)(ErlDrvPort port, char* command) :
	     This  is  called  when  the  driver is instantiated, when open_port/2 is called. The
	     driver should return a number >= 0 or a pointer, or if the driver can't be  started,
	     one of three error codes should be returned:

	     ERL_DRV_ERROR_GENERAL - general error, no error code

	     ERL_DRV_ERROR_ERRNO - error with error code in erl_errno

	     ERL_DRV_ERROR_BADARG - error, badarg

	     If an error code is returned, the port isn't started.

	   void (*stop)(ErlDrvData drv_data) :
	     This  is called when the port is closed, with port_close/1 or Port ! {self(), close}
	     . Note that terminating the port owner process also closes the port. If drv_data  is
	     a	pointer  to memory allocated in start , then stop is the place to deallocate that
	     memory.

	   void (*output)(ErlDrvData drv_data, char *buf, int len) :
	     This is called when an erlang process has sent data to the port. The data is pointed
	     to  by  buf  , and is len bytes. Data is sent to the port with Port ! {self(), {com-
	     mand, Data}} , or with port_command/2 . Depending on how the  port  was  opened,  it
	     should  be  either  a  list  of  integers	0...255  or a binary. See open_port/3 and
	     port_command/2 .

	   void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event) :

	   void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event) :
	     This is called when a driver event (given in the event parameter) is signaled.  This
	     is used to help asynchronous drivers "wake up" when something happens.

	     On  unix  the  event is a pipe or socket handle (or something that the select system
	     call understands).

	     On Windows the event is an Event or Semaphore (or something that  the  WaitForMulti-
	     pleObjects  API  function	understands).  (Some trickery in the emulator allows more
	     than the built-in limit of 64 Events to be used.)

	     To use this with threads and asynchronous routines, create a pipe	on  unix  and  an
	     Event  on	Windows.  When	the routine completes, write to the pipe (use SetEvent on
	     Windows), this will make the emulator call ready_input or ready_output .

	     Spurious events may happen. That is,  calls  to  ready_input  or  ready_output  even
	     though no real events are signaled. In reality it should be rare (and OS dependant),
	     but a robust driver must nevertheless be able to handle such cases.

	   char *driver_name :
	     This is the name of the driver, it must correspond to the atom used in  open_port	,
	     and the name of the driver library file (without the extension).

	   void (*finish)(void) :
	     This  function  is called by the erl_ddll driver when the driver is unloaded. (It is
	     only called in dynamic drivers.)

	     The driver is only unloaded as a result of calling unload_driver/1  ,  or	when  the
	     emulator halts.

	   void *handle :
	     This  field  is  reserved	for the emulator's internal use. The emulator will modify
	     this field; therefore, it is important that the driver_entry isn't declared const .

	   int (*control)(ErlDrvData drv_data, unsigned int command, char  *buf,  int  len,  char
	   **rbuf, int rlen) :
	     This is a special routine invoked with the erlang function port_control/3 . It works
	     a little like an "ioctl" for  erlang  drivers.  The  data	given  to  port_control/3
	     arrives in buf and len . The driver may send data back, using *rbuf and rlen .

	     This  is  the  fastest way of calling a driver and get a response. It won't make any
	     context switch in the erlang emulator, and requires no message passing. It is  suit-
	     able for calling C function to get faster execution, when erlang is too slow.

	     If  the  driver  wants to return data, it should return it in rbuf . When control is
	     called, *rbuf points to a default buffer of rlen bytes, which can be used to  return
	     data. Data is returned different depending on the port control flags (those that are
	     set with set_port_control_flags ).

	     If the flag is set to PORT_CONTROL_FLAG_BINARY , a binary will  be  returned.  Small
	     binaries  can  be returned by writing the raw data into the default buffer. A binary
	     can also be  returned  by	setting  *rbuf	to  point  to  a  binary  allocated  with
	     driver_alloc_binary  .  This  binary  will  be freed automatically after control has
	     returned.	The  driver  can  retain  the  binary	for   read   only   access   with
	     driver_binary_inc_refc  to  be  freed  later  with  driver_free_binary . It is never
	     allowed to alter the binary after control has returned. If *rbuf is set to NULL,  an
	     empty list will be returned.

	     If  the  flag  is	set to 0 , data is returned as a list of integers. Either use the
	     default buffer or set *rbuf to point to a larger buffer allocated with  driver_alloc
	     . The buffer will be freed automatically after control has returned.

	     Using binaries is faster if more than a few bytes are returned.

	     The return value is the number of bytes returned in *rbuf .

	   void (*timeout)(ErlDrvData drv_data) :
	     This  function  is  called any time after the driver's timer reaches 0. The timer is
	     activated with driver_set_timer . There are no priorities or ordering among drivers,
	     so if several drivers time out at the same time, any one of them is called first.

	   void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev) :
	     This  function is called whenever the port is written to. If it is NULL , the output
	     function is called instead. This function is faster than output , because	it  takes
	     an  ErlIOVec  directly, which requires no copying of the data. The port should be in
	     binary mode, see open_port/2 .

	     The ErlIOVec contains both a SysIOVec , suitable for writev , and one or more  bina-
	     ries.  If	these binaries should be retained, when the driver returns from outputv ,
	     they can be queued (using driver_enq_bin for instance), or if they  are  kept  in	a
	     static or global variable, the reference counter can be incremented.

	   void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data) :
	     This  function  is called after an asynchronous call has completed. The asynchronous
	     call is started with driver_async . This function is called from the erlang emulator
	     thread,  as opposed to the asynchronous function, which is called in some thread (if
	     multithreading is enabled).

	   int (*call)(ErlDrvData drv_data, unsigned  int  command,  char  *buf,  int  len,  char
	   **rbuf, int rlen, unsigned int *flags) :
	     This  function  is  called from erlang:port_call/3 . It works a lot like the control
	     call-back, but uses the external term format for input and output.

	     command is an integer, obtained from the call from erlang (the  second  argument  to
	     erlang:port_call/3 ).

	     buf   and	 len   provide	 the  arguments  to  the  call	(the  third  argument  to
	     erlang:port_call/3 ). They can be decoded using ei functions.

	     rbuf points to a return buffer, rlen bytes long. The return data should be  a  valid
	     erlang term in the external (binary) format. This is converted to an erlang term and
	     returned by erlang:port_call/3 to the caller. If  more  space  than  rlen	bytes  is
	     needed to return data, *rbuf can be set to memory allocated with driver_alloc . This
	     memory will be freed automatically after call has returned.

	     The return value is the number of bytes returned in *rbuf . If ERL_DRV_ERROR_GENERAL
	     is returned (or in fact, anything < 0), erlang:port_call/3 will throw a BAD_ARG .

	   void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data) :
	     Intentionally left undocumented.

	   int extended_marker :
	     This  field  should  either be equal to ERL_DRV_EXTENDED_MARKER or 0 . An old driver
	     (not aware of the extended driver interface) should set this field to 0  .  If  this
	     field  is	equal  to  0 , all the fields following this field also have to be 0 , or
	     NULL in case it is a pointer field.

	   int major_version :
	     This field should equal ERL_DRV_EXTENDED_MAJOR_VERSION if the extended_marker  field
	     equals ERL_DRV_EXTENDED_MARKER .

	   int minor_version :
	     This  field should equal ERL_DRV_EXTENDED_MINOR_VERSION if the extended_marker field
	     equals ERL_DRV_EXTENDED_MARKER .

	   int driver_flags :
	     This field is used to pass driver capability information to the runtime  system.  If
	     the  extended_marker  field  equals ERL_DRV_EXTENDED_MARKER , it should contain 0 or
	     driver flags ( ERL_DRV_FLAG_* ) ored bitwise. Currently the following  driver  flags
	     exist:

	     ERL_DRV_FLAG_USE_PORT_LOCKING :
	       The  runtime system will use port level locking on all ports executing this driver
	       instead of driver level locking when the driver is run in a  runtime  system  with
	       SMP support. For more information see the erl_driver documentation.

	     ERL_DRV_FLAG_SOFT_BUSY :
	       Marks  that  driver instances can handle being called in the output and/or outputv
	       callbacks  even	though	a  driver  instance  has  marked  itself  as  busy   (see
	       set_busy_port() ). Since erts version 5.7.4 this flag is required for drivers used
	       by the Erlang distribution (the behaviour has always been required by drivers used
	       by the distribution).

	   void *handle2 :
	     This  field  is  reserved	for the emulator's internal use. The emulator will modify
	     this field; therefore, it is important that the driver_entry isn't declared const .

	   void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor) :
	     This callback is called when a monitored process exits. The  drv_data  is	the  data
	     associated  with  the  port  for  which the process is monitored (using driver_moni-
	     tor_process ) and the monitor corresponds to the ErlDrvMonitor structure  filled  in
	     when   creating   the   monitor.  The  driver  interface  function  driver_get_moni-
	     tored_process can be used to retrieve the process id of the exiting  process  as  an
	     ErlDrvTermData .

	   void (*stop_select)(ErlDrvEvent event, void* reserved) :
	     This function is called on behalf of driver_select when it is safe to close an event
	     object.

	     A typical implementation on Unix is to do close((int)event) .

	     Argument reserved is intended for future use and should be ignored.

	     In contrast to most of the other call-back functions, stop_select is called indepen-
	     dent  of  any port. No ErlDrvData argument is passed to the function. No driver lock
	     or port lock is guaranteed to be held. The port that called driver_select might even
	     be  closed  at  the  time	stop_select is called. But it could also be the case that
	     stop_select is called directly by driver_select .

	     It is not allowed to call any functions in the driver API from  stop_select  .  This
	     strict limitation is due to the volatile context that stop_select may be called.

SEE ALSO
       erl_driver(3erl) , erl_ddll(3erl) , erlang(3erl) , kernel(3erl)

Ericsson AB				    erts 5.8.3			       driver_entry(3erl)


All times are GMT -4. The time now is 07:46 AM.

Unix & Linux Forums Content Copyrightę1993-2018. All Rights Reserved.
×
UNIX.COM Login
Username:
Password:  
Show Password