Эта проблема может быть решена применением «своих собственных» сообщений на основе общего механизма управляющих последовательностей, поддерживаемого в сообщениях типа _IO_MSG.
Сообщение типа _IO_MSG было предусмотрено для того, чтобы дать вам возможность вводить свои собственные типы сообщений, не конфликтуя при этом со «стандартными» типами сообщений администраторов ресурсов, поскольку для администраторов ресурсов сам тип сообщения _IO_MSG уже является «стандартным».
Первое, что вы должны сделать при использовании сообщений типа _IO_MSG — это определить ваши «специальные» сообщения. В этом примере мы определим два таких типа и последуем стандартной модели сообщений администратора ресурсов: один тип будет сообщением ввода, другой — вывода.
typedef struct {
int data_rate;
int more_stuff;
} my_input_xyz_t;
typedef struct {
int old_data_rate;
int new_data_rate;
int more_stuff;
} my_output_xyz_t;
typedef union {
my_input_xyz_t i;
my_output_xyz_t o;
} my_message_xyz_t;
Здесь мы определили новый тип — объединение (union) из сообщений ввода и вывода — и назвали этот тип my_message_xyz_t
xyz
» какова бы она ни была. Сообщение ввода имеет тип my_input_xyz_t
, а сообщение вывода — my_output_xyz_t
. Отметьте, что и «ввод», и «вывод» определяются с позиции администратора ресурса: «ввод» — это данные, поступающие Нам надо придумать какой-то вызов API для клиента — мы, конечно, можем принудить клиента «вручную» заполнять структуры my_input_xyz_t
my_output_xyz_t
, но я не рекомендовал бы так делать по той причине, что API призван «отвязать» реализацию передаваемого сообщения от функциональности. Давайте предположим, что API клиента у нас такой:int adjust_xyz(int *
int *
Теперь мы имеем хорошо документированную функцию
int adjust_xyz(int *dr, int *odr, int *ms) {
my_message_xyz_t msg;
int sts;
msg.i.data_rate = *dr;
msg.i.more_stuff = *ms;
sts =
io_msg(global_fd, COMMAND_XYZ, &msg, sizeof(msg.i),
sizeof(msg.o));
if (sts == EOK) {
*odr = msg.o.old_data_rate;
*ms = msg.o.more_stuff;
}
return (sts);
}
Это пример применения функции
sizeof(msg.i)
), другой — для вывода (sizeof(msg.о)
). Заметьте, что мы обновляем значения Последнее, что я сделал в функции
• Скрыть дескриптор файла внутри функции
• Передавать от клиента дескриптор файла каждому вызову функции библиотеки API (полезно, если клиент хочет разговаривать с администратором ресурса еще и другими способами, например, стандартными POSIX-вызовами на основе файловых дескрипторов типа
Вот текст функции
int io_msg(int fd, int cmd, void *msg, int isize,
int osize) {
io_msg_t io_message;
iov_t rx_iov[2];
iov_t tx_iov[2];
int sts;
Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT