#c #linux #file-descriptor
#c #linux #файловый дескриптор
Вопрос:
Один файл размером 2 ГБ передается с сервера на клиент. На стороне клиента, после получения 512 МБ этого файла, я открываю его с помощью:
FILE *fp= fopen("that file","r");
Теперь, после завершения загрузки, могу ли я получить доступ ко всем данным этого файла объемом 2 ГБ с помощью этого файлового дескриптора? Или мне нужно повторно открыть его, чтобы получить доступ ко всему файлу?
Комментарии:
1. Почему вы хотите открыть файл до его полной загрузки?
2. @JoachimPileborg я просто думаю, идет ли потоковая передача файла, и я хочу воспроизвести его во время этого ?!!
Ответ №1:
Во-первых, вам следует избегать пробелов в именах файлов Linux. Таким образом, ваш пример должен FILE *fp= fopen("that_file","r");
содержать пробелы (или даже управляющие символы, такие как перевод строки) в именах файлов — плохой вкус.
А в Linux файловый дескриптор (который не является FILE*
дескриптором!) Представляет собой небольшое целое число, которое обрабатывается ядром: внутри ядра процессы имеют таблицу открытых файлов, и их код приложения ссылается (используя системные вызовы, такие как open
и read
и т.д.) На эти файлы по их файловому дескриптору. Стандартная библиотека C управляет буферизацией и файловыми дескрипторами (поэтому внутри структуры FILE
данных есть буферы и файловый дескриптор).
Итак, если у вас есть один процесс, который читает файл, а другой одновременно записывает его (это плохая практика), процесс чтения может считывать все доступные байты.
Итак, вам не нужно «обновлять» ваш fp
, но ваш код дерьмовый (из-за отсутствия синхронизации между процессом чтения и записи).
Комментарии:
1. 1> спасибо, что сказал о пробелах 2> что, если я открою этот файл с помощью open(), тогда мне нужно обновить fp?
2. Нет (но, возможно, вызов fsync может помочь, но я считаю, что вам это не нужно). Тем не менее, я настаиваю на том, что это плохая практика , поскольку у вас должен быть какой-то способ синхронизации процессов записи и чтения
3. @Mr .32: здесь нет разницы между
open
иfopen
. В этомfsync
тоже нет необходимости.4. Существует огромная разница между
open
amp;fopen
:open
является системным вызовом (и вы должны буферизировать данные, чтобы избежать вызоваwrite
слишком маленьких фрагментов данных), возвращающим целочисленный файловый дескриптор.fopen
это стандартная функция библиотеки C, возвращающаяFILE*
указатель. Вы будете использоватьfprintf
илиfwrite
для записи туда, и он буферизует для вас. См. Такжеfflush
.5. @BasileStarynkevitch Если быть точным, большинство современных операционных систем в некоторой степени будут выполнять буферизацию чтения / записи для вас. Контроллеры диска также будут выполнять некоторую буферизацию. Таким образом, хотя хорошей практикой является выполнение некоторого объема буферизации, это строго не требуется.
Ответ №2:
Нет необходимости повторно открывать файл; если вы периодически запрашиваете размер файла в клиенте, вы увидите, что он увеличивается. Обратите внимание, что файл не увеличивается до тех пор, пока процесс записи не очистит его буферы.
( FILE*
Кстати, A не является файловым дескриптором.)
Комментарии:
1. возможно, потребуется fsync (особенно с реализациями на основе fuse, которым разрешено локально кэшировать статистическую информацию IIRC)
Ответ №3:
Файловый дескриптор должен быть обновлен для доступа ко всему файлу. Обычно при открытии файла текущее содержимое файла загружается в память, и оно будет обновлено файловым дескриптором, и любое обновление внешнего файла не будет обновляться в загруженной памяти.
Комментарии:
1. Это полная бессмыслица. Открытие файла не загрузит его в память.
2.
The fopen() function shall open the file whose pathname is the string pointed to by filename, and associates a stream with it.