По какой-то причине очень часто люди думают, что создание неблокирующего fd или вызов poll/select/.. имеет другое поведение для файлов по сравнению с другими типами описаний файлов, но неблокирующее поведение и поведение готовности к вводу/выводу по сути, то же самое для всех типов описаний файлов: ядро немедленно вернется из чтения/записи и т. д., если результат известен, и в этом случае будет сигнализировать о готовности ввода-вывода. Когда сокет имеет условие EOF, select будет сигнализировать о том, что сокет готов к чтению, и вы получите 0 (для EOF). То же самое происходит с файлами — если вы находитесь в конце файла, ядро немедленно вернется из чтения и вернет 0, чтобы сигнализировать EOF.
Важным отличием является то, что файлы могут изменять содержимое в случайных местах и могут быть расширены. Каналы и сокеты не являются произвольным доступом и не могут быть добавлены после закрытия. Таким образом, несмотря на то, что поведение является последовательным, часто это не то, что требуется, а именно ожидание изменения файла каким-либо образом.
Конфликт в умах многих людей заключается просто в том, что они хотят, чтобы им сообщали «когда появятся новые данные», но если вы немного подумаете об этом, вы поймете, что простое пробуждение не будет адекватным интерфейсом для этого, поскольку вы у вас нет возможности узнать, почему вы проснулись и что изменилось.
POSIX не имеет интерфейса для этого, кроме регулярного опроса fd или файла (и в случае случайных изменений, регулярного чтения всего файла!). Некоторые операционные системы имеют интерфейс для выполнения чего-то подобного (kqueue в BSD, inotify в GNU/Linux), но они также не идеально подходят друг другу (например, inotify не может просматривать fd). для изменений он будет отслеживать путь для изменений).
Самое близкое, что вы можете сделать с libev, это использовать ev_stat
наблюдателя. Он ведет себя так, как если бы вы регулярно stat()
устанавливали путь и вызывали обратный вызов наблюдателя при каждом изменении данных статистики. При переносе он делает именно это: он регулярно вызывает stat
, но в некоторых операционных системах (в настоящее время только inotify в GNU/Linux, так как kqueue не имеет правильной семантики для этого) он может использовать другие механизмы для ускорения этого в некоторых случаях, хотя он будет возвращаться к обычному stat
опросу везде, например, когда файл находится в сетевой файловой системе, где inotify не может видеть удаленные изменения.
Чтобы ответить на ваш вопрос: если у вас есть путь, вы можете использовать наблюдателя ev_stat
для отслеживания изменений статистических данных, таких как изменения размера / mtime и т. д. Сделать это правильно может быть немного сложно (см. документацию libev, особенно часть о разрешении времени статистики: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_stat_code_did_the_file_attri), и вы должны помните, что при этом отслеживается путь, а не файловый дескриптор, поэтому вам может потребоваться регулярно сравнивать устройство/инод вашего файлового дескриптора и отслеживаемый путь, чтобы убедиться, что вы все еще открыть нужный файл.
Это по-прежнему не говорит вам, какая часть файла изменилась.
В качестве альтернативы, поскольку вы, по-видимому, хотите только читать добавленные данные, вы можете просто регулярно read()
файл (в обратном вызове ev_timer
) и избавиться от всех сложностей и проблем настройки ev_stat
наблюдателя (не забывая также сравнить путь stat с вашими статданными fd, чтобы увидеть, открыт ли у вас еще нужный файл, в зависимости от того, может ли файл, который вы читаете, быть переименован или заменен.Иногда программы также обрезают файлы, что вы также можете обнаружить, увидев уменьшение размера между stat звонки).
По сути, это то, что делают старые реализации tail -f
, в то время как новые могут, например, получать подсказки (только) от inotify, как это делают ev_stat
наблюдатели.
Все это непросто, и детали зависят от ваших знаний о том, как именно изменяется файл, но это лучшее, что вы можете сделать.
person
Remember Monica
schedule
25.07.2018
inotify
для мониторинга файла на наличие изменений, прежде чем выдавать другое чтение. - person jxh   schedule 26.07.2018