Буферизованный ввод / вывод

Android

Member
Регистрация
05.07.2019
Сообщения
86
Оценка реакций
26
C966AD7F-32C1-46FA-8EE1-D422B46AD2A7.jpeg

Обычно более эффективно читать с кратностью 4096 или 8192 байта из-за выравнивания блоков

Буферный ввод-вывод в пользовательском пространстве может увеличить производительность еще больше

Запись в буфер, который записывается в одной операции

Запросы на чтение поступают из буфера

Конечный результат - меньшее количество системных вызовов для больших объемов данных, все выровнены по границам блоков.

Предоставлено stdio

Процедуры StardardI / O действуют на файловых указателях, а не на fds

Тип FILE, определенный в stdio.h

FILE * fopen (const char * path, const char * mode);

FILE * fdopen (int fd, const char * mode);

режимы: r, w, r + (чтение + запись), w + (чтение, запись, усечение), a + (rw в режиме добавления)

Закрытие потока также закроет дескриптор файла.

int fclose (FILE * stream);

int fcloseall (void); // специфичный для Linux

чтение

// читаем символ

int fgetc (FILE * stream);

// положил его обратно

int ungetc (int c, FILE * stream);

// читаем строку

// читает на один символ меньше размера и ставит в конце

// остановит и перевод строки, а также поставит



char * fgets (char * str, int size, FILE * stream);

// Чтение двоичных данных

// читает элементы `nr`, каждый из которых имеет размер` size`

// возвращает меньше nr, если есть ошибка

// невозможно узнать, какое из двух условий произошло без использования ferror () и feof ()

size_t fread (void * buf, size_t size, size_t nr, FILE * stream);

пишу

// написать символ

// возвращаем EOF в случае ошибки

int fputc (int c, FILE * stream);

// написать строку

int fputs (const char * str, FILE * stream);

// двоичный

// Возвращаемое значение меньше nr означает ошибку.

size_t fwrite (void * buf, size_t size, size_t nr, FILE * stream);

Важно помнить, что из-за различий в размерах, выравнивании и т. Д. Двоичные данные, записанные в одном приложении, могут не читаться другими приложениями.

Пример программы

# include <stdio.h>



int main (int arc, char ** argv) {

struct пиратский {

имя персонажа [100];

длинная добыча без знака;

без знака int beard_len;

} p, blackbeard = {"Mayank", 100, 50};



FILE * file = fopen ("/ tmp / pirate", "w");

if (! file) {

PError ( "Еореп");

возврат 1;

}

if (! fwrite (& blackbeard, sizeof (struct pirate), 1, file)) {

PError ( "FWRITE");

возврат 1;

}

if (fclose (file)) {

PError ( "fclose");

возврат 1;

}



file = fopen ("/ tmp / pirate", "r");

if (! file) {

PError ( "Еореп");

возврат 1;

}

if (! fread (& p, sizeof (struct pirate), 1, file)) {

PError ( "Fread"); возврат 1;

}

if (fclose (file)) {

PError ( "fclose");

возврат 1;

}

printf ("% s,% lu,% u",

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.

, p.booty, p.beard_len);

}

Другой

int fseek (FILE * stream, long offset, int fromce);

// fsetpos, rewind, ftell, fgetpos для поиска

// fflush сбрасывает данные в ядро (но не синхронизирует)

fileno (* stream) получает fd

ошибки

ferror (FILE * stream) возвращает ненулевое значение, если установлена ошибка

feof () возвращает ненулевое значение, если EOF установлен

clearerr () очищает ошибку

Многопоточность



Стандартные функции ввода-вывода являются потокобезопасными

Для функций multipl используйте явные блокировки

flockfile (* stream) блокирует файл (блокирует), увеличивая количество блокировок

funlockfile (* stream) уменьшает количество блокировок

ftrylockfile (* stream) является неблокирующим, возврат ненулевой, если не может заблокировать.



Расширенный файловый ввод / вывод

Scatter / Gather I / O



Идея состоит в том, чтобы записать несколько буферов в файл или прочитать несколько буферов из файла.

Буферы читаются и записываются в последовательном порядке, но очень эффективно ядром

#include <sys / uio.h>

struct iovec {

void * iov_base;

size_t iov_len;

};

ssize_t readv (int fd, const struct iovec * iov, int count);

ssize_t writev (int fd, const struct iovec * iov, int count);

Epoll



проще в использовании, чем опрос и выбор, но для Linux

развязывает создание слушателя, добавление fds и ожидание на нем

#include <stdio.h>

#include <sys / epoll.h>

#include <unistd.h>

int main () {

int epfd = epoll_create1 (0);

struct epoll_event events [2];

события [0] .events = EPOLLIN;

события [0] .data.fd = STDIN_FILENO;

события [1] .events = EPOLLOUT;

события [1] .data.fd = STDOUT_FILENO;

if (epoll_ctl (epfd, EPOLL_CTL_ADD, STDIN_FILENO, & events [0]) == -1) {

PError ( "epoll_ctl");

возврат 1;

}

if (epoll_ctl (epfd, EPOLL_CTL_ADD, STDOUT_FILENO, & events [1]) == -1) {

PError ( "epoll_ctl");

возврат 1;

}



struct epoll_event out_events [2];

int events_ready = epoll_wait (epfd, out_events, 2, 0);

if (events_ready == -1) {

PError ( "epoll_wait");

возврат 1;

}



printf («События готовы:% d \ n», events_ready);

for (int i = 0; i <events_ready; i ++) {

printf («Событие fd:% i:% i \ n», out_events .events, out_events .data.fd);

}

вернуть 0;

}

MMAP



mmap отображает файл в память

#include <sys / mman.h>

void * mmap (void * addr, size_t len, int prot, int flags, int fd, off_t offset);

Прот - режим защиты - PROT_READ, PROT_WRITE, PROT_EXEC

должно соответствовать открытому режиму файла

флаги:



MAX_FIXED - адрес является обязательным, а не обязательным (не рекомендуется)

MAP_PRIVATE - файл отображается при копировании при записи

MAP_SHARED - используется совместно с другими процессами, отображающими этот файл

должен быть указан один из двух предыдущих, но не оба

отображение увеличивает счетчик ссылок файла

addr и offset должны быть выровнены по границе страницы

чтобы получить размер страницы

long page_size = sysconf (_SC_PAGESIZE); // <unistd.h>

// или же

int getpagesize (void);

удалить отображение:

int munmap (void * arrd, size_t len);

удалит все сопоставления в заданном диапазоне

пример

#include <sys / types.h>

#include <sys / stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <sys / mman.h>

#include <stdio.h>



int main (int argc, char * argv []) {



if (argc! = 2) {

printf ("Должно содержать имя файла \ n"); возврат 1;

}



int fd = open (argv [1], O_RDONLY);

if (fd == -1) {

PError ( "открытый"); возврат 1;

}



struct stat sb;



if (fstat (fd, & sb) == -1) {

PError ( "fstat"); возврат 1;

}



if (! S_ISREG (sb.st_mode)) {

printf ("Не обычный файл \ n"); возврат 1;

}



char * p;

if ((p = mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {

PError ( "ММАП"); возврат 1;

}



for (int i = 0; i <sb.st_size; i ++) {

путчар (* (p + i));

}

putchar ( '\ п');



if (munmap (p, sb.st_size) == -1) {

PError ( "munmap"); возврат 1;

}
вернуть 0;
}