Чтение онлайн

на главную - закладки

Жанры

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

Кёртен Роб

Шрифт:

Возврат данных клиенту осуществляется «обычным» способом при помощи функции MsgReply. Заметьте, что поле состояния (status) функции MsgReply используется для указания числа отправленных клиенту байт.

static int my_read_dir(resmgr_context_t *ctp,

 io_read_t *msg, iofunc_ocb_t *ocb) {

 int nbytes;

 int nleft;

 struct dirent *dp;

 char *reply_msg;

 char fname[_POSIX_PATH_MAX];

 //
Выделить буфер для ответа

 reply_msg = calloc(1, msg->i.nbytes);

 if (reply_msg == NULL) {

return (ENOMEM);

 }

 // Назначить выходной буфер

 dp = (struct dirent *)reply_msg;

 // Осталось «nleft» байт

 nleft = msg->i.nbytes;

 while (ocb->offset < NUM_ENTS) {

// Создать имя файла

sprintf(fname, "%с", ocb->offset + "a");

// Проверить, насколько велик результат

nbytes = dirent_size(fname);

// Есть место?

if (nleft - nbytes >= 0) {

// Заполнить элемент каталога и увеличить указатель

dp =

dirent_fill(dp, ocb->offset + 1, ocb->offset, fname);

// Увеличить смещение OCB

ocb->offset++;

// Учесть, сколько байт мы использовали

nleft -= nbytes;

} else {

// Места больше нет, остановиться

break;

}

 }

 // Возвращаемся обратно к клиенту

 MsgReply(ctp->rcvid, (char*)dp - reply_msg, reply_msg,

(char*)dp — reply_msg);

 // Освободить буфер

 free(reply_msg);

 // Сказать библиотеке, что мы уже ответили сами

 return (_RESMGR_NOREPLY);

}

my_read_file

В функции my_read_file мы видим код, почти аналогичный простому примеру функции чтения, который приведен выше в данном разделе. Единственная странная вещь, которую мы здесь делаем — поскольку мы знаем, что возвращается всегда только один байт данных, значит, если параметр nbytes не равен нулю, то он должен быть равен единице (и ничему другому). Таким образом, мы можем создавать данные, подлежащие возврату, непосредственным заполнением символьной переменной string. Обратите внимание, как мы используем поле inode атрибутной записи для определения, какие данные возвращать. Это обычный прием для администраторов, обслуживающих несколько ресурсов. Дополнительным трюком было бы расширить атрибутную запись (мы говорили об этом в разделе «Расширение атрибутной записи») и хранить непосредственно в ней либо сами данные, либо указатель на них.

static int my_read_file(resmgr_context_t *ctp,

 io_read_t *msg, iofunc_ocb_t *ocb) {

 int nbytes;

 int nleft;

 char string;

 // Тут нет никаких xtype...

 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) (

return (ENOSYS);

 }

 // Выяснить, сколько байт осталось...

 nleft = ocb->attr->nbytes — ocb->offset;

 // ...и сколько мы можем возвратить клиенту

 nbytes = min(nleft, msg->i.nbytes);

 if (nbytes) {

// Создать ответную строку

string = ocb->attr->inode - 1 + "A";

// Возвратить ее клиенту

MsgReply(ctp->rcvid, nbytes, &string + ocb->offset,

nbytes);

// Обновить флаги и смещение

ocb->attr->flags |=

IOFUNC_ATTR_ATIME | IOFUNC_ATTR_DIRTY_TIME;

ocb->offset += nbytes;

 } else {

// Возвращать нечего, индицировать конец файла

MsgReply(ctp->rcvid, EOK, NULL, 0);

 }

 // Уже ответили сами

 return (_RESMGR_NOREPLY);

}

dirent_size

Вспомогательная подпрограмма dirent_size просто вычисляет число байт, необходимое для структуры

struct dirent
, с учетом ограничений по выравниванию. Опять же, для нашего простого администратора ресурсов здесь имеет место небольшое искусственное упрощение, потому что мы точно знаем, каков размер каждого элемента каталога — все имена файлов имеют длину ровно один байт. Однако, как бы там ни было, это все равно полезная служебная подпрограмма.

int dirent_size(char *fname) {

return (ALIGN(sizeof(struct dirent) - 4 + strlen(fname)));

}

dirent_fill

И, наконец, вспомогательная подпрограмма dirent_fill применяется для помещения передаваемых ей значений (а именно — полей inode, offset и fname) в также передаваемый ей элемент каталога. В порядке щедрости она также возвращает указатель на адрес (с учетом выравнивания), с которого должен начинаться следующий элемент каталога.

Поделиться:
Популярные книги

Студент

Гуров Валерий Александрович
1. Студент
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Студент

Варлорд

Астахов Евгений Евгеньевич
3. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Варлорд

Как я строил магическую империю

Зубов Константин
1. Как я строил магическую империю
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю

Кодекс Охотника. Книга XII

Винокуров Юрий
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XII

Неудержимый. Книга II

Боярский Андрей
2. Неудержимый
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Неудержимый. Книга II

Измена

Рей Полина
Любовные романы:
современные любовные романы
5.38
рейтинг книги
Измена

Пенсия для морского дьявола

Чиркунов Игорь
1. Первый в касте бездны
Фантастика:
попаданцы
5.29
рейтинг книги
Пенсия для морского дьявола

Не грози Дубровскому! Том V

Панарин Антон
5. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том V

Утопающий во лжи 3

Жуковский Лев
3. Утопающий во лжи
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Утопающий во лжи 3

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Средневековая история. Тетралогия

Гончарова Галина Дмитриевна
Средневековая история
Фантастика:
фэнтези
попаданцы
9.16
рейтинг книги
Средневековая история. Тетралогия

Измена. Возвращение любви!

Леманн Анастасия
3. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Возвращение любви!

Комбинация

Ланцов Михаил Алексеевич
2. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Комбинация

Кодекс Охотника. Книга V

Винокуров Юрий
5. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
4.50
рейтинг книги
Кодекс Охотника. Книга V