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

UnixForum





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

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

Счётчик ссылок использования модуля

Вернёмся ещё раз к вопросу счётчика ссылок использования модуля, и, на примере только что спроектированного модуля, внесём для себя окончательную ясность в вопрос. Но для этого изготовим ещё одну элементарную тестовую программу (пользовательский процесс):

simple.c :

	#include <fcntl.h> 
	#include <stdio.h> 
	#include <stdlib.h> 
	#include <string.h> 
	#include "mopen.h" 

	int main( int argc, char *argv[] ) { 
	   char dev[ 80 ] = "/dev/";
	   strcat( dev, DEVNAM ); 
	   int df; 
	   if( ( df = open( dev, O_RDWR ) ) < 0 ) 
	      printf( "open device error: %m" ), exit( EXIT_FAILURE ); 
	   char msg[ 160 ]; 
	   fprintf( stdout, "> " ); 
	   fflush( stdout ); 
	   gets( msg ); // gets() - опасная функция! 
	   int res, len = strlen( msg ); 
	   if( ( res = write( df, msg, len ) ) != len ) 
	      printf( "write device error: %m" ); 
	   char *p = msg; 
	   do { 
	      if( ( res = read( df, p, sizeof( msg ) ) ) > 0 ) { 
	         *( p + res ) = '\0'; 
	         printf( "read %d bytes: %s", res, p ); 
	         p += res; 
	      } 
	      else if( res < 0 ) 
	         printf( "read device error: %m" ); 
	   } while ( res > 0 ); 
	   fprintf( stdout, "%s", msg ); 
	   close( df ); 
	   return EXIT_SUCCESS; 
	}; 

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

$ make

	...
	/tmp/ccfJzj86.o: In function `main': 
	simple.c:(.text+0x9c): warning: the `gets' function is dangerous and should not be used. 

- такое предупреждение при сборке нас не должно смущать: мы и сами наслышаны об опасности функции gets() с точки зрения возможного переполнения буфера ввода, но для нашего теста это вполне допустимо, а мы будем соблюдать разумную осторожность при вводе:

$ sudo insmod ./mmopen.ko mode=2 debug=1

Запустим 3 копии тестового процесса:

$ ./simple

> 12345

	read 6 bytes: 12345 
	12345 

$ ./simple

> 987

read 4 bytes: 987

987

$ ./simple

> ^C

То, что показано, выполняется на 4-х независимых терминалах, и его достаточно сложно объяснять в линейном протоколе, но, будем считать, что мы оставили 3 тестовых процесса заблокированными на ожидании ввода строки (символ приглашения '>'). Выполним в этом месте:

$ lsmod | grep mmopen

mmopen 2455 3

Примечание: Интересно: lsmod показывает число ссылок на модуль, но не знает (не показывает) имён ссылающихся модулей; из консольных команд (запуска модулей) имитировать (и увидеть) такой результат не получится.

$ dmesg | tail -n3

	open - node: f1899ce0, file: f2e5ff00, refcount: 1 
	open - node: f1899ce0, file: f2f35880, refcount: 2 
	open - node: f1899ce0, file: f2de2500, refcount: 3 

Хорошо видно, как счётчик ссылок использования пробежал диапазон от 0 до 3. После этого введём строки (разной длины) на 2-х копиях тестового процесс, а последний завершим по Ctrl+C (SIGINT), чтобы знать, как счётчик использования отреагирует на завершение (аварийное) клиента по сигналу. Вот что мы находим в системном журнале как протокол всех этих манипуляций:

$ dmesg | tail -n15

	write - file: f2e5ff00, write to f2ff9200 bytes 5; refcount: 3 
	put bytes : 5 
	read - file: f2e5ff00, read from f2ff9200 bytes 160; refcount: 3 
	return bytes :  6 
	read - file: f2e5ff00, read from f2ff9200 bytes 160; refcount: 3 
	return : EOF 
	close - node: f1899ce0, file: f2e5ff00, refcount: 3 
	write - file: f2f35880, write to f1847800 bytes 3; refcount: 2 
	put bytes : 3 
	read - file: f2f35880, read from f1847800 bytes 160; refcount: 2 
	return bytes :  4 
	read - file: f2f35880, read from f1847800 bytes 160; refcount: 2 
	return : EOF 
	close - node: f1899ce0, file: f2f35880, refcount: 2 
	close - node: f1899ce0, file: f2de2500, refcount: 1 

$ lsmod | grep mmopen

mmopen 2455 0

Примечание: На всём протяжении выполнения функции, реализующей операцию release() устройства, счётчик использования ещё не декрементирован: так как сессия файлового открытия ещё не завершена!

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

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


Предыдущий раздел: Оглавление Следующий раздел:
Множественное открытие устройства   Неблокирующий ввод-вывод и мультиплексирование