A
Android
Original poster
Обычно более эффективно читать с кратностью 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;
}