Определить диапазон сообщений для обработчика
#include <sys/iofunc.h>#include <sys/dispatch.h>int message_attach( dispatch_t *dpp,message_attr_t *attr,int low,int high,int (*func)( message_context_t *ctp,int code,unsigned flags,void *handle ),void *handle );
Несмотря на то, что эти аргументы имеют тип int , message_attach() сохраняет их значения внутри как short . |
libc
Функция message_attach() подключает обработчик для диапазона сообщений [low, high] (включая сообщения на границах диапазона) для дескриптора диспетчера dpp.
Использование перекрывающихся диапазонов сообщений или пульсов считается ошибкой написания кода. Типы сообщений должны быть больше значения _IO_MAX (определена в <sys/iomsg.h> ). |
При получении сообщения с типом, принадлежащим указанному диапазону, dispatch_handler() вызывает установленную пользователем функцию-обработчик func. Также можно использовать ту же функцию с pulse_attach(). Изучая ctp->rcvid в func можно определить, получен пульс или сообщение.
Эта функция отвечает за выполнение любой работы, необходимой для обработки сообщения, находящегося в ctp->msg. Дескриптор handle, переданный в функцию-обработчик, это дескриптор handle, изначально переданный в message_attach().
Функция обработчик
Пользовательская функция func вызывается при получении сообщения из заданного диапазона. Функция получает контекст сообщения ctp, в котором находится сообщение, тип сообщения, и дескриптор handle (переданный в message_attach()). В настоящее время аргумент flags зарезервирован. Пользовательская функция должна возвращать 0
; другие возвраты зарезервированы.
Контекст сообщения соответствует описанию структуры message_context_t.
В данном примере создаётся менеджер ресурсов, в котором происходит подключение обработчика для диапазона приватных сообщений и пульса, который будет использован для события таймера:
#include <stdio.h>#include <stddef.h>#include <stdlib.h>#define THREAD_POOL_PARAM_T dispatch_context_t#include <sys/iofunc.h>#include <sys/dispatch.h>static resmgr_connect_funcs_t connect_func;static resmgr_io_funcs_t io_func;static iofunc_attr_t attr;int timer_tick( message_context_t *ctp, int code, unsigned flags, void *handle ){union sigval value = ctp->msg->pulse.value;/* Do some useful work on every timer firing... */printf( "received timer event, value %d\n", value.sival_int );return (0);}int message_handler( message_context_t *ctp, int code, unsigned flags, void *handle ){printf( "received private message, type %d\n", code );return (0);}int main( int argc, char **argv ){thread_pool_attr_t pool_attr;thread_pool_t *tpp;dispatch_t *dpp;resmgr_attr_t resmgr_attr;int id;int timer_id;struct sigevent event;struct _itimer itime;if ( (dpp = dispatch_create()) == NULL ){fprintf( stderr, "%s: Unable to allocate dispatch handle.\n", argv[0] );return (EXIT_FAILURE);}memset( &pool_attr, 0, sizeof pool_attr );pool_attr.handle = dpp;/* We are doing resmgr and pulse-type attaches */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;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);}iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_func,_RESMGR_IO_NFUNCS, &io_func );iofunc_attr_init( &attr, S_IFNAM | 0666, 0, 0 );memset( &resmgr_attr, 0, sizeof resmgr_attr );resmgr_attr.nparts_max = 1;resmgr_attr.msg_max_size = 2048;if ( (id = resmgr_attach( dpp, &resmgr_attr, "/dev/mynull", _FTYPE_ANY, 0,&connect_func, &io_func, &attr )) == -1 ){fprintf( stderr, "%s: Unable to attach name.\n", argv[0] );return (EXIT_FAILURE);}/* We want to handle our own private messages, of type 0x5000 to 0x5fff */if ( message_attach( dpp, NULL, 0x5000, 0x5fff, &message_handler, NULL ) == -1 ){fprintf( stderr, "Unable to attach to private message range.\n" );return (EXIT_FAILURE);}/* Initialize an event structure and attach a pulse to it */if ( (event.sigev_code = pulse_attach( dpp, MSG_FLAG_ALLOC_PULSE, 0, &timer_tick, NULL )) == -1 ){fprintf( stderr, "Unable to attach timer pulse.\n" );return (EXIT_FAILURE);}/* Connect to our channel */if ( (event.sigev_coid = message_connect( dpp, MSG_FLAG_SIDE_CHANNEL )) == -1 ){fprintf( stderr, "Unable to attach to channel.\n" );return (EXIT_FAILURE);}event.sigev_notify = SIGEV_PULSE;event.sigev_priority = -1;/* We could create several timers and use different sigev values for each */event.sigev_value.sival_int = 0;if ( (timer_id = TimerCreate( CLOCK_REALTIME, &event )) == -1 ){fprintf( stderr, "Unable to attach channel and connection.\n" );return (EXIT_FAILURE);}/* And now setup our timer to fire every second */itime.nsec = 1000000000;itime.interval_nsec = 1000000000;TimerSettime( timer_id, 0, &itime, NULL );/* Never returns */thread_pool_start( tpp );return (EXIT_SUCCESS);}
Для примера использования интерфейса диспетчера см. dispatch_create(), resmgr_attach(), и thread_pool_create().
ЗОСРВ «Нейтрино»
message_attr_t, message_context_t, dispatch_block(), dispatch_create(), dispatch_handler(), dispatch_unblock(), message_connect(), message_detach(), struct _msg_info, pulse_attach()
Предыдущий раздел: Описание API системной библиотеки