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

UnixForum





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

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

Более экзотические возможности

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

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

Запуск процессов из ядра

Новые процессы пользовательского пространства могут создаваться кодом ядра, так же, как они создаются и пользовательским кодом вызовами группы exec*().

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

Простейший пример демонстрирует возможность порождения новых процессов в системе по инициативе ядра (архив exec.tgz):

mod_exec.c :

	#include <linux/module.h> 
	
	static char *str; 
	module_param( str, charp, S_IRUGO ); 
	
	int __init exec_init( void ) { 
	   int rc; 
	   char *argv[] = { "wall", "this is wall message", NULL }; 
	   static char *envp[] = { NULL };
	   if( str ) argv[ 1 ] = str; 
	   rc = call_usermodehelper( "/usr/bin/wall", argv, envp, 0 ); 
	   if( rc ) 
	      printk( KERN_INFO "failed to execute : %s %s\n", argv[ 0 ], argv[ 1 ] ); 
	   else 
	      printk( KERN_INFO "execute : %s %s\n", argv[ 0 ], argv[ 1 ] ); 
	   return -1; 
	} 
	
	module_init( exec_init ); 
	MODULE_LICENSE( "GPL" );
	MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" ); 
	MODULE_VERSION( "1.1" );

Вызов call_usermodehelper() получает параметры точно так же, как вызов пользовательского пространства execve() (через который выполняются все вызовы семейства exec*()), детали смотрите в справочной странице :

$ man 2 execve

Срабатывание созданного модуля:

$ sudo insmod mod_exec.ko

	this is wall messageom root@notebook.localdomain (Tue May  3 22:32:00 2011): 
	insmod: error inserting 'mod_exec.ko': -1 Operation not permitted 

$ dmesg | tail -n1

	execute : wall this is wall message 

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

$ wall this is wall message

	Broadcast message from olej@notebook.localdomain (pts/2) (Tue May  3 22:33:57this is wall message

В этом и есть особенность и ограниченность метода: процесс запускается без управляющего терминала и с нестандартным для него окружением! Если в качестве пользовательского процесса, заменив строку запуска, использовать:

	char *argv[] = { "/bin/echo", "this is wall message", NULL }; 

То результатом будет:

$ sudo insmod mod_exec.ko str=XXX

	insmod: error inserting 'mod_exec.ko': -1 Operation not permitted 

$ dmesg | tail -n1

	execute : /bin/echo XXX 

- мы имеем совершенно нормальный запуск пользовательского процесса ... но в глухо-немом варианте, без ожидаемого вывода в терминал, поскольку не существует терминала, в который надлежало бы производить такой вывод.

Всю основную работу по созданию и запуску процесса, как легко видеть, выполняет вызов (<linux/kmod.h>):

	static inline int call_usermodehelper( char *path, char **argv, char **envp, enum umh_wait wait ); 
	enum umh_wait { 
	   UMH_NO_WAIT = -1,   /* don't wait at all */ 
	   UMH_WAIT_EXEC = 0,  /* wait for the exec, but not the process */ 
	   UMH_WAIT_PROC = 1,  /* wait for the process to complete */ 
	}; 

Предыдущий раздел: Оглавление Следующий раздел:
Устройства USB   Сигналы