Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > [kernel] printk и va_start


Автор: cupper 23.2.2010, 23:54
Пытаюсь разобраться с тем как работает printk, в целом все понятно за исключением двух моментов:
Код

asmlinkage int printk(const char *fmt, ...) 
{ 
   va_list args; 
   int r; 
 
   va_start(args, fmt); 
   r = vprintk(fmt, args); 
   va_end(args); 
 
   return r; 
} 

как работают макросы va_start va_end va_arg
Код

typedef char *va_list;
#endif                /* _VALIST */

/*
 * Storage alignment properties
 */
#define  _AUPBND                (sizeof (acpi_native_int) - 1)
#define  _ADNBND                (sizeof (acpi_native_int) - 1)

/*
 * Variable argument list macro definitions
 */
#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)              (void) 0
#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

немогу понять как это работает. 
После вызова макроса 
va_start(args, fmt);
args на что указывает ? на кусок памяти в котором расположены последовательно переменные которые передавались printk в качестве ... или что ? А в fmt ?

2. 
Код

printk(KERN_ERR "bla bla bla\n"); 

как так передается не строка и строка как одно целое ?из анализа кода чета не понял как они распарсиваются ((

Автор: 586 24.2.2010, 01:17
Цитата(cupper @  23.2.2010,  23:54 Найти цитируемый пост)
немогу понять как это работает. 
После вызова макроса 
va_start(args, fmt);
args на что указывает ?

указывает на ((&fmt)+1)

Цитата(cupper @  23.2.2010,  23:54 Найти цитируемый пост)
printk(KERN_ERR "bla bla bla\n"); 

Это конкатенация строк:
Код
const char *s = "blablabla" "blablabla" "blablabla";

То есть, в функцию printk передаётся один аргумент.

Автор: MAKCim 24.2.2010, 11:13
cupper, 
непонятно, что может быть непонятного ;)
у вас же все определения есть
пошагово посмотрите, что происходит

Автор: cupper 24.2.2010, 12:15
ну например непонятно что произойдет если в printk будут переданы параметры одного типа, а изыматься будут с другими типами (форматная строка другая)  (положили 4 long сняли 4 char) таким образом в стеке остались часть данных и если не вызвать va_end то что произойдет ? получается можно изменить стек под свои "не хорошие" нужды ?

Автор: 586 24.2.2010, 17:29
Цитата(cupper @  24.2.2010,  12:15 Найти цитируемый пост)
положили 4 long сняли 4 char

Не "сняли" а "прочли".
va_end не влияет на освобождение параметров в стеке. 
va_end используется совместно с va_start. Если вызвали va_start, то нужно вызвать и va_end.
Цитата
ну например непонятно что произойдет если в printk будут переданы параметры одного типа, а изыматься будут с другими типами

Может произойти ошибка. А может ничего не произойти. Подобные функции считаются опасными.
В этом примере произойдёт Segmentation Fault:
Код
printk("%s", 2);

Автор: cupper 24.2.2010, 18:43
[QUOTE=586,24.2.2010,  17:29]
Цитата(cupper @  24.2.2010,  12:15 Найти цитируемый пост)

va_end используется совместно с va_start. Если вызвали va_start, то нужно вызвать и va_end.

ну а что будет если не вызвать va_end, тобишь не выровнять стек ? что то неопределенное ? 

Автор: MAKCim 24.2.2010, 22:47
cupper, 
ну неужели из дефайнов не видно? ;)
Цитата

(void) 0

ничего не будет

Автор: cupper 25.2.2010, 23:49
Цитата(MAKCim @ 24.2.2010,  22:47)
cupper, 
ну неужели из дефайнов не видно? ;)
Цитата

(void) 0

ничего не будет

этото видно, получает если каким либо образом в ворфматной строке задать одни параметры и передать другие типы то можно чтто оставить в стеке (в теории), как уже многими было сказано небезопастная конструкция. Но также везде пишется что нужно юзать va_end после va_start (хотя это пишут для пользовательких функий а не ядровых) И если ядровые va_end ничего неделают смысл тогда их в чем ? нахрена их писать ?)

Автор: MAKCim 26.2.2010, 09:55
Цитата(cupper @  25.2.2010,  23:49 Найти цитируемый пост)
И если ядровые va_end ничего неделают смысл тогда их в чем ? нахрена их писать ?) 

va_start/va_end/va_arg в оригинале являются частью стандартной библиотеки С
ядро в этом смысле ее эмулирует
точно не знаю, но даю процентов 95, что va_end в С также ничего не делает ;)


Цитата(cupper @  25.2.2010,  23:49 Найти цитируемый пост)
этото видно, получает если каким либо образом в ворфматной строке задать одни параметры и передать другие типы то можно чтто оставить в стеке (в теории), как уже многими было сказано небезопастная конструкция

стек растет в сторону меньших адресов, поэтому если мы передали значения типов больших размеров, то ничего небезопасного тут нет, но это, безусловно, ошибка

Автор: cupper 26.2.2010, 13:15
[QUOTE=MAKCim,26.2.2010,  09:55]
Цитата(cupper @  25.2.2010,  23:49 Найти цитируемый пост)

точно не знаю, но даю процентов 95, что va_end в С также ничего не делает ;)

хм, я когда читал про С функции va_start  то там было обязательным условием вызов va_end для того чтобы 100% выровнять стек и избежать проблем проблем.

Автор: MAKCim 26.2.2010, 13:37
я про то, что в 95% случаев реализация va_X вообще ничего не делает со стеком, поэтому ничего выравнивать не надо ;)
но семантика использования va_X _требует_ вызова va_end в конце, поскольку таков интерфейс использования данной функциональности

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)