Энциклопедия разработчика модулей ядра Linux | страница 36



>int init_module() {

> /* Success if proc_register_dynamic is a success,

> * failure otherwise */

>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

> return proc_register(&proc_root, &Our_Proc_File);

>#else

> return proc_register_dynamic(&proc_root, &Our_Proc_File);

>#endif

> /* proc_root is the root directory for the proc

> * fs (/proc). This is where we want our file to be

> * located. */

>}


>/* Cleanup - unregister our file from /proc. This could

>* get dangerous if there are still processes waiting in

>* WaitQ, because they are inside our open function,

>* which will get unloaded. I'll explain how to avoid

>* removal of a kernel module in such a case in chapter 10. */

>void cleanup_module() {

> proc_unregister(&proc_root, Our_Proc_File.low_ino);

>}

Замена для printk

В начале (глава1), я сказал, что X и программирование модулей ядра не совместимы. Это истинно при разработке модуля, но в фактическом использовании, Вы должны быть способны послать сообщениям любому tty[10]. Это важно для идентификации ошибок после того, как модуль выпущен, потому что он будет использоваться через любой из терминалов.

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

printk.c

>/* printk.c - send textual output to the tty you're

>* running on, regardless of whether it's passed

>* through X11, telnet, etc.

>*/

>/* Copyright (C) 1998 by Ori Pomerantz */


>/* The necessary header files */

>/* Standard in kernel modules */

>#include /* We're doing kernel work */

>#include /* Specifically, a module */


>/* Deal with CONFIG_MODVERSIONS */

>#if CONFIG_MODVERSIONS==1

>#define MODVERSIONS

>#include

>#endif


>/* Necessary here */

>#include /* For current */

>#include /* For the tty declarations */


>/* Print the string to the appropriate tty, the one

>* the current task uses */

>void print_string(char *str) {

> struct tty_struct *my_tty;

> /* The tty for the current task */

> my_tty = current->tty;

> /* If my_tty is NULL, it means that the current task

> * has no tty you can print to (this is possible, for

> * example, if it's a daemon). In this case, there's

> * nothing we can do. */

> if (my_tty != NULL) {

>  /* my_tty->driver is a struct which holds the tty's

>  * functions, one of which (write) is used to