The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

6.5.2 Реализация драйвера kapi

6.5.2 Реализация драйвера kapi

Предыдущая  Содержание  Следующая V*D*V

Драйвер kapi является символьным драйвером, реализованным в виде модуля ядра. В этом разделе обсуждаются детали реализации драйвера для ядра 2.6.

Существуют две основные структуры данных.

 

struct file_operations kapi_fops: эта таблица содержит функции файловых операций, такие как open, close, ioctl и другие для данного драйвера.
 
static struct file_operations kapi_fops = {
 .owner   = THIS_MODULE,
 .llseek  = NULL,
 .read    = NULL,
 .write   = NULL,
 .ioctl   = kapi_ioctl,
 .open    = kapi_open,
 .release = kapi_release,
};
 

Обратите внимание, что файловые операции read, write и lseek установлены в NULL. Эти операции недопустимы для  драйвера kapi, так как все операции выполняются через интерфейс ioctl.

struct miscdevice kapi_dev: драйвер kapi зарегистрирован как символьный драйвер, выполняющий разнообразные операции (miscellaneous character driver). Младшим номером является KAPI_MINOR (111). Старшим номером любого символьного драйвера, выполняющего разнообразные операции, является 10.
 
static struct miscdevice kapi_dev = {
 KAPI_MINOR,
 "kapi",
 &kapi_fops,
};
 

Каждый модуль ядра имеет функцию инициализации модуля и функцию освобождения модуля. Драйвер kapi предоставляет kapi_init и kapi_cleanup_module в качестве своих функций инициализации и очистки, соответственно.

 

Функция kapi_init регистрирует драйвер kapi как символьный драйвер, выполняющий разнообразные операции, с младшим номером KAPI_MINOR. Функция вызывается при загрузке модуля.

 

static int __init

kapi_init(void)

{

  int ret;

  ret = misc_register(&kapi_dev);

  if (ret)

    printk(KERN_ERR "kapi: can't misc_register on

                     minor=%d\n", KAPI_MINOR);

  return ret;

}

 

kapi_cleanup_module вызывается, когда модуль выгружается. Эта функция отменяет регистрацию драйвера.

 

static void __exit

kapi_cleanup_module(void)

{

  misc_deregister(&kapi_dev);

}

 

Процедуры open и close просто отслеживают количество одновременно работающих пользователей данного драйвера. Они используются в основном для отладки.

 

static int

kapi_open(struct inode *inode, struct file *file)

{

  kapi_open_cnt++;

  return 0;

}

 

static int

kapi_release(struct inode *inode, struct file *file)

{

  kapi_open_cnt--;

  return 0;

}

 

Давайте теперь обсудим ядро драйвера kapi, функцию kapi_ioctl. kapi_ioctl зарегистрирована в таблице fops как операция ioctl для данного драйвера.

Функция kapi_ioctl выполняет следующие операции:

 

1.Копирование передаваемого пользователем объекта kfunc_t в объект ядра kfunc_t.

2.Выделение памяти для DIR_IN и DIR_OUT аргументов.

3.Копирование из пользовательских буферов всех аргументов, которые имеют флаг направления DIR_IN, в буферы ядра.

4.Вызов запрошенной функции ядра.

5.Копирование из буферов ядра всех аргументов с флагом направления DIR_OUT в пользовательские буферы.

6.Наконец, копирование возвращаемого значения функции ядра в пространство пользователя и освобождение всех выделенных буферов ядра.

 

Аргументом для kapi_ioctl является указатель на объект типа kfunc_t. Первый шаг заключается в копировании объекта kfunc_t в память ядра.

 

static int

kapi_ioctl(struct inode *inode, struct file *file,

           unsigned int cmd, unsigned long arg)

{

  int i,err;

  kfunc_t kdata,udata;

 

  if(copy_from_user(&udata, (kfunc_t *)arg,

                    sizeof(kfunc_t)))

return -EFAULT;

 

Выделяем буферы ядра для всех аргументов и возвращаемого значения. Выполняем копирование всех аргументов, имеющих направление DIR_IN.

 

for (i = 0 ; i < udata.num ; i++){

  kdata.arg[i].val = kmalloc(udata.arg[i].size,

                             GFP_KERNEL);

  if (udata.arg[i].dir == DIR_IN){

    if (copy_from_user(kdata.arg[i].val, udata.arg[i].val,

                       udata.arg[i].size))

      goto error;

  }

}

kdata.ret.val = kmalloc(udata.ret.size, GFP_KERNEL);

 

Вызываем запрошенную функцию ядра. В этом примере мы предоставили ioctl для функции ядра my_kernel_func. Вам необходимо таким же образом добавить свои функции в инструкцию switch. Идентификатор функции также должен быть добавлен в перечисление function_id в kapi.h. Возвращаемое значение вызываемой функции следует сохранить в kdata.ret.val.

 

switch (cmd) {

 

case MY_KERNEL_FUNC:

  *(int *)(kdata.ret.val) =

      my_kernel_func(*(int *)kdata.arg[0].val,

                     (char *)kdata.arg[1].val,

                     (char *)kdata.arg[2].val);

  break;

 

default:

  return -EINVAL;

}

 

Теперь пришло время отправить результат работы вызываемой функции ядра обратно в функцию-заглушку пространства пользователя. Копируем все аргументы, имеющие направление DIR_OUT, и возвращаемое значение функции в пользовательское пространство. Также освобождаем выделенные буферы ядра.

 

err = 0;

for (i = 0 ; i < udata.num ; i++){

  if (udata.arg[i].dir == DIR_OUT){

    if (copy_to_user(udata.arg[i].val, kdata.arg[i].val,

                     udata.arg[i].size))

      err = -EFAULT;

  }

  kfree(kdata.arg[i].val);

}

 

/* копирование возвращаемого значения */

if (copy_to_user(udata.ret.val, kdata.ret.val,

                 udata.ret.size))

  err = -EFAULT;

 

kfree(kdata.ret.val);

return err;

}

 

Наконец, my_kernel_func просто выводит пользовательский ввод и возвращает целое значение 2. Для простоты мы поместили эту функцию в kapi-kernel.c. Вы не должны добавлять свои функции в этот файл. Также не забудьте проэкспортировать функцию, используя EXPORT_SYMBOL, так как драйвер kapi загружается как модуль ядра.

 

int my_kernel_func(int val, char *in_str, char *out_str){

  printk(KERN_DEBUG"val = %d, str = %s\n", val, in_str);

  strcpy(out_str, "Hello User Space");

  return 2;

}

 

EXPORT_SYMBOL(my_kernel_func);

 

Предыдущая  Содержание  Следующая