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



Причина для put_user и get_user в том, что память в Linux (под архитектурой Intel, это может быть различно под некоторыми другими процессорами) сегментирована. Это означает, что указатель, отдельно не ссылается на уникальное место в памяти, а только на место в сегменте памяти, и Вы должны знать, который сегмент памяти нужен. Имеется один сегмент памяти для ядра и по одному на каждый из процессов.

Единственный сегмент памяти, доступный для процесса, это его собственный, так для нормальных программ, нет никакой потребности волноваться относительно сегментов. Когда Вы пишете модуль, обычно Вы хотите обращаться к сегменту памяти ядра, который обрабатывается системой автоматически. Однако, когда содержание буфера памяти должно быть передано между процессом в настоящее время имеющим управление и ядром, функция получает указатель на буфер памяти, который находится в своем сегменте процесса. Макрокоманды put_user и get_user позволяют Вам обращаться к нужной Вам памяти.

procfs.c

>/* procfs.c - create a "file" in /proc, which allows

>* both input and output.

>*/

>/* Copyright (C) 1998-1999 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 because we use proc fs */

>#include


>/* 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 /* 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 ssize_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 */