procmgr_event_notify()

Запросить получение уведомлений об общесистемных событиях

Прототип:

#include <sys/procmgr.h>
int procmgr_event_notify( unsigned flags,
const struct sigevent *event );

Аргументы:

flags
Побитовое ИЛИ типов событий, для которых запрашивается получение уведомлений, либо 0, чтобы отключить ивент struct sigevent. Типы событий включают в себя:
PROCMGR_EVENT_CONFSTR
PROCMGR_EVENT_DAEMON_DEATH
PROCMGR_EVENT_PATHSPACE
PROCMGR_EVENT_SYNC
PROCMGR_EVENT_SYSCONF
event
Указатель на структуру struct sigevent, которая определяет способ получения уведомлений.

Библиотека:

libc

Описание:

Функция procmgr_event_notify() запрашивает у менеджера процессов получение уведомлений об общесистемных событиях, идентифицированных аргументом flags. Процесс может иметь только один активный запрос на уведомление.

Типы событий

Следующие типы событий определены в <sys/procmgr.h>:

PROCMGR_EVENT_CONFSTR
Процесс задал строку конфигурации.
PROCMGR_EVENT_DAEMON_DEATH
Процесс в сессии 1 завершился. Это событие наиболее полезно для отслеживания завершения процессов демонов, которые используют procmgr_daemon() для перевода себя в сессию 1 и закрытия/перенаправления файловых дескрипторов. Завершение демонов трудно обнаружить другим способом.

Note: Уведомление осуществляется через аргумент event, поэтому информация о том, какой процесс завершился, не предоставляется. После того, как было получено уведомление о событии, нужно выполнить дополнительные действия, чтобы определить завершившиеся процессы. Это можно сделать, опросив список всех процессов в поиске конкретных идентификаторов процессов и имен. Если нужный идентификатор процесса не найден – это значит, что процесс завершился. Пример ниже демонстрирует, как можно это сделать.

PROCMGR_EVENT_PATHSPACE
Менеджер ресурсов добавил или удалил запись (например, точку монтирования) в пространстве путей. Обычно это связано с библиотечными вызовами resmgr_attach() и resmgr_detach(). Завершение процесса менеджера ресурсов также генерирует это событие, если точки монтирования не были заранее отсоединены.
PROCMGR_EVENT_SYNC
Процесс вызвал sync() для синхронизации файловых систем.
PROCMGR_EVENT_SYSCONF
Процесс задал строку системной конфигурации.

Возвращаемое значение:

-1
Возникла ошибка.
≠-1
Успешное завершение.

Примеры:

/*
* Пример демонстрирует использование procmgr_event_notify() с флагом PROCMGR_DAEMON_DEATH.
* Он позволяет получать уведомления, если какой-либо процесс в сессии 1 завершается.
* Демоны — это процессы, которые затрудняют обнаружение своего завершения, вызывая функцию
* procmgr_daemon(). Одна из таких мер заключается в том, что демоны завершаются в сессии 1.
* В этом и проявляется полезность флага PROCMGR_DAEMON_DEATH.
*
* Уведомление не сообщает какой именно процесс завершился. Получив уведомление, нужно
* пройтись по списку процессов, которые все еще работают и определить, все ли искомые
* процессы все еще работают. Если известны идентификаторы этих процессов, то это становится
* проще. Если они не известны, можно определять процессы по имени. Код ниже выполняет поиск
* по имени.
*/
#include <devctl.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/procfs.h>
#include <sys/procmgr.h>
static int check_if_running( char *process );
#define DAEMON_DIED_CODE (_PULSE_CODE_MINAVAIL)
struct dinfo_s {
procfs_debuginfo info;
char pathbuffer[PATH_MAX];
};
int main( int argc, char **argv )
{
char *daemon_to_watch;
int chid, coid, rcvid;
struct sigevent event;
struct _pulse msg;
if ( argc != 2 )
{
printf( "use: %s process_to_watch_for\n", argv[0] );
exit( EXIT_FAILURE );
}
daemon_to_watch = argv[1]; /* отслеживаемый процесс */
chid = ChannelCreate( 0 );
coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
SIGEV_PULSE_INIT( &event, coid, SIGEV_PULSE_PRIO_INHERIT,
DAEMON_DIED_CODE, 0 );
/*
* Запрос получения уведомлений в виде пульсов при завершении демона
*/
if ( procmgr_event_notify( PROCMGR_EVENT_DAEMON_DEATH, &event ) == -1 )
{
fprintf( stderr, "procmgr_event_notify() failed" );
exit( EXIT_FAILURE );
}
while ( 1 )
{
rcvid = MsgReceive( chid, &msg, sizeof(msg), NULL );
if ( rcvid != 0 )
{
/* полученное не является пульсом; возможна ошибка или получение сообщения */
exit( EXIT_FAILURE );
}
if ( check_if_running( daemon_to_watch ) == 0 )
printf( "%s is no longer running\n", daemon_to_watch );
}
return (0);
}
/*
* check_if_running - функция производит поиск процесса по имени.
*/
static int check_if_running( char *process )
{
DIR *dirp;
struct dirent *dire;
char buffer[20];
int fd, status;
pid_t pid;
struct dinfo_s dinfo;
if ( (dirp = opendir( "/proc" )) == NULL )
{
perror( "Could not open '/proc'" );
return (-1);
}
while ( 1 )
{
if ( (dire = readdir( dirp )) == NULL )
break;
if ( isdigit( dire->d_name[0] ) )
{
pid = strtoul( dire->d_name, NULL, 0 );
sprintf( buffer, "/proc/%d/as", pid );
if ( (fd = open( buffer, O_RDONLY )) != NULL )
{
status = devctl( fd, DCMD_PROC_MAPDEBUG_BASE,
&dinfo, sizeof(dinfo), NULL );
if ( status == EOK )
{
if ( !strcmp( process, basename( dinfo.info.path ) ) )
{
closedir( dirp );
/* следует закрыть дескриптор, чтобы избежать утечек памяти */
close( fd );
return (1);
}
} /* ветка обработки ошибок */
close( fd );
}
}
}
closedir( dirp );
return (0);
}

Классификация:

ЗОСРВ «Нейтрино»

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

procmgr_daemon(), procmgr_event_trigger(), struct _pulse, struct sigevent




Предыдущий раздел: Описание API системной библиотеки