Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра Linux
Назад Отладка в ядре Вперед

Комплементарный отладочный модуль

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

  • проектируемый модуль теперь не выносит критические переменные в качестве органов диагностики в файловые системы, а только объявляет их экспортируемыми:
  • комплементарный отладочный модуль динамически устанавливает связь с этими переменными (импортирует) при своей загрузке...
  • и создаёт для них интерфейсы в свя:диагностическим и управляющим переменным;
  • после завершения отладки отладочный модуль просто изымается из проекта.

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

Файл общих определений:

mdsys2.h :

	#include <linux/module.h> 
	#include <linux/pci.h> 
	#include <linux/interrupt.h>
	#include <linux/version.h> 
	
	extern unsigned int irq_counter; 
	int __init init( void ); 
	void __exit cleanup( void ); 
	module_init( init ); 
	module_exit( cleanup ); 
	MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" ); 
	MODULE_DESCRIPTION( "module in debug" ); 
	MODULE_LICENSE( "GPL v2" ); 

Собственно проектируемый (отлаживаемый) модуль:

mdsys2.с :

	#include "mdsys2.h" 
	
	#define SHARED_IRQ 16               // my eth0 interrupt 
	static int irq = SHARED_IRQ; 
	module_param( irq, int, S_IRUGO );  // may be change 
	
	unsigned int irq_counter = 0; 
	EXPORT_SYMBOL( irq_counter ); 
	static irqreturn_t mdsys_interrupt( int irq, void *dev_id ) { 
	   irq_counter++; 
	   return IRQ_NONE; 
	} 
	
	static int my_dev_id; 
	int __init init( void ) { 
	   if( request_irq( irq, mdsys_interrupt, IRQF_SHARED, "my_interrupt", &my_dev_id ) ) 
	      return -1; 
	   else 
	      return 0; 
	} 
	
	void cleanup( void ) { 
	   synchronize_irq( irq ); 
	   free_irq( irq, &my_dev_id ); 
	   return; 
	} 

И модуль, создающий для него отладочный интерфейс:

mdsysс.h :

	#include "mdsys2.h" 
	
	#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) 
	static ssize_t show( struct class *class, struct class_attribute *attr, char *buf ) { 
	#else 
	static ssize_t show( struct class *class, char *buf ) { 
	#endif 
	   sprintf( buf, "%d\n", irq_counter ); 
	   return strlen( buf ); 
	} 
	
	#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) 
	static ssize_t store( struct class *class, struct class_attribute *attr, const char *buf, size_t c 
	#else 
	static ssize_t store( struct class *class, const char *buf, size_t count ) { 
	#endif 
	   int i, res = 0; 
	   const char dig[] = "0123456789"; 
	   for( i = 0; i < count; i++ ) { 
	      char *p = strchr( dig, (int)buf[ i ] ); 
	      if( NULL == p ) break; 
	      res = res * 10 + ( p - dig ); 
	   } 
	   irq_counter = res; 
	   return count; 
	} 
	
	CLASS_ATTR( mds, 0666, &show, &store ); // => struct class_attribute class_attr_mds 
	static struct class *mds_class; 
	
	int __init init( void ) { 
	   int res = 0; 
	   mds_class = class_create( THIS_MODULE, "mds-class" ); 
	   if( IS_ERR( mds_class ) ) printk( KERN_ERR "bad class create\n" ); 
	   res = class_create_file( mds_class, &class_attr_mds ); 
	   if( res != 0 ) printk( KERN_ERR "bad class create file\n" ); 
	   return res; 
	} 
	
	void cleanup( void ) { 
	   class_remove_file( mds_class, &class_attr_mds ); 
	   class_destroy( mds_class ); 
	   return; 
	} 

Теперь отладочный модуль не знает ничего ни о прерываниях, ни о структуре отлаживаемого модуля — он знает только ограниченный набор экспортируемых переменных (или, как вариант, экспортируемых точек входа), по именам и по типам. Опробуем то, что у нас получилось, и сравним с примером предыдущего раздела:

$ sudo insmod mdsys2.ko

$ sudo insmod mdsysc.ko

$ lsmod | head -n3

	Module                  Size  Used by 
	mdsysc                   934  0 
	mdsys2                   844  1 mdsysc 

$ cat /sys/class/mds-class/mds

	784 

$ cat /sys/class/mds-class/mds

825

$ echo 0 > /sys/class/mds-class/mds

$ cat /sys/class/mds-class/mds

21

Теперь мы удалим отладочный модуль:

$ sudo rmmod mdsysc

Отлаживаемый модуль замечательно продолжает работать, но отладочные интерфейсы к нему исчезли:

$ lsmod | head -n3

	Module                  Size  Used by 
	mdsys2                   844  0 
	lp                      6794  0 

$ cat /sys/class/mds-class/mds

cat: /sys/class/mds-class/mds: Нет такого файла или каталога

$ sudo rmmod mdsys2


Предыдущий раздел: Оглавление Следующий раздел:
Интерфейсы пространства пользователя к модулю   Некоторые мелкие советы в завершение