well this is the code with a extended mount structure
//Resource Manager
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
/*
- define THREAD_POOL_PARAM_T such that we can avoid a compiler
- warning when we use the dispatch_*() functions below
*/
#define THREAD_POOL_PARAM_T dispatch_context_t
/* Define our overrides before including <sys/iofunc.h> */
struct device;
#define IOFUNC_ATTR_T struct device
struct ocb;
#define IOFUNC_OCB_T struct ocb
struct ex_mount;
#define IOFUNC_MOUNT_T struct ex_mount
#include <sys/iofunc.h>
#include <sys/dispatch.h>
struct ocb {
iofunc_ocb_t hdr;
struct ocb *next;
struct ocb **prev;
};
struct device {
iofunc_attr_t attr;
struct ocb *list;
};
struct ex_mount {
iofunc_mount_t dev_mount;
char dev_name[256];
};
struct ocb *ocb_calloc (resmgr_context_t *ctp, struct device *device);
void ocb_free (struct ocb *ocb);
iofunc_funcs_t ocb_funcs = { /* our ocb allocating & freeing functions */
_IOFUNC_NFUNCS,
ocb_calloc,
ocb_free
};
/* The mount structures.*/
iofunc_mount_t mountpoint1 = { 0, 0, 0, 0, &ocb_funcs };
iofunc_mount_t mountpoint2 = { 0, 0, 0, 20,&ocb_funcs};
/* Two structures device per attached name */
struct device deviceattr1, deviceattr2 ;
struct ex_mount mount1, mount2 ;
int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
int io_write (resmgr_context_t *ctp, io_write_t *msg,RESMGR_OCB_T *ocb);
static resmgr_connect_funcs_t connect_funcs;
static resmgr_io_funcs_t io_funcs;
int main(int argc, char *argv)
{
/ declare variables we’ll be using */
thread_pool_attr_t pool_attr;
resmgr_attr_t resmgr_attr;
dispatch_t *dpp;
thread_pool_t *tpp;
dispatch_context_t *ctp;
int id;
/* initialize dispatch interface */
if((dpp = dispatch_create()) == NULL) {
fprintf(stderr, "%s: Unable to allocate dispatch handle.\n",
argv[0]);
return EXIT_FAILURE;
}
/* initialize resource manager attributes */
memset(&resmgr_attr, 0, sizeof resmgr_attr);
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
/* initialize functions for handling messages */
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
io_funcs.read = io_read;
io_funcs.write = io_write;
/* initialize attribute structure used by the device */
iofunc_attr_init(&deviceattr1.attr, S_IFNAM | 0666, 0, 0);
iofunc_attr_init(&deviceattr2.attr, S_IFNAM | 0666, 0, 0);
deviceattr1.attr.mount = &mountpoint1;
deviceattr2.attr.mount = &mountpoint2;
/*Set structures*/
mount1.dev_mount = mountpoint1;
mount2.dev_mount = mountpoint2;
/*Here the extra data is set*/
sprintf(mount1.dev_name,"%s","/dev/plc1");
sprintf(mount2.dev_name,"%s","/dev/plc2");
printf("%s y %s Registered \n",mount1.dev_name, mount2.dev_name);
/* attach our device name */
id = resmgr_attach(dpp, /* dispatch handle */
&resmgr_attr, /* resource manager attrs */
mount1.dev_name, /* device name */
_FTYPE_ANY, /* open type */
0, /* flags */
&connect_funcs, /* connect routines */
&io_funcs, /* I/O routines */
&deviceattr1); /* handle */
resmgr_attach(dpp, /* dispatch handle */
&resmgr_attr, /* resource manager attrs */
mount2.dev_name, /* device name */
_FTYPE_ANY, /* open type */
0, /* flags */
&connect_funcs, /* connect routines */
&io_funcs, /* I/O routines */
&deviceattr2); /* handle */
if(id == -1) {
fprintf(stderr, "%s: Unable to attach name.\n", argv[0]);
return EXIT_FAILURE;
}
/* initialize thread pool attributes */
memset(&pool_attr, 0, sizeof pool_attr);
pool_attr.handle = dpp;
pool_attr.context_alloc = dispatch_context_alloc;
pool_attr.block_func = dispatch_block;
pool_attr.unblock_func = dispatch_unblock;
pool_attr.handler_func = dispatch_handler;
pool_attr.context_free = dispatch_context_free;
pool_attr.lo_water = 2;
pool_attr.hi_water = 4;
pool_attr.increment = 1;
pool_attr.maximum = 50;
/* allocate a thread pool handle */
if((tpp = thread_pool_create(&pool_attr,
POOL_FLAG_EXIT_SELF)) == NULL) {
fprintf(stderr, "%s: Unable to initialize thread pool.\n",
argv[0]);
return EXIT_FAILURE;
}
/* start the threads, will not return */
thread_pool_start(tpp);
}
int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
{
printf(“READ -------------- \n”);
printf (“Received %d bytes, Blocksize is %d in %s Device\n”, msg → i.nbytes, ocb->hdr.attr->attr.mount->dev_mount.blocksize, ocb->hdr.attr->attr.mount->dev_name);
/Driver Function, this function go to the interface “abslc.h” who call libabslc.so.1 (driver)/
//ReadPLC(&buffer, &address);
return (_RESMGR_NPARTS (1));
}
int io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
{
int status;
char *buf;
if ((status = iofunc_write_verify(ctp, msg, ocb, NULL)) != EOK)
return (status);
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
return(ENOSYS);
/* set up the number of bytes (returned by client's write()) */
_IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
buf = (char *) malloc(msg->i.nbytes + 1);
if (buf == NULL)
return(ENOMEM);
/* Reread the data from the sender's message buffer. */
resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
buf [msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
printf ("Received %d bytes = %s, Blocksize is %d in %s Device\n", msg -> i.nbytes, buf, ocb->hdr.attr->attr.mount->dev_mount.blocksize, ocb->hdr.attr->attr.mount->dev_name);
/*Driver Function, this function go to the interface "abslc.h" who call libabslc.so.1 (driver)*/
//WritePLC(&buffer, &address);
free(buf);
if (msg->i.nbytes > 0)
ocb->hdr.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
printf("WRITE -------------- \n");
return (_RESMGR_NPARTS (0));
}
/*
-
ocb_calloc
-
-
The purpose of this is to give us a place to allocate our own OCB.
-
It is called as a result of the open being done
-
(e.g. iofunc_open_default causes it to be called). We
-
registered it through the mount structure.
*/
struct ocb * ocb_calloc (resmgr_context_t *ctp, IOFUNC_ATTR_T *device)
{
struct ocb *ocb;
if (!(ocb = calloc (1, sizeof (*ocb)))) {
return 0;
}
/* see note 3 */
ocb → prev = &device → list;
if (ocb → next = device → list) {
device → list → prev = &ocb → next;
}
device → list = ocb;
return (ocb);
}
/*
- ocb_free
-
- The purpose of this is to give us a place to free our OCB.
- It is called as a result of the close being done
- (e.g. iofunc_close_ocb_default causes it to be called). We
- registered it through the mount structure.
*/
void ocb_free (IOFUNC_OCB_T ocb)
{
/ see note 3 */
if (*ocb → prev = ocb → next) {
ocb → next → prev = ocb → prev;
}
free (ocb);
}
with OCB extended is the same but the diference that i don[t know where data is set.