» » » Ори Померанц - Энциклопедия разработчика модулей ядра Linux


Авторские права

Ори Померанц - Энциклопедия разработчика модулей ядра Linux

Здесь можно скачать бесплатно "Ори Померанц - Энциклопедия разработчика модулей ядра Linux" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Рейтинг:
Название:
Энциклопедия разработчика модулей ядра Linux
Издательство:
неизвестно
Год:
неизвестен
ISBN:
нет данных
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

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

Описание и краткое содержание "Энциклопедия разработчика модулей ядра Linux" читать бесплатно онлайн.



Linux Kernel Module Programming Guide свободная книга; Вы можете воспроизводить и/или изменять ее в соответствии с версией 2 (или, в вашем случае, любой более поздней версией) GNU General Public License, опубликованной Free Software Foundation. Версия 2 поставляется с этим документом в Приложении E.

Эта книга распространяется в надежде, что будет полезна, но без какой-либо гарантии; даже без подразумеваемой гарантии высокого спроса или пригодности какой-либо для специфической цели.

Автор поощряет широкое распространение этой книги для персонального или коммерческого использования, если вышеупомянутое примечание относительно авторского права остается неповрежденным, и распространитель твердо придерживается условий GNU General Public License (см. Приложение E). Вы можете копировать и распространять эту книгу бесплатно или для получения прибыли. Никакое явное разрешение не требуется от автора для воспроизводства этой книги в любой среде, физической или электронной.

Обратите внимание, производные работы и переводы этого документа должны быть помещены согласно GNU General Public License, и первоначальное примечание относительно авторского права должно остаться неповрежденным. Если Вы пожертвовали новый материал этой книге, Вы должны сделать исходный текст доступным для ваших изменений. Пожалуйста делайте изменения и модификации, доступные непосредственно поддерживающему данный проект Ori Pomerantz. Он объединит модификации и обеспечит непротиворечивость изменений для всего Linux сообщества.

Если Вы планируете издавать и распространять эту книгу коммерчески, пожертвования, лицензионные платежи, и/или напечатанные копии будут высоко оценены автором и Linux Documentation Project (LDP). Содействие таким образом показывает вашу поддержку свободного программного обеспечения и Linux Documentation Project. Если Вы имеете вопросы или комментарии, пожалуйста войдите в контакт с автором по адресу, приведенному выше.






* we keep this, rather than call the original function

* (sys_open), is because somebody else might have

* replaced the system call before us. Note that this

* is not 100% safe, because if another module

* replaced sys_open before us, then when we're inserted

* we'll call the function in that module - and it

* might be removed before we are.

*

* Another reason for this is that we can't get sys_open.

* It's a static variable, so it is not exported. */

asmlinkage int (*original_call)(const char *, int, int);


/* For some reason, in 2.2.3 current->uid gave me

* zero, not the real user ID. I tried to find what went

* wrong, but I couldn't do it in a short time, and

* I'm lazy - so I'll just use the system call to get the

* uid, the way a process would.

*

* For some reason, after I recompiled the kernel this

* problem went away.

*/

asmlinkage int (*getuid_call)();


/* The function we'll replace sys_open (the function

* called when you call the open system call) with. To

* find the exact prototype, with the number and type

* of arguments, we find the original function first

* (it's at fs/open.c).

*

* In theory, this means that we're tied to the

* current version of the kernel. In practice, the

* system calls almost never change (it would wreck havoc

* and require programs to be recompiled, since the system

* calls are the interface between the kernel and the processes). */

asmlinkage int our_sys_open(const char *filename, int flags, int mode) {

 int i = 0;

 char ch;

 /* Check if this is the user we're spying on */

 if (uid == getuid_call()) {

  /* getuid_call is the getuid system call,

  * which gives the uid of the user who

  * ran the process which called the system

  * call we got */

  /* Report the file, if relevant */

  printk("Opened file by %d: ", uid);

  do {

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

   get_user(ch, filename+i);

#else

   ch = get_user(filename+i);

#endif

   i++;

   printk("%c", ch);

  } while (ch != 0);

  printk("\n");

 }

 /* Call the original sys_open - otherwise, we lose

 * the ability to open files */

 return original_call(filename, flags, mode);

}


/* Initialize the module - replace the system call */

int init_module() {

 /* Warning - too late for it now, but maybe for next time... */

 printk("I'm dangerous. I hope you did a ");

 printk("sync before you insmod'ed me.\n");

 printk("My counterpart, cleanup_module(), is even");

 printk("more dangerous. If\n");

 printk("you value your file system, it will ");

 printk("be \"sync; rmmod\" \n");

 printk("when you remove this module.\n");

 /* Keep a pointer to the original function in

 * original_call, and then replace the system call

 * in the system call table with our_sys_open */

 original_call = sys_call_table[__NR_open];

 sys_call_table[__NR_open] = our_sys_open;

 /* To get the address of the function for system

 * call foo, go to sys_call_table[__NR_foo]. */

 printk("Spying on UID:%d\n", uid);

 /* Get the system call for getuid */

 getuid_call = sys_call_table[__NR_getuid];

 return 0;

}


/* Cleanup - unregister the appropriate file from /proc */

void cleanup_module() {

 /* Return the system call back to normal */

 if (sys_call_table[__NR_open] != our_sys_open) {

  printk("Somebody else also played with the ");

  printk("open system call\n");

  printk("The system may be left in ");

  printk("an unstable state.\n");

 }

 sys_call_table[__NR_open] = original_call;

}

Отложенные процессы

Что Вы делаете, когда кто-то просит Вас о чем-то, что Вы не можете сделать сразу же? Если вы человек, и вы обеспокоены, единственное, что Вы можете сказать: «Не сейчас, я занят.». Но если вы модуль, Вы имеете другую возможность. Вы можете поместить процесс в спячку, чтобы он бездействовал, пока Вы не сможете обслужить его. В конце концов, процессы помещаются в спячку и пробуждаются ядром постоянно.

Этот модуль является примером этого подхода. Файл (названный /proc/sleep) может быть открыт только одним процессом сразу. Если файл уже открыт, модуль называет module_interruptible_sleep_on[7]. Эта функция изменяет состояние задачи (задача является структурой данных в ядре, которая хранит информацию относительно процесса и системного вызова) в состояние TASK_INTERRUPTIBLE, что означает, что задача не будет выполняться пока не будет пробуждена так или иначе, и добавляет процесс к WaitQ, очереди задач ждущих, чтобы обратиться к файлу. Затем функция обращается к планировщику за контекстным переключателем другого процесса, который может использовать CPU, то есть управление передается другому процессу.

Когда процесс закончит работу с файлом, тот закрывается, и вызывается module_close. Эта функция пробуждает все процессы в очереди (нет никакого механизма, чтобы пробудить только одни из них). Управление возвращается и процесс, который только закрыл файл, может продолжать выполняться. Планировщик решает, что тот процесс поработал достаточно и передает управление другому процессу. В конечном счете, один из процессов, который был в очереди, получит управление. Он продолжит выполнение с той точки, в которой был вызван module_interruptible_sleep_on[8]. Он может установить глобальную переменную, чтобы сообщить всем другим процессам, что файл является все еще открытым. Когда другие процессы получат часть времени CPU, они увидят глобальную переменную и продолжат спячку.

Чтобы сделать нашу жизнь более интересной, module_close не имеет монополии на пробуждение процессов которые ждут, чтобы обратиться к файлу. Сигнал Ctrl-C (SIGINT) может также пробуждать процесс[9]. В таком случае, мы хотим возвратить -EINTR немедленно. Это важно, так как пользователи могут, например, уничтожить процесс прежде, чем он получит доступ к файлу.

Имеется еще одна хитрость. Некоторые процессы не хотят спать: они хотят или получать то, что они хотят, немедленно или сообщить, что действие не может быть выполнено. Такие процессы используют флажок O_NONBLOCK при открытии файла. Ядро отвечает, возвращая код ошибки -EAGAIN из операций, которые иначе блокировали бы, типа открытия файла в этом примере. Программа cat_noblock, доступная в исходном каталоге для этой главы, может использоваться, чтобы открыть файл с флагом O_NONBLOCK.

sleep.c

/* sleep.c - create a /proc file, and if several

* processes try to open it at the same time, put all

* but one to sleep */

/* Copyright (C) 1998-99 by Ori Pomerantz */


/* The necessary header files */

/* Standard in kernel modules */

#include <linux/kernel.h> /* We're doing kernel work */

#include <linux/module.h> /* Specifically, a module */


/* Deal with CONFIG_MODVERSIONS */

#if CONFIG_MODVERSIONS==1

#define MODVERSIONS

#include <linux/modversions.h>

#endif


/* Necessary because we use proc fs */

#include <linux/proc_fs.h>


/* For putting processes to sleep and waking them up */

#include <linux/sched.h>

#include <linux/wrapper.h>


/* In 2.2.3 /usr/include/linux/version.h includes a

* macro for this, but 2.0.35 doesn't - so I add it

* here if necessary. */

#ifndef KERNEL_VERSION

#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))

#endif


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

#include <asm/uaccess.h> /* for get_user and put_user */

#endif


/* The module's file functions ********************** */

/* Here we keep the last message received, to prove

* that we can process our input */

#define MESSAGE_LENGTH 80

static char Message[MESSAGE_LENGTH];


/* Since we use the file operations struct, we can't use

* the special proc output provisions - we have to use

* a standard read function, which is this function */

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

static size_t module_output(

 struct file *file, /* The file read */

 char *buf, /* The buffer to put data to (in the user segment) */

 size_t len, /* The length of the buffer */

 loff_t *offset) /* Offset in the file - ignore */

#else

 static int module_output(

 struct inode *inode, /* The inode read */

 struct file *file, /* The file read */

 char *buf, /* The buffer to put data to (in the user segment) */

 int len) /* The length of the buffer */

#endif

{

 static int finished = 0;

 int i;

 char message[MESSAGE_LENGTH+30];

 /* Return 0 to signify end of file - that we have

 * nothing more to say at this point. */

 if (finished) {

  finished = 0;

  return 0;

 }

 /* If you don't understand this by now, you're

 * hopeless as a kernel programmer. */

 sprintf(message, "Last input:%s\n", Message);

 for(i=0; i<len && message[i]; i++) put_user(message[i], buf+i);

 finished = 1;

 return i; /* Return the number of bytes "read" */

}


/* This function receives input from the user when

* the user writes to the /proc file. */

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

static ssize_t module_input(

 struct file *file, /* The file itself */

 const char *buf, /* The buffer with input */

 size_t length, /* The buffer's length */

 loff_t *offset) /* offset to file - ignore */

#else

 static int module_input(

 struct inode *inode, /* The file's inode */

 struct file *file, /* The file itself */

 const char *buf, /* The buffer with the input */

 int length) /* The buffer's length */

#endif

{

 int i;

 /* Put the input into Message, where module_output

 * will later be able to use it */


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Энциклопедия разработчика модулей ядра Linux"

Книги похожие на "Энциклопедия разработчика модулей ядра Linux" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Ори Померанц

Ори Померанц - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Ори Померанц - Энциклопедия разработчика модулей ядра Linux"

Отзывы читателей о книге "Энциклопедия разработчика модулей ядра Linux", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.