qnx之resource manager(三)
作者:互联网
qnx之resource manager(三)
device-specific and per-open data
学习目的
1.举例引入概念
2.代码编写步骤
1.举例引入概念
a time resource manager,如下所示:
该resource manager必须要有以下特性:
1.操作多个设备
•/dev/time/now
•/dev/time/min
•/dev/time/hour
2.在read时,能返回多个数据
•返回一次数据
•在后面的reads中,返回0以表示读到了文件的最后
3.维护open和read之间的上下文
注:要实现以上需求,必须要满足以下要求:a.name和device的数量都知道;b.device的数量不是特别大(少于100)
2.代码编写步骤:
1.注册这3个新name
resmgr_attach (dpp, &rattr, “/dev/time/now”,
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &nowattr);
resmgr_attach (dpp, &rattr, “/dev/time/hour”,
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &hourattr);
resmgr_attach (dpp, &rattr, “/dev/time/min”,
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &minattr);
- 1
- 2
- 3
- 4
- 5
- 6
或者
char *devnames [NumDevices] = { … initializers … };
…
for (i = 0; i < NumDevices; i++) {
resmgr_attach (…, devnames [i], …);
}
- 1
- 2
- 3
- 4
- 5
图解:
2.编写I/O和connect 函数相关
每一个open()都匹配一个ocb,并且指向我们打开的设备的attribute structure。
attribute structure指向更高级别的structure(mount structure),它描述了 普通mountpoint 信息。
重写attr,以包含我们自己的数据:
struct Timeattr_s;
#define IOFUNC_ATTR_T struct Timeattr_s
#include <sys/iofunc.h>
#include <sys/neutrino.h>
typedef struct Timeattr_s {
iofunc_attr_t attr; // encapsulate iofunc layer’s
// attr
char * format; // our data
} Timeattr_
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
导致io_open函数原型变化:
int io_open (..., RESMGR_HANDLE_T *handle, ...)
变为
int io_open (..., Timeattr_t *tattr, ...)
- 1
- 2
- 3
重写ocb,以包含我们自己的数据:
struct Timeocb_s;
#define IOFUNC_OCB_T struct Timeocb_s
#include <sys/iofunc.h>
#include <sys/neutrino.h>
typedef struct Timeocb_s {
iofunc_ocb_t ocb; // encapsulate iofunc layer’s ocb
char *buffer; // for buffer of data we return
int bufsize; // how many bytes are in buffer
} Timeocb_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
使io_read函数原型变化:
int io_read (..., RESMGR_OCB_T *ocb)
变为
int io_read (..., Timeocb_t *tocb)
- 1
- 2
- 3
ocb的动态分配和释放
1:先定义iofunc_funcs_t结构体,
2:然后将该结构体地址放入iofunc_mount_t结构体中,
3:再将iofunc_mount_t结构体地址放入iofunc_attr_t
IOFUNC_OCB_T *time_ocb_calloc (resmgr_context_t *ctp,
IOFUNC_ATTR_T *attr) //由iofunc_open_default()函数调用
void time_ocb_free (IOFUNC_OCB_T *ocb)//由iofunc_close_ocb_default()函数调用
Timeocb_t *
time_ocb_calloc (resmgr_context_t *ctp, Timeattr_t *tattr)
{
Timeocb_t *tocb;
tocb = calloc (1, sizeof (Timeocb_t));
// do anything else to our per ocb data
tocb -> buffer = NULL;
return tocb;
}
void
time_ocb_free (Timeocb_t *tocb)
{
if (tocb -> buffer) {
free (tocb -> buffer);
}
free (tocb);
}
//1
iofunc_funcs_t time_ocb_funcs = {
_IOFUNC_NFUNCS,
time_ocb_calloc,
time_ocb_free
};
//2
iofunc_mount_t time_mount = { 0, 0, 0, 0, &time_ocb_funcs };
//3
for (i = 0; i < NUMDEVICES; i++) {
iofunc_attr_init (&timeattrs [i].attr, ...);
timeattrs [i].attr.mount = &time_mount;
timeattrs [i].format = formats[i];
resmgr_attach (dpp, &rattr, devnames [i], _FTYPE_ANY, 0,
&connect_funcs, &io_funcs,
&timeattrs [i]);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
注:系统中有
typedef struct _iofunc_ocb {
IOFUNC_ATTR_T *attr;
…
} iofunc_ocb_t;
所以iofunc_ocb_t包含了我们重写的IOFUNC_ATTR_T,并且IOFUNC_ATTR_T包含了iofunc_attr_t
以上几个结构体包含关系如图:
总体代码:
/*
* time.c
*
* This module contains the source code for the /dev/time
* resource manager. This illustrates returning data to a client
* that is different on a per-device basis.
*
* This module contains all of the functions necessary.
*
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
/*
* we are extending the ocb and the attr (Timeocb_s and Timeattr_s are
* really Timeocb_t and Timeattr_t below)
*/
struct Timeattr_s;
#define IOFUNC_ATTR_T struct Timeattr_s
struct Timeocb_s;
#define IOFUNC_OCB_T struct Timeocb_s
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <string.h>
/*
* Define our device attributes structure.
*/
typedef struct Timeattr_s {
iofunc_attr_t attr;
char * format; // output format of each device
} Timeattr_t;
/*
* Define our open context block structure.
*/
typedef struct Timeocb_s {
iofunc_ocb_t ocb; // this has 'IOFUNC_ATTR_T *attr' at its top
// (ocb.offset is the current position
// in the buffer)
char *buffer; // the data returned to the client
int bufsize; // the size of the buffer
} Timeocb_t;
/*
* Number of devices, and how long or format strings are allowed to be.
*/
#define NUMDEVICES 3
#define MAX_FORMAT_SIZE 64
/*
* Declare the tables used by the resource manager.
*/
/* for a shared target, please change the time directory to something
* unique.
*/
#define TIME_DIR "/dev/time"
//#define TIME_DIR "/david/time"
// device names table
char *devnames [NUMDEVICES] =
{
TIME_DIR "/now", // offset HNow
TIME_DIR "/hour", // offset HHour
TIME_DIR "/min" // offset HMin
};
// formats for each device
char formats [NUMDEVICES][MAX_FORMAT_SIZE + 1] =
{
"%Y %m %d %H:%M:%S\n",
"%H\n",
"%M\n"
};
// pathname ID table
int pathnameID [NUMDEVICES];
// device information table
Timeattr_t timeattrs [NUMDEVICES];
/*
* some forward declarations
*/
void options (int argc, char **argv);
// I/O functions
int io_read (resmgr_context_t *ctp, io_read_t *msg, Timeocb_t *tocb);
int io_write (resmgr_context_t *ctp, io_write_t *msg, Timeocb_t *tocb);
Timeocb_t *time_ocb_calloc (resmgr_context_t *ctp, Timeattr_t *tattr);
void time_ocb_free (Timeocb_t *tocb);
// miscellaneous support functions
char *format_time (char *format, int time_offset);
/*
* our connect and I/O functions
*/
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
/*
* our ocb allocating and freeing functions
*/
iofunc_funcs_t time_ocb_funcs = {
_IOFUNC_NFUNCS,
time_ocb_calloc,
time_ocb_free
};
/*
* the mount structure, we only have one so we statically declare it
*/
iofunc_mount_t time_mount = { 0, 0, 0, 0, &time_ocb_funcs };
/*
* our dispatch, resource manager and iofunc variables
*/
dispatch_t *dpp;
resmgr_attr_t rattr;
dispatch_context_t *ctp;
/*
* some miscellaneous variables
*/
char *progname = "time"; // for diagnostic messages
int optv; // -v for verbose operation
int main (int argc, char **argv)
{
int i;
printf ("%s: starting...\n", progname);
options (argc, argv);
dpp = dispatch_create ();
memset (&rattr, 0, sizeof (rattr));
/*
* initialize the connect functions and I/O functions tables to
* their defaults and then override the defaults with the
* functions that we are providing.
*/
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
io_funcs.read = io_read;
io_funcs.write = io_write;
/*
* call resmgr_attach to register our 3 prefixes with the
* process manager, and also to let it know about our connect
* and I/O functions.
*
* On error, returns -1 and errno is set.
*/
for (i = 0; i < NUMDEVICES; i++) {
if (optv) {
printf ("%s: attaching pathname %s\n", progname, devnames [i]);
}
/*
* for this sample program we are using the same mount structure
* for all devices, we are using it solely for providing the
* addresses of our ocb calloc and free functions.
*/
iofunc_attr_init (&timeattrs [i].attr, S_IFCHR | 0666, NULL, NULL);
timeattrs [i].attr.mount = &time_mount;
timeattrs [i].format = formats[i];
pathnameID [i] = resmgr_attach (dpp, &rattr, devnames [i],
_FTYPE_ANY, 0, &connect_funcs, &io_funcs, &timeattrs [i]);
if (pathnameID [i] == -1) {
fprintf (stderr, "%s: couldn't attach pathname %s, errno %d\n",
progname, devnames [i], errno);
exit (1);
}
}
if (optv) {
printf ("%s: entering dispatch loop\n",
progname);
}
ctp = dispatch_context_alloc (dpp);
while (1) {
if ((ctp = dispatch_block (ctp)) == NULL) {
fprintf (stderr, "%s: dispatch_block failed: %s\n",
progname, strerror (errno));
exit (1);
}
dispatch_handler (ctp);
}
}
/*
* time_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 register
* it through the mount structure.
*/
Timeocb_t *
time_ocb_calloc (resmgr_context_t *ctp, Timeattr_t *tattr)
{
Timeocb_t *tocb;
if (optv) {
printf ("%s: in time_ocb_calloc \n", progname);
}
if ((tocb = calloc (1, sizeof (Timeocb_t))) == NULL) {
if (optv) {
printf ("%s: couldn't allocate %d bytes\n",
progname, sizeof (Timeocb_t));
}
return (NULL);
}
// do anything else to our part of the ocb we wish
tocb -> buffer = NULL;
return (tocb);
}
/*
* time_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 register
* it through the mount structure.
*/
void
time_ocb_free (Timeocb_t *tocb)
{
if (optv) {
printf ("%s: in time_ocb_free \n", progname );
}
/*
* if we actually allocated a buffer (ie: if the
* client called "read", as opposed to just open/close),
* return the memory associated with the buffer.
*/
if (tocb -> buffer) {
free (tocb -> buffer);
}
free (tocb);
}
/*
* io_read
*
* At this point, the client has called their library "read"
* function, and expects zero or more bytes.
* We are getting the format which we are handling for
* this request via the "tocb -> ocb . attr -> format" parameter.
*/
int
io_read (resmgr_context_t *ctp, io_read_t *msg, Timeocb_t *tocb)
{
int nleft;
int onbytes;
int status;
if (optv) {
printf ("%s: in io_read, offset is %lld, nbytes %d\n",
progname, tocb -> ocb . offset, msg -> i.nbytes);
}
if ((status = iofunc_read_verify(ctp, msg, &tocb->ocb, NULL)) != EOK)
return (status);
// No special xtypes
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
return(ENOSYS);
}
/*
* the first time in, get the time and set up
* the size
*/
if (tocb -> buffer == NULL) {
/* format the output based on the format string for the device currently being used */
tocb -> buffer = format_time (tocb -> ocb.attr -> format, 0);
tocb -> bufsize = strlen (tocb -> buffer) + 1;
}
/*
* on all reads (first and subsequent) calculate
* how many bytes we can return to the client,
* based upon the number of bytes available (nleft)
* and the client's buffer size
*/
nleft = tocb -> bufsize - tocb -> ocb . offset;
onbytes = min (msg -> i.nbytes, nleft);
/*
* do the MsgReply here. Why are we replying instead of having
* the resmgr API do it? To show that you can.
*/
if (onbytes) {
MsgReply (ctp -> rcvid, onbytes, tocb -> buffer + tocb -> ocb . offset, onbytes);
} else {
MsgReply (ctp -> rcvid, 0, NULL, 0);
}
/*
* advance the offset to reflect the number
* of bytes returned to the client.
*/
tocb -> ocb . offset += onbytes;
if (msg->i.nbytes > 0)
tocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
/*
* return _RESMGR_NOREPLY because we've done the
* MsgReply ourselves...
*/
return (_RESMGR_NOREPLY);
}
/*
* io_write
*
* At this point, the client has called their library "write"
* function. Writing is not defined for /dev/time, so we just
* swallow any bytes that they may have written, just like
* /dev/null. An alternate approach is to return an error at
* open time if we detect that the device has been opened for
* writing.
*/
int
io_write (resmgr_context_t *ctp, io_write_t *msg, Timeocb_t *tocb)
{
int status;
if (optv) {
printf ("%s: in io_write\n", progname);
}
if ((status = iofunc_write_verify(ctp, msg, &tocb->ocb, NULL)) != EOK)
return (status);
// No special xtypes
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
return(ENOSYS);
}
_IO_SET_WRITE_NBYTES (ctp, msg -> i.nbytes); // indicate how many we wrote
if (msg->i.nbytes > 0)
tocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
return (_RESMGR_NPARTS (0));
}
/*
* format_time()
*
* Format a time based on the correct device and time offset
* value.
*
* We assume that the malloc always works.
*/
char *
format_time (char *format, int time_offset)
{
char *ptr;
time_t now;
ptr = malloc (64);
time (&now);
now += time_offset;
strftime (ptr, 64, format, localtime (&now));
return (ptr);
}
/*
* options
*
* This routine handles the command line options.
* For our /dev/time family, we support:
* -v verbose operation
*/
void
options (int argc, char **argv)
{
int opt;
optv = 0;
while ((opt = getopt (argc, argv, "v")) != -1) {
switch (opt) {
case 'v':
optv = 1;
break;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
</div>
标签:resource,Timeocb,tocb,ocb,qnx,manager,io,time,iofunc 来源: https://blog.csdn.net/rifu19950726/article/details/99819400