Что именно расширяет KERN_INFO и где это реализовано? - PullRequest
1 голос
/ 07 января 2020

В этом вопросе: Почему функция printk () не использует запятую для разделения параметров? , кто-то сказал, KERN_INFO расширяется до ""\001" "6". Я знаю, что первый \0 является нулевым символом, но тогда что же такое 01? Как я полагаю, чтобы быть одним в восьмеричном. Когда препроцессор объединяет его вместе до "\0016", остаток после нуля равен 016, что составляет 14 в десятичном виде. Итак, я посмотрел в ascii и нашел его как 0E SO (shift out)? Это не имеет смысла для меня, и это должно иметь какое-то отношение к ведению журнала (так как это цель printk). Так в чем же смысл макропоследовательностей KERN_INFO после раскрытия?

Кроме того, я попытался посмотреть в источнике, в /usr/include/linux/kernel.h, но не нашел там макрос. Так это в kernel.h или где-то еще?

1 Ответ

2 голосов
/ 07 января 2020

"\001" "6" - это два строковых литерала, которые будут объединены (с любыми другими смежными строковыми литералами) в один строковый литерал. (Конкатенация выполняется на фазе перевода 6 , как определено в стандарте C.)

Первый из этих строковых литералов, "\001" содержит одну восьмеричную последовательность , определяющий один символ. Восьмеричная escape-последовательность в строковом литерале или символьной константе состоит из обратного знака sh (\), за которым следуют от 1 до 3 восьмеричных цифр (001 в данном случае). В этом случае отдельный символ имеет цифру c код 1, что соответствует символу ASCII SOH (начало заголовка).

Строковый литерал "\0016" содержит последовательности для двух символов '\001' и '6', поскольку восьмеричная escape-последовательность всегда заканчивается не более чем 3 восьмеричными цифрами.

Escape-последовательности не пересекают границу между соседними строковыми литералами. (Последовательности Escape расширяются на этапе 3 трансляции, поэтому они уже раскрываются перед объединением смежных строковых литералов на этапе 6 трансляции). Следовательно, пара строковых литералов "\1" "6" эквивалентна (после конкатенации) единственному строковому литералу "\0016", а не "\16".

Как указано @ Peter L. , макрос KERN_INFO и другие макросы «уровня ядра» определены в «include / linux / kern_levels.h» в исходном коде ядра Linux. На самом деле, это так с версии ядра 3.6. До версии ядра 3.6 они были определены в «include / linux / printk.h» и использовали другой формат строки с номером уровня ядра, указанным в угловых скобках (например, KERN_INFO раньше определялось как "<6>").

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

...