- Windows open close read write
- open, read, write, close
- Открытие файла
- Чтение/запись файла
- Чтение/запись сложных объектов за один системный вызов
- Закрытие файла
- Установка смещения в файле
- Манипулирование файловыми дескрипторами
- File Operations, Open, Write, and Close Files In C
- stdio.h Library
- Opening File
- Closing File
- Reading File
- Writing File
Windows open close read write
Important Terminology
What is the File Descripter??
File descriptor is integer that uniquely identifies an open file of the process.
File Descriptor table: File descriptor table is the collection of integer array indices that are file descriptors in which elements are pointers to file table entries. One unique file descriptors table is provided in operating system for each process.
File Table Entry: File table entries is a structure In-memory surrogate for an open file, which is created when process request to opens file and these entries maintains file position.
Standard File Descriptors: When any process starts, then that process file descriptors table’s fd(file descriptor) 0, 1, 2 open automatically, (By default) each of these 3 fd references file table entry for a file named /dev/tty
/dev/tty: In-memory surrogate for the terminal
Terminal: Combination keyboard/video screen
Read from stdin => read from fd 0 : Whenever we write any character from keyboard, it read from stdin through fd 0 and save to file named /dev/tty.
Write to stdout => write to fd 1 : Whenever we see any output to the video screen, it’s from the file named /dev/tty and written to stdout in screen through fd 1.
Write to stderr => write to fd 2 : We see any error to the video screen, it is also from that file write to stderr in screen through fd 2.
I/O System calls
Basically there are total 5 types of I/O system calls:
- Create: Used to Create a new empty file.
- Parameter :
- Returns :
- Create new empty file on disk
- Create file table entry
- Set first unused file descriptor to point to file table entry
- Return file descriptor used, -1 upon failure
Parameters
- Path : path to file which you want to use
- use absolute path begin with “/”, when you are not work in same directory of file.
- Use relative path which is only file name with extension, when you are work in same directory of file.
- flags : How you like to use
- O_RDONLY: read only, O_WRONLY: write only, O_RDWR: read and write, O_CREAT: create file if it doesn’t exist, O_EXCL: prevent creation if it already exists
- How it works in OS
Output:
close: Tells the operating system you are done with a file descriptor and Close the file which pointed by fd.
- Parameter
- Return
- 0 on success.
- -1 on error.
- How it works in the OS
- Destroy file table entry referenced by element fd of file descriptor table
– As long as no other process is pointing to it! - Set element fd of file descriptor table to NULL
Here, In this code first open() returns 3 because when main process created, then fd 0, 1, 2 are already taken by stdin, stdout and stderr. So first unused file descriptor is 3 in file descriptor table. After that in close() system call is free it this 3 file descriptor and then after set 3 file descriptor as null. So when we called second open(), then first unused fd is also 3. So, output of this program is 3.
read: From the file indicated by the file descriptor fd, the read() function reads cnt bytes of input into the memory area indicated by buf. A successful read() updates the access time for the file.
- Parameters
- Returns: How many bytes were actually read
- return Number of bytes read on success
- return 0 on reaching end of file
- return -1 on error
- return -1 on signal interrupt
- Important points
- buf needs to point to a valid memory location with length not smaller than the specified size because of overflow.
- fd should be a valid file descriptor returned from open() to perform read operation because if fd is NULL then read should generate error.
- cnt is the requested number of bytes read, while the return value is the actual number of bytes read. Also, some times read system call should read less bytes than cnt.
open, read, write, close
Открытие файла
Работа с содержимым файла происходит через целочисленный файловый дескриптор, который представляет из себя номер строки в таблице ссылок на открытые файлы процесса.
При открытии файла в вызове ядра open() проверяются соответствие флагов и прав доступа к файлу.
mode — права доступа к файлу, назначаемые в момент его создания. Чтобы нельзя было случайно создать файл со слишком свободным доступом, при создании файла производится побитовое умножение mode на битовую маску umask (mode &
umask). mode и _umask__ удобно задавать в восьмеричном виде считая, что классические права доступа rwx соответствуют одной восьмеричной цифре. Например, права доступа rwxr-xr— запишутся в восьмеричном виде как 0754. Типичная маска выглядит так —w—w- или 022в восьмеричной записи. Такая маска отбирает права на запись у группы и остальных.
Системный вызов umask(mask) устанавливает новую маску и возвращает старую.
Для удобства записи прав доступа существуют мнемонические макросы:
S_IRWXU 00700 User Read, Write,eXecute; S_IRUSR 00400 User Read; S_IWUSR 00200 User Write и т.д. S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH.
flags — флаги уточняющие режим открытия файла. Флаги делятся на несколько групп:
- режим доступа: O_RDONLY, O_WRONLY, O_RDWR, O_WRONLY+O_APPEND(чтение,запись, чтение+запись, запись всегда в конец файла);
- режим создания — O_CREAT, O_CREAT+O_EXCL, O_TRUNC (создавать файл, создавать только если не существует, обрезать существующий до нулевой длины);
- прочие O_NOFOLLOW, O_CLOEXEC, O_NOCTTY (не открывать символические ссылки, закрывать при вызове exec, не рассматривать открытый файл как управляющий терминал CTTY=Control TeleTYpe).
При ошибке открытия файла возвращается -1 и в переменную errno заносится код ошибки. Возможные значения ошибки (не все):
- EACCES — нет прав на сам файл или на поиск в каталоге в котором он находится;
- ENOENT — файл не существует и не указан флаг O_CREAT;
- EEXIST — файл существует и указаны флаги O_CREAT+O_EXCL;
- EFAULT — плохой указатель на имя файла (например NULL);
- EISDIR — попытка открыть каталог;
- ELOOP — символические ссылки создали кольцо в структуре каталогов.
Чтение/запись файла
Чтение и запись возвращают количество прочитанных/записанных байтов или -1. -1 не всегда означает ошибку.
Возможные варианты ответа при записи:
- число от 0 до count — число реально записанных байтов;
- -1 — ошибка. Если errno при ошибке выставлено в EAGAIN, EWOULDBLOCK или EINTR , то операцию можно повторить см. ниже.
Возможные варианты ответа при чтении:
- число от 1 до count — число реально записанных байтов;
- 0 — признак конца файла
- -1 — ошибка. Если errno при ошибке выставлено в EAGAIN, EWOULDBLOCK или EINTR , то операцию можно повторить см. ниже.
- EAGAIN или EWOULDBLOCK (только для сокетов) — не удалось провести неблокирующее чтение/запись для файла (сокета), открытого в режиме O_NONBLOCK;
- EINTR — операция чтения/записи была прервана доставкой сигнала до того, как удалось прочитать/записать хотя бы один байт;
- EBADF — плохой дескриптор файла (файл закрыт);
- EINVAL — неверный режим доступа к файлу (чтение вместо записи или наоборот);
- EFAULT — неверный указатель на буфер (например NULL).
Чтение/запись сложных объектов за один системный вызов
Чтение/запись из/в фрагментированной памяти
Чтение/запись в определенную позицию. offset — смещение в байтах относительно начала файла.
Закрытие файла
Ошибки при закрытии файла встречаются редко, но встречаются.
- EBADF — попытка закрыть файловый дескриптор, не связанный с открытым файлом;
- EINTR — операция прервана доставкой сигнала. Может встретиться на медленных (например сетевых) ФС;
- EIO — ошибка нижележащей системы ввода/вывода. Например обрыв соединения с файловым сервером.
Установка смещения в файле
Для установки позиции/чтения записи в файле используются два параметра offset — смещение в байтах и whence — место от которого отсчитывается смещение. Возможные значения whence:
- SEEK_SET — от начала файла;
- SEEK_CUR — от текущей позиции;
- SEEK_END — от конца файла.
Возвращается установленная позиция или -1 в случае ошибки.
Сочетание offset=0 и whence=SEEK_CUR позволяет узнать текущую позицию чтения/записи.
С помощью lseek возможно перемещение указателя записи за конец файла. Многие ФС в такой ситуации не выделяют блоки хранения под пропущенные байты и создают «дырявые» файлы, занимающие на диске пространство меньше своей длины.
В данном примере создаётся файл длиной примерно 1 ГБ, занимающий на диске один блок данных (например 512 Б).
В 32-х разрядных системах могут быть проблемы с большими файлами. В этом случае надо использовать вызов lseek64 и некоторые дополнительные трюки.
Манипулирование файловыми дескрипторами
Возможно создание ссылки на файловый дескриптор.
dup() — выбирает в таблице открытых файлов первую свободную строку и записывает ссылку на oldfd в неё, dup2() — закрывает файл, связанный с дескриптором newfd (если он был открыт) и записывает ссылку oldfd в newfd. В случае успеха возвращается файловый дескриптор, в случае ошибки -1.
В связи с тем, что в таблицу открытых файлов вписывается именно ссылка, у файловых дескрипторов oldfd и newfd всегда будет одна и та же позиция головки чтения/записи.
Типичное применение dup2() — это подмена стандартных дескрипторов 0,1,2 (stdin,stdout,stderr). oldfd в этом случае закрывается после создания ссылки. dup2() предпочтительнее чем dup(), т.к. выполняется атомарно, что может быть важно в многопоточной среде.
File Operations, Open, Write, and Close Files In C
While learning C programming language one of the most exciting parts is writing and reading a file. Because these operations create something on the operating system we can see which is different from other examples. In this tutorial, we will look at different aspects of file operations.
stdio.h Library
As we know C provides different types of features with libraries. Input and output related features are provided by the library named stdio.h. In order to run related file operations, we should include this library as below. We generally put include like to the start of the code file like below.
Opening File
The first step to work with a file is opening it. Files can be opened by using fopen function. fopen function generally gets the filename and mode parameters.
fopen function returns a handler back where we use FILE type variable for this.
Below we will create a file pointer named fp and open file named test.txt with w+ write and read mode.
Closing File
In the previous part, we have opened a file with fopen function. But the code provided there is not an efficient code because the file handler does not closed which means the file is not closed. Not closing a file can create a performance or write problems. So after our operation is completed we should close the file with fclose function.
and complete code will be like below.
Reading File
One of the fundamental steps for file operation is reading a file. There are different ways and modes to read a file but in this step, we simply read a line. We will put this in a while loop and read it to the end of the file. Because we will read file so we will use read mode while opening the file with fopen function. We will provide the variable, str , we want to put the grabbed string and the size to read which is 80 and the last one is the file pointer fp
And here fully working code where we use while to read line by line to the end of the file. If the end of the file arrived the NULL value will be returned.
Writing File
In previous steps, we have learned how to open and close files. But the ultimate goal is not opening and closing files. We generally read or write to file. There are different ways to write a file but in this tutorial, we will simply put some line to the file. We will use fputs function by providing the string and file pointer like below.
We can see the whole working example below.