LINUX.ORG.RU

fwrite + много pread

 ,


0

1

Приветствую.

В продолжении темы

Напомню - пишу по кольцу с камеры на флешку без файловой системы через буфер fwrite кусками по 256КБ, из за нехватки времени заняться вопросом скачивание архива выполнялось в полурукопашном режиме через открытие отдельного FILE* или дескриптора в отдельном потоке и долгая перекачка по ентернетам.

Пришло время заняться вопросом отдать архив нескольким клиентам одновременно и собсна вопрос - можно ли через уже открытый FILE* и int fd = fileno(FILE*), используя pread со своим смещением в каждом потоке безопасно выполнять выгрузку одного и того же «файла»? или лучше для каждой выгрузки-потока выполнять свой open?

ЗЫ. на старте не знаю сколько будет одновременно читающих потоков.

★★★

Ответ на: комментарий от wolverin

или лучше для каждой выгрузки-потока выполнять свой open?

ибо в этом случае полагаю не нужны никакие синхронизации

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

Тут мб лучше вариат синхронного чтения и асинхронной отправки в тредах? Для меня звучит немного медленнее, но надёжнее.

Bfgeshka ★★★★★
()
Ответ на: комментарий от wolverin

На здоровье. Но хочу заметить, что параллельное чтение никогда не делал и мб можно сделать так, как вы раньше хотели.

Bfgeshka ★★★★★
()
Ответ на: комментарий от Bfgeshka

принято, просто «файл» может быть 512Гб при 512МБ памяти и думаю как эффективней «метаться» по нему )

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)

Никаких проблем pread не создаст хоть в 1 поток хоть в 10. Осталось сделать наконец ещё один шаг - выкинуть ненужное stdio, файл открывать через open() и писать через write(), буфер записи реализовать самостоятельно.

firkax ★★★★★
()
Ответ на: комментарий от firkax

спасибо, через фврайт пишется нормально без реализации самостоятельного захода солнца )

посмотрел уже strace [pid ] write(7, "..."..., 262144) = 262144

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)

а вот тут лучше mmap :-) если с ним делать правильно - будут меньше требования по памяти. Сэкономишь на клиентских буферах

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

а при pread разве не так же будут в память подниматься данные? все таки в этот раз нужно последовательное чтение всех байт, а не как прошлый раз только условных 20

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

а при pread разве не так же будут в память подниматься данные? все таки в этот раз нужно последовательное чтение всех байт, а не как прошлый раз только условных 20

в клиентских pread ты-же эти данные куда-то читаешь и копируешь? лишний буфер, лишнее копирование. Клиенты которые только читают могут mmap`ить фрагменты и эффективно разделят общую память.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

присваиваю адрес считанных байтов структуре ффмпега AVPacket и вызываю av_write_frame, потом делаю смещение на величину кадра и так весь буфер, т.е. сам я ничего никуда не копирую

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

присваиваю адрес считанных байтов структуре ффмпега AVPacket и вызываю av_write_frame, потом делаю смещение на величину кадра и так весь буфер, т.е. сам я ничего никуда не копирую

facepalm :-(

а pread как по вашему, что делает ? копирует

MKuznetsov ★★★★★
()
Ответ на: комментарий от wolverin

То что он делает внутри write() это понятно, тут других вариантов то и нет. Но ты ради одного примитивного буфера тащишь тяжеленную обёртку с кучей ненужного внутри.

firkax ★★★★★
()
Ответ на: комментарий от wolverin

Он имеет ввиду что pread копирует из кеша ОС в память твоей проги. А mmap и правда не копирует, а отображает кеш напрямую в твоё адресное пространство. Но это всё мелочи по сравнению с временем на собственно чтение с диска.

Если строго, то pread и правда не читает, он отправляет запрос кешу, движок кеша читает и отвечает pread-у, что данные готовы и их можно отдать проге. тобы читать напрямую, нао файл открывать с O_DIRECT но там лишняя возня будет на линуксе.

firkax ★★★★★
()
Ответ на: комментарий от firkax

ещё имел в виду, что когда несколько клиентов-ридеров работают с одним файлом и примерно в одной области, то mmap`ят они одну и ту-же память и не надо создавать (аллоцировать) чего-то дополнительного.

Не без проблем будет: с выравниванием по страницам придётся потрахаться, желательно чтобы и на носители тоже всё ровненько лежало.

MKuznetsov ★★★★★
()
Ответ на: комментарий от firkax

Большое спасибо за ликбез, но наверное все таки на приад останавлюсь пока, поскольку не потребуется ммап анммап делать когда появляются читатели или держать его все время, ещё нет статистики но наверное больше одного читателя будет редко.

Нет пока времени на велосипедостроение и в том числе поэтому фврайт.

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 2)

Если бы ты писал pwrite — да. fwrite буферизирует часть на стороне приложения.

cumvillain
()

А ещё можно использовать sendfile — копировать из файла в сокет мимо юзерспейса, с буферизацией только в ядерный page cache. Без отдельного open на каждое соединение не обойтись. Но это кмк не проблема.

iliyap ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.