Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > kernel-mode в Linux для новичка


Автор: Sandric 12.10.2010, 17:34
В университете задали задание выполнить копирование из файла в файл в kernel и user mode. Вообще лабораторная рассчитывалась под win, но я уже начал выполнять под убунтой, и вот что получилось:
Код

#include "fcntl.h"

#include "sys/types.h"

#include "sys/stat.h"


int main(){

    std::cout << "hello world";

    int fd, fdn;

    fd = open("from2copy.txt", O_RDONLY);

    fdn = open("where2copy.txt", O_WRONLY | O_CREAT);

    chmod("where2copy.txt", S_IRWXU);

    std::cout << "\n" << fd;

    const size_t bufSize = 256;

    char chBuf[256];

    int fileSize = read(fd, chBuf, bufSize);

    std::cout << "\n" << chBuf;

    write(fdn, chBuf, fileSize);

}

Она работает, но теперь мне нужно запустить ее в режиме ядра.
Если кто знает как это сделать, пожалуйста отпишитесь.

Автор: MAKCim 12.10.2010, 18:05
боюсь, с таким уровнем знаний (судя по коду) ядро вы не осилите
значит скорее всего вам в центр помощи нужно обратиться, т. к. за вас тут коди писать не будут

Автор: Sandric 12.10.2010, 22:24
Цитата(MAKCim @ 12.10.2010,  18:05)
боюсь, с таким уровнем знаний (судя по коду) ядро вы не осилите
значит скорее всего вам в центр помощи нужно обратиться, т. к. за вас тут коди писать не будут

Вообщето я писал kernel-mode код на плюсах около года назад. Это был простой драйвер на курсах по низкоуровневому программированию, но это было под win. В любом случае не думаю, что вы можете что то предполагать относительно того что я смогу осилить, а что не смогу. И если вам кажется что мой код настолько далек от необходимого, думаю уместнее было бы порекоммендовать конкретную литературу или маны. Конечно если вы на 100(!)% уверены что я осилю.

Автор: MAKCim 12.10.2010, 23:09
Sandric, 
http://docs.google.com/viewer?a=v&q=cache:5-XYK8a1q8QJ:linuxkernel.ru/store/knm.pdf+%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5+%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9+%D1%8F%D0%B4%D1%80%D0%B0+linux&hl=be&gl=by&pid=bl&srcid=ADGEESirXgdDTYmLjSQULrsR8QhJh96fQkMalTYZrvVFFEITJkLucVbpGn4wuEdbRhGkxScTYSekMJrHF85BpH1Y7IeDCqnCZXvQGKytiTPq0e-VsrNk8KCddMTT2VOB4E3C7VtRLhLg&sig=AHIEtbTL_AB8Mh9AV-xtDKSJOYkjvME4wA

Автор: xvr 13.10.2010, 09:40
Работа с файлами в kernel под Linux практически невозможна (поправьте меня, если это уже не так).
Под Win - возможна. Так что бегом обратно под Win  smile 

Автор: MAKCim 13.10.2010, 10:21
Цитата(xvr @  13.10.2010,  09:40 Найти цитируемый пост)
Работа с файлами в kernel под Linux практически невозможна

что значит практически?

Автор: Sandric 13.10.2010, 13:13
Цитата(MAKCim @ 12.10.2010,  23:09)
Sandric, 
http://docs.google.com/viewer?a=v&q=cache:5-XYK8a1q8QJ:linuxkernel.ru/store/knm.pdf+%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5+%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9+%D1%8F%D0%B4%D1%80%D0%B0+linux&hl=be&gl=by&pid=bl&srcid=ADGEESirXgdDTYmLjSQULrsR8QhJh96fQkMalTYZrvVFFEITJkLucVbpGn4wuEdbRhGkxScTYSekMJrHF85BpH1Y7IeDCqnCZXvQGKytiTPq0e-VsrNk8KCddMTT2VOB4E3C7VtRLhLg&sig=AHIEtbTL_AB8Mh9AV-xtDKSJOYkjvME4wA

Спасибо. Я в свою очередь нашел на английском языке http://www.tldp.org/LDP/lkmpg/2.6/html/index.html. Буду читать.

Автор: GrayCardinal 13.10.2010, 13:18
Во-первых в приведенном коде как минимум одна ошибка. Во-вторых. Какое отношение user-space код имеет к kernel-sapce'у 
?

Автор: svlary 14.10.2010, 05:15
Цитата(xvr @  13.10.2010,  09:40 Найти цитируемый пост)
поправьте меня, если это уже не так
  • asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
  • asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
  • asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
В файле /usr/src/kernels/linux-2.6.16/fs/read_write.c

Автор: xvr 14.10.2010, 08:53
Цитата(MAKCim @ 13.10.2010,  10:21)
Цитата(xvr @  13.10.2010,  09:40 Найти цитируемый пост)
Работа с файлами в kernel под Linux практически невозможна

что значит практически?

Я давно не смотрел в ядро, но когда я смотрел туда в последний раз, то таблица файлов (т.е. файловых хэндлов) была принадлежностью описания user space процесса. Т.е. без какого то хелпера (в виде обычного пользовательского процесса) нельзя было использовать никакой handle based файловый ввод вывод (kernel просто не мог открыть файл, т.к. было некуда)
Цитата

В файле /usr/src/kernels/linux-2.6.16/fs/read_write.c
А sys_open там есть?

Автор: svlary 15.10.2010, 05:43
Цитата(xvr @  14.10.2010,  08:53 Найти цитируемый пост)
А sys_open там есть?

  Эти функции подробно описаны в книге :  Бовет, Д. "Ядро Linux, 3-е изд. "

В частности про функцию sys_open () там пишется  (стр 650):

Опишем работу функции sys_open (). Она выполняет следующие шаги: 
  • 1. Вызывает getname (), чтобы прочитать из адресного пространства процесса 
    путь к файлу. 
  • 2. Вызывает get_unused_fd(), чтобы наЙТИ незанятый СЛОТ В current-> 
    fiies->fd. Соответствующий индекс (дескриптор нового файла) хранится 
    в локальной переменной f d. 
  • 3. Вызывает функцию filpopeno, передавая ей в качестве параметров путь, 
    флаги режима доступа и битовую маску прав доступа. В свою очередь, эта 
    функция выполняет следующие шаги: 
      • копирует флаги режима доступа в namei_f lags, но кодирует флаги ре- 
      режима доступа ordonly, owronly и ordwr специальным образом: нуле- 
      нулевой (самый младший) бит nameifiags устанавливается, только если 
      доступ к файлу требует прав на чтение, а бит с номером 1 устанавлива- 
      устанавливается, только если доступ к файлу требует прав на запись. Обратите 
      внимание, что в системном вызове open () невозможно указать, что дос- 
      доступ к файлу не требует привилегий на чтение или запись. Однако это 
      имеет смысл при анализе пути, содержащем символьные ссылки; 
      • вызывает функцию open namei (), передавая ей в качестве параметров 
      путь, модифицированные флаги режима доступа и адрес локальной 
      структуры nameidata. Эта функция анализирует путь следующим об- 
      образом: 
      D если флаг ocreat не установлен среди флагов режима доступа, 
      функция запускает операцию анализа пути со сброшенным флагом 
      lookup_parent и установленным флагом lookup_open. Кроме того, 
      флаг lookup_follow устанавливается, только если флаг o_nofollow 
      сброшен, а флаг lookupdirectory устанавливается, только если флаг 
      o_directory установлен; 
      D если среди флагов режима доступа флаг ocreat установлен, функ- 
      функция запускает операцию анализа с установленными флагами 
      LOOKUP_PARENT, LOOKUP_OPEN И LOOKUP_CREATE. ЕСЛИ фуНКЦИЯ 
      pathiookup() завершит свое выполнение успешно, обсуждаемая 
      функция проверит, существует ли запрошенный файл. В противном 
      случае она выделит новый дисковый индексный дескриптор, вызвав 
      метод create родительского индексного дескриптора; 
      ( Примечание : Функция opennamei (), помимо прочего, выполняет несколько проверок на 
      безопасность в отношении файла, который определила операция анализа пути. 
      В частности, проверяется, существует ли индексный дескриптор, связанный с 
      найденным объектом "элемент каталога", является ли он обычным файлом, и 
      разрешен ли текущему процессу доступ к этому файлу в соответствии с флага- 
      флагами режима доступа. Кроме того, если файл открывается для записи, функция 
      убеждается, что он не заблокирован другими процессами. )
      • вызывает функцию dentryopen (), передавая ей адреса объекта "эле- 
      "элемент каталога" и объекта, представляющего смонтированную систему, 
      которые были получены в результате анализа пути. Вызванная функция 
      выполняет следующее: 
      D выделяет новый файловый объект; 
      п инициализирует поля f_f lags и fmode файлового объекта в соответ- 
      соответствии с флагами режима доступа, переданными системному вызову 
      open(); 
      п инициализирует поля fdentry и f_vf smnt файлового объекта в соот- 
      соответствии с адресами объекта "элемент каталога" и объекта, пред- 
      представляющего смонтированную файловую систему, переданными в 
      качестве параметров; 
      п записывает в поле fop содержимое поля iop соответствующего 
      объекта "индексный дескриптор". Это действие устанавливает все 
      методы, необходимые для последующих файловых операций; 
      D заносит файловый объект в список открытых файлов, на который 
      указывает поле s_f iles суперблока файловой системы; 
      а если метод open определен среди файловых операций, функция вы- 
      вызывает его; 
      ° вызывает fiierastateinit о для инициализации структур данных 
      опережающего чтения (см. главу 16); 
      D если флаг odirect установлен, функция проверяет, можно ли вы- 
      выполнить операции прямого ввода/вывода на этом файле (см. гла- 
      главу 16); 
      и возвращает адрес файлового объекта; 
      • возвращает адрес файлового объекта.
  • 4. Записывает в current->fiies->fd[fd] адрес файлового объекта, возвра- 
    возвращенный функцией dentryopen (). 
  • 5. Возвращает fd.

Автор: xvr 15.10.2010, 08:46
Внимательно смотрим на пп 1,2,4 и делаем вывод - эта функция (и весь вышеперечисленный набор) открывает файл в ТЕКУЩЕМ ПОЛЬЗОВАТЕЛЬСКОМ процессе. Т.е. вы откроете файл где то у user level приложения, а не в ядре. Вы сможете общаться с этим файлом и из ядра, но и приложение у пользователя его тоже увидит (и это может ему не понравится). 
Еще у меня есть подозрение, что буфера для обмена с файлом тоже будут у пользовательского приложения (для sys_open это явно написанно в п1)

Вывод - пишите на Win, там функции Nt*File работают одинаково в User Space и в Kernel Space и позволяют работать с файлом с Kernel Level не вываливая его потроха в первый попавшийся User Space процесс  smile 

PS. В Linux insmod не зря читает образ драйвера (kernel модуля) из User Space, а не непосредственно из ядра

Автор: Sandric 2.11.2010, 18:10
Добрый день.
Спасибо за все советы, но боюсь мне уже будет поздно переделывать все под винду.

У меня новый вопрос - запись чтение в файл используя стандартную библиотеку (fprintf).

Я сделал копирование файла, используя vfs_write/vfs_read:
Код

#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>

#include <linux/module.h>    /* Needed by all modules */
#include <linux/kernel.h>    /* Needed for KERN_INFO */

struct file* file_open(const char* path, int flags, int rights) {
    struct file* filp = NULL;
    mm_segment_t oldfs;
    int err = 0;

    oldfs = get_fs();
    set_fs(get_ds());
    filp = filp_open(path, flags, rights);
    set_fs(oldfs);
    if(IS_ERR(filp)) {
        err = PTR_ERR(filp);
        return NULL;
    }
    return filp;
}


void file_close(struct file* file) {
    filp_close(file, NULL);
}


int file_read(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) {
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}


int file_write(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) {
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}


int file_sync(struct file* file) {
    file_fsync(file, file->f_dentry);
    return 0;
}


int init_module(void)
{

    const char *file_path = "/home/sandric/from2copy.txt";
    const char *file_path_dest = "/home/sandric/where2copy.txt";
    
    unsigned char data[1024];

    struct file *fd = file_open(file_path, 0, 0);    
    struct file *fd_dest = file_open(file_path_dest, 1, 1);

    int size = file_read(fd, 0, data, 1024);

    file_write(fd_dest, 0, data, size);

    file_close(fd_dest);
    file_close(fd);    

    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye world 1.\n");
}


Но теперь мне нужно реализовать чтение/запись используя стандартную библиотеку в пользовательском режиме и режиме ядра.

Есть ли какой то аналог fprintf, или функция, которую использует fprintf при работе с ядром.
Спасибо.

Автор: MAKCim 2.11.2010, 19:17
смотрите <linux/kernel.h>

Автор: xvr 2.11.2010, 20:48
Цитата(Sandric @  2.11.2010,  18:10 Найти цитируемый пост)
Спасибо за все советы, но боюсь мне уже будет поздно переделывать все под винду.

Это не советы, это диагноз   smile 

Цитата(Sandric @  2.11.2010,  18:10 Найти цитируемый пост)
Есть ли какой то аналог fprintf, или функция, которую использует fprintf при работе с ядром.
Есть kprintf, а то, что вам надо это редкое извращение. Очень сомневаюсь, что такое найдется. Пишите свои функции.

man на filp_open порадовал:

Цитата

Description

This is the helper to open a file from kernelspace if you really have to. But in generally you should not do this, so please move along, nothing to see here.. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)