Только что открытый дескриптор файла начинается с позиции = 0. Если вы продолжите чтение с того же fd
в oop, вы получите последовательные фрагменты. (Используйте больший буфер, такой как 8kiB и l oop над двойными словами в пользовательском пространстве, хотя, используя значение, которое read
вернуло в качестве верхнего предела! Системный вызов очень дорог во времени ЦП.)
Можно ли начать чтение файла с заданной c строки или байта.
- Байт: да
- Строка: нет. В Unix / Linux ядро не имеет индекса смещения начала строки или какого-либо другого линейно-ориентированного API. Например, обработка строки в stdio
fgets
выполняется исключительно в пользовательском пространстве. Существовали некоторые исторические ОС с файлами на основе записей, но файлы Unix представляют собой плоские массивы байтов. (Они могут иметь дыры, неписанные экстенты и расширенные атрибуты ... Но API ядра для содержимого основного файла работают только с байтовыми смещениями).
Если вы хотите сделать строки, прочитайте большой блок и l oop вперёд, пока вы не увидите некоторое количество новых строк. Если вы еще не там, прочитайте другой блок; повторяйте, пока не найдете начало и конец нужного номера строки, или пока не нажмете EOF. x86-64 может эффективно искать 16 байтов одновременно с pcmpeqb
/ pmovmskb
/ popcnt
(popcnt требует SSE4.2 или заданный c функциональный бит popcnt).
Или только с SSE2 или при оптимизации для больших блоков: от pcmpeqb
/ psadbw
(против всех нулей) до байтов от hsum до qwords / paddd
. Затем проверьте, сколько строк вы проходили так часто с помощью скалярного кода. Или сделайте это простым и переходите к поиску первой новой строки в векторе SIMD.
Очевидно, что медленным и простым вариантом является l oop байт за раз, который насчитывает '\n'
символов - если вы знать, как сделать strchr с SSE2, это должно быть просто векторизовать этот поиск, используя приведенные выше предложения.
Но если вам нужны только некоторые определенные c байтовые позиции, у вас есть два основных варианта :
- искать с
lseek(2)
до read(2)
(см. Ответ @ Nicolae Natea) Использовать POSIX / Linux pread(2)
для чтения из указанного смещения , не перемещая смещение файла FD для будущих вызовов read
. Linux имя системного вызова: pread64
(__NR_pread64 equ 17
от asm/unistd_64.h
)
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
Единственное отличие от read
- смещение аргумента, 4-й аргумент таким образом передается в R10 (не RCX, как соглашение о вызове функций в пространстве пользователя). off_t
- это 64-битный тип, который просто передается в одном регистре в 64-битном коде.
Кроме имени pread64
в .h
, в этом нет ничего особенного Интерфейс asm по сравнению с интерфейсом C соответствует стандартному соглашению о системных вызовах. (Он существует с Linux 2.1.60; до этого оболочка glib c эмулировала его с помощью lseek.)
Есть и другие вещи, которые вы можете сделать, например mmap
или preadv
системный вызов, но pread - это именно то, что вам нужно, если у вас есть известная позиция, с которой вы хотите прочитать.