Безопасно ли анализировать файл/ proc/?



Я хочу парсить /proc/net/tcp/, но это безопасно?



Как я должен открывать и читать файлы из /proc/ и не бойтесь, что какой-то другой процесс (или сама ОС) будет менять его в то же время?

515   7  

7 ответов:

в общем, нет. (так что большинство ответов здесь неверны.) Это может будьте в безопасности, в зависимости от того, какое свойство вы хотите. Но это легко в конечном итоге с ошибками в коде, если вы предполагаете слишком много о согласованности файла в /proc. Например, см. эта ошибка, которая возникла из предположения, что /proc/mounts был последовательный снимок.

например:

  • /proc/uptime is совершенно атомным, как кто-то упомянул в другом ответе-но только с Linux 2.6.30, которому меньше двух лет. Так что даже этот крошечный, тривиальный файл был подвержен состоянию гонки до тех пор, и все еще находится в большинстве ядер предприятия. Смотрите fs/proc/uptime.c для текущего источника, или фиксация, которая сделала его атомарным. На ядре pre-2.6.30 вы можете open файл read немного, то если вы позже вернетесь и read опять же, часть, которую вы получите, будет несовместима с первой частью. (Я только что продемонстрировал это-попробуйте сами для удовольствия.)

  • /proc/mounts и атомарный в пределах одного read системный вызов. если вы read весь файл сразу, вы получаете один последовательный снимок точек монтирования в системе. Однако, если вы используете несколько read системные вызовы -- и если файл большой, это именно то, что произойдет, если вы используете обычный Библиотеки ввода/вывода и не обращайте особого внимания на эту проблему-вы будете подвержены состоянию гонки. Вы не только не получите согласованный снимок, но и точки монтирования, которые присутствовали до того, как вы начали и никогда не прекращали присутствовать, могут отсутствовать в том, что вы видите. Чтобы увидеть, что это атомарный для одного read() посмотри m_start() на fs/namespace.c и смотрите, как он захватывает семафор, который охраняет список точек монтирования, который он держит до m_stop(), который называется, когда read() выполняемый. Чтобы увидеть, что может пойти не так, см. эта ошибка с прошлого года (тот же самый, который я связал выше) в другом высококачественном программном обеспечении, которое беспечно читает /proc/mounts.

  • /proc/net/tcp, о котором вы на самом деле спрашиваете, еще менее последователен, чем это. Это атомные только в каждой строке таблицы. Чтобы увидеть это, посмотрите на listening_get_next() на net/ipv4/tcp_ipv4.c и established_get_next() чуть ниже в этом же файле и посмотреть замки они вынимают на каждом входе по очереди. У меня нет кода repro, удобного для демонстрации отсутствия согласованности от строки к строке, но там нет блокировок (или чего-либо еще), которые сделали бы его последовательным. Что имеет смысл, если вы подумаете об этом-сеть часто является супер-занятой частью системы, поэтому не стоит накладных расходов, чтобы представить последовательное представление в этом диагностическом инструменте.

другой кусок, который держит /proc/net/tcp атомарный внутри каждой строки является буферизация в seq_read(), который вы можете прочитать на fs/seq_file.c. Это гарантирует, что как только вы read() часть одной строки, текст всей строки хранится в буфере, так что следующий read() получит остальную часть этой строки перед началом нового. Тот же механизм используется в /proc/mounts чтобы сохранить каждую строку атомарной, даже если вы делаете несколько read() звонки, и это также механизм, который /proc/uptime в новых ядрах используется, чтобы оставаться атомарным. Этот механизм делает не буфера весь файл, потому что ядро осторожно относится к использованию памяти.

большинство файлов в /proc будет по крайней мере так же последовательно, как /proc/net/tcp, С каждой строкой последовательное изображение одной записи в любой информации, которую они предоставляют, потому что большинство из них используют то же самое seq_file абстракция. Как то /proc/uptime пример иллюстрирует, однако, некоторые файлы все еще были перенесены для использования seq_file еще в 2009 году; я уверен, что есть еще некоторые, которые используют старые механизмы и даже не имеют этого уровень атомарности. Эти предостережения редко документируются. Для данного файла ваша единственная гарантия-прочитать источник.

в случае /proc/net/tcp, вы можете прочитать его и парсить каждую строку без страха. Но если вы попытаетесь сделать какие-либо выводы из нескольких строк сразу-будьте осторожны, другие процессы и ядро are изменение его во время чтения, и вы, вероятно, создаете ошибку.

хотя файлы /proc появляются как обычные файлы в пользовательском пространстве, они на самом деле не файлы, а скорее сущности, которые поддерживают стандартные операции с файлами из пользовательского пространства (open,read,close). обратите внимание, что это сильно отличается от обычного файла на диске, который изменяется ядром.

все, что делает ядро, это печатает свое внутреннее состояние в свою собственную память с помощью sprintf - как функция, и эта память копируется в пользовательское пространство всякий раз, когда вы выпускаете read(2) системный вызов.

ядро обрабатывает эти вызовы совершенно иначе, чем для обычных файлов, что может означать, что весь снимок данных, которые вы будете читать, может быть готов в то время, когда вы open(2) это, в то время как ядро гарантирует, что параллельные вызовы являются последовательными и атомарными. Я нигде этого не читал, но это действительно не имеет смысла быть иначе.

мой совет-взглянуть на реализацию файла proc в вашем конкретном вкусе Unix. Это действительно проблема реализации (как и формат и содержание вывода), которая не регулируется стандартом.

самым простым примером может быть реализация uptime proc файл в Linux. Обратите внимание, как весь буфер создается в функции обратного вызова, поставляемой в single_open.

/proc-это виртуальная файловая система : на самом деле, он просто дает удобный вид внутренностей ядра. Это определенно безопасно читать его (вот почему он здесь), но это рискованно в долгосрочной перспективе, так как внутренние из этих виртуальных файлов могут развиваться с более новой версией ядра.

EDIT

дополнительная информация доступна в документация proc в ядре Linux doc глава 1.4 сетей Я не могу найти если информация, как информация меняться со временем. Я думал, что он был заморожен на открытом, но не может иметь определенного ответа.

EDIT2

по данным Sco doc (не linux, но я уверен, что все ароматы *nix ведут себя так)

хотя состояние процесса и следовательно, содержание /proc файлы могут меняться от мгновенного до мгновенное, одно чтение(2) a /proc файл гарантированно вернуть `вменяемый" представительства государств, которые есть, чтение будет атомарным снимок состояния процесса. Такая гарантия не распространяется на последовательные чтения, применяемые к a /proc файл для запущенного процесса. В кроме того, атомарность является специфически не гарантируется для любого ввода / вывода, примененного к файл as (адресное пространство); содержание адреса любого процесса пространство может быть одновременно изменено с помощью LWP этого процесса или любого другого процесс в системе.

API procfs в ядре Linux предоставляет интерфейс, чтобы убедиться, что чтение возвращает согласованные данные. Читайте комментарии в __proc_file_read. Пункт 1) в большом блоке комментариев объясняет этот интерфейс.

это, как говорится, это, конечно, до реализации конкретного файла proc, чтобы правильно использовать этот интерфейс, чтобы убедиться, что его возвращаемые данные непротиворечивы. Итак, чтобы ответить на ваш вопрос: нет, ядро не гарантирует согласованность файлов proc во время чтение, но оно предоставляет средства для реализации этих файлов для обеспечения согласованности.

у меня есть источник для Linux 2.6.27.8 удобный, так как я занимаюсь разработкой драйверов в данный момент на встроенной цели ARM.

файл ...linux-2.6.27.8-lpc32xx/net/ipv4/raw.c в строке 934 содержится, например

    seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
            " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",
            i, src, srcp, dest, destp, sp->sk_state,
            atomic_read(&sp->sk_wmem_alloc),
            atomic_read(&sp->sk_rmem_alloc),
            0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
            atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));

выходы

[wally@zenetfedora ~]$ cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 15160 1 f552de00 299
   1: 00000000:C775 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13237 1 f552ca00 299
...

функции raw_sock_seq_show() который является частью иерархии procfs функции обработки. Текст не генерируется до тех пор, пока read() запрос из /proc/net/tcp файл, разумный механизм с тех пор procfs чтения, безусловно, гораздо менее распространены, чем обновление информации.

некоторые драйверы (например, мой) реализуют функцию proc_read с помощью одного sprintf(). Дополнительная сложность в реализации основных драйверов заключается в обработке потенциально очень длинного вывода, который может не поместиться в промежуточный буфер пространства ядра во время одного чтения.

Я проверил это с помощью программы, использующей буфер чтения 64K, но это приводит к буферу пространства ядра 3072 байта в моей системе для proc_read, чтобы вернуть данные. Несколько вызовов с опережающими указателями необходимы, чтобы получить больше, чем столько текста возвращается. Я не знаю, как правильно сделать возвращенные данные согласованными, когда требуется более одного ввода-вывода. Конечно, каждая запись в /proc/net/tcp самосогласованности. Существует некоторая вероятность того, что линии бок о бок снимаются в разное время.

за исключением неизвестных ошибок, нет никаких условий гонки в /proc это приведет к чтению поврежденных данных или смеси старых и новых данных. В этом смысле, это безопасно. Однако есть еще состояние гонки, что большая часть данных, которые Вы читаете из /proc потенциально-устаревший, как только он генерируется, и даже более того, к тому времени, когда вы доберетесь до его чтения/обработки. Например, процессы могут умереть в любое время, и новому процессу может быть назначен тот же pid; единственные идентификаторы процессов, которые вы можете когда-либо использование без условий расы - это ваши собственные дочерние процессы". То же самое касается сетевой информации (открытые порты и т. д.) и действительно большая часть информации в /proc. Я бы счел это плохой и опасной практикой полагаться на любые данные в /proc быть точным, за исключением данных о вашем собственном процессе и потенциально его дочерних процессах. Конечно, все еще может быть полезно представить другую информацию от /proc пользователю / администратору для получения информации / ведения журнала / и т. д. цели.

когда вы читаете из файла /proc, ядро вызывает функцию, которая была зарегистрирована заранее, чтобы быть функцией" read " для этого файла proc. Смотрите __proc_file_read функция в fs / proc/generic.с.

таким образом, безопасность чтения proc так же безопасна, как и функция, которую ядро вызывает для удовлетворения запроса на чтение. Если эта функция правильно блокирует все данные, к которым она прикасается, и возвращает их вам в буфер, то это абсолютно безопасно для чтения с помощью этой функции. Поскольку прок файлы, такие как тот, который используется для удовлетворения запросов на чтение /proc/net/tcp, были вокруг некоторое время и подверглись скрупулезному обзору, они примерно так же безопасны, как вы могли бы попросить. На самом деле, многие распространенные утилиты Linux полагаются на чтение из файловой системы proc и форматирование вывода по-другому. (С моей головы, я думаю, что " ps " и "netstat" делают это).

этот документ описывает интерфейсы в /proc/сеть/TCP и /труды/нетто/tcp6.
Обратите внимание, что эти интерфейсы устарел в пользу tcp_diag. Эти интерфейсы /proc предоставляют информацию о текущем активном TCP соединения, и реализованы с помощью tcp4_seq_show () в net/ipv4/tcp_ipv4.с и tcp6_seq_show() в net / ipv6 / tcp_ipv6.c, соответственно.

Comments

    Ничего не найдено.