Русские Блоги
1. Что такое файловый дескриптор? (Файловый API Linux)
- Дескрипторы файлов используются для различения нескольких файлов, открытых программой.
- Область дескриптора файла — текущий процесс, дескриптор файла не имеет смысла вне текущего процесса.
- open, creat () возвращает fd, все последующие операции полагаются на то, что этот fd соответствует этому файлу, и, наконец, при закрытии файла fd также необходимо указать, чтобы закрыть файл. Если fd утерян до того, как мы закроем файл, то файл не может быть закрыт, его нельзя будет прочитать или записать.
- При запуске процесса по умолчанию открываются 3 файла: стандартный ввод, стандартный вывод и стандартная ошибка. Соответствующие файловые дескрипторы: 0 (STDIN_FILENO), 1 (STDOUT_FILENO) и 2 (STDERR_FILENO). Эти константы определены в unistd Заголовочный файл .h. в.
- Когда после запуска программы открываются другие файлы, система возвращает наименьший доступный файловый дескриптор в таблице файловых дескрипторов и записывает этот файловый дескриптор в таблицу. Процесс в Linux может открывать не более NR_OPEN_DEFAULT (т.е. 1024) файлов, поэтому, когда файл больше не используется, должна быть вызвана функция close (), чтобы вовремя закрыть файл.
2. Что такое ввод-вывод
Ввод / вывод — это процесс копирования данных между основной памятью и внешними устройствами Устройство -> Память (операция ввода) Память -> Устройство (операция вывода) Расширенный ввод / вывод ANSI
Стандартная библиотека ввода-вывода, предоставляемая C, называется высокоуровневым вводом-выводом, обычно также называемым буферизованным вводом-выводом, низкоуровневый ввод-вывод обычно называется небуферизованным вводом-выводом.
Прежде чем говорить о функциях системного вызова read (), write (), давайте сначала рассмотрим операции ввода-вывода без кеширования и стандартные операции ввода-вывода (т. Е. Операции ввода-вывода с кешем).
3. С или без ввода-вывода кеша
- Некэшированные функции чтения () и записи () ввода-вывода, чтение и запись файлов непосредственно с жесткого диска, все они являются системными вызовами, только в кеше ядра
- Существуют кешированные функции ввода-вывода (стандартный ввод-вывод) fread (), fwrite (), все они вызываются пользовательским уровнем, и есть кеши в ядре и на пользовательском уровне.
Цель стандартного ввода-вывода для обеспечения кэширования — уменьшить количество вызовов для чтения и записи, тем самым повышая эффективность чтения и записи.
Следующий тестовый код может доказать, что открытие и запись не буферизуются, то есть, когда программа выполняет свою операцию io, она будет выполнена немедленно, она не останется в буфере, предоставленном системой, и не будет выполняться до тех пор, пока операция закрытия завершена. Команды fopen и fwrite буферизуются и не будут выполняться до завершения операции fclose. Пошаговая отладка печати кода позволяет увидеть это явление
#include #include #include #include #include #include int main() < int fd; FILE *file; char *str="hello,world\n"; if((fd=open("test1.txt",O_RDWR|O_CREAT|O_TRUNC,775))<0) < printf("Error open file"); return -1; >if((file=fopen("test2.txt","w"))==NULL) < printf("Error Open File."); return -1; >printf("File has been Opened."); sleep(15); if(write(fd,str,strlen(str)) if(fwrite(str,sizeof(char),strlen(str),file) printf("After write"); sleep(15); printf("After sleep."); close(fd); fclose(file); printf("end\n:"); return 0; >
4. Общие функции системного вызова
int open(const char *pathname, int flags);
Функция: Откройте файл и создайте его, если он не существует.
Параметры: pathname: путь к файлу, flags: флаги поведения открытия файла, такие как: open in read-only mode (O_RDONLY, первая буква не является данными), open file in read-write или new file mode (O_RDWR | O_CREAT) режим
Возвращаемое значение: Успех: Успешно вернуть дескриптор открытого файла
не удалось: -1
Функция: закрыть открытый файл
Параметры: дескриптор файла fd, возвращаемое значение open (), create ()
Возвращаемое значение: Успех: 0
не удалось: -1
ssize_t read(int fd, void *buf, size_t count);
Функция: считывать указанное количество данных в память (буфер)
параметр
fd: файловый дескриптор файла, который вы хотите прочитать.
buf: указатель на блок памяти, байты, считанные из файла, помещаются в этот блок памяти.
count: указывает содержимое, которое вы хотите прочитать из файла (Примечание: это число счетчика может быть присвоено по желанию, и, наконец, фактическое возвращенное число (возвращаемое значение чтения) будет иметь преимущественную силу.
Возвращаемое значение: Успех: вернуть количество байтов, скопированных из файла в указанный буфер.
Ошибка: возврат -1
Примечание: если у read () есть файловый дескриптор, связанный с описанием открытого файла, пока файл открыт с флагами O_RDONLY или O_RDWR, вы можете использовать системный вызов read () для чтения байтов из файла.
ssize_t write(int fd, const void *buf, size_t count);
Функция: используйте системный вызов write () для записи данных в файл
fd: файловый дескриптор записываемого файла
buf: указатель на блок памяти, чтение данных из этого блока памяти и запись их в файл
count: количество байтов для записи в файл
Успех: количество байтов, фактически записанных в данные
Ошибка: возврат -1
Примечание: распространенной причиной ошибок записи является то, что диск заполнен или превышен предел длины файла. Write () на самом деле не записывает на диск, а сначала записывает в буфер памяти, а затем записывает в буфер, когда буфер заполнен или выполняется операция обновления. Диск, если вы хотите записывать на диск в реальном времени, вы можете вызвать int fsync (int fd); или добавить O_SYNC к флагам при открытии
off_t lseek(int fds, off_t offset, int whence);
Тип off_t в Linux обычно является длинным, а по умолчанию — 32-битным целым числом. При компиляции gcc он будет скомпилирован как длинный тип int. В 64-битной системе Linux он будет скомпилирован как длинный long int, 64-битное целое число., которое определено в файле заголовка unistd.h
Функция: используется для указания позиции смещения файла, чтобы реализовать произвольный доступ к файлу.
fds — это дескриптор файла, который будет записан, обычно получается путем открытия, создания
смещение — это смещение файла, которое относится к расстоянию, на которое перемещается каждая операция чтения и записи файла
откуда: SEEK_SET, смещение файла будет установлено равным смещению.
где: SEEK_CUR, смещение файла будет установлено равным текущему смещению плюс смещение, смещение может быть положительным или отрицательным.
откуда: SEEK_END, смещение файла будет установлено равным длине файла плюс смещение, смещение может быть положительным или отрицательным.
возвращаемое значение
Успешно: вернуть новое смещение файла
ошибка: возврат -1
5. функции системного вызова read (), write () для реализации содержимого файла cp
#include #include #include #include #include int main(int argc, char *argv[]) < if((argc == 3) && (strcmp(argv[1], argv[2]) != 0)) < int fd_src, fd_dest, ret; char buf [1024]; // Считываем данные из исходного файла и сохраняем их в buf memset(buf, 0, sizeof(buf)); fd_src = open(argv[1], O_RDONLY); if(fd_src < 0) < perror("open argv[1]"); return -1; >// Новый целевой файл fd_dest = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC,0644); if(fd_dest < 0) < close(fd_src); perror("open argv[2]"); return -1; >while((ret = read(fd_src, buf, sizeof(buf)))> 0) < // Записываем данные в целевой файл, обращаем внимание на последний параметр, сколько писать write(fd_dest, buf, ret); >// Закрываем открытый файл close(fd_src); close(fd_dest); return 0; > printf ("Пожалуйста, введите правильное имя файла как './example303CreateFun имя файла' \ n"); // Ошибка параметра return -1; >
Результаты тестирования кода
6. Используйте lseek для расчета длины файла.
#include #include #include #include #include #include int main(int argc,char *argv[]) < int fd,length; if(argc<2) < puts("Please input the open file pathname!\n"); return -1; >if((fd=open(argv[1],O_RDONLY)) <0) < perror("Open file failure!"); return -1; >if((length = lseek(fd,0,SEEK_END)) <0) < perror("lseek file failure!"); >printf("The file's length is %d\n",length); close(fd); return 0; >
Результаты теста следующие: