Привет, Хабр! Я тут недавно увлёкся темой написания драйверов на линукс, ибо просто хотелось посмотреть, как выглядит это ваше программирование линукс модулей.

Так как я профессионально раскрашиваю кнопочки в React, мне было весьма трудно понять суть низкоуровневого программирования, но в итоге я разобрался. Однако, хочется, чтобы написание драйверов было такой же лёгкое задачей как написание фронтенда, я захотел написать библиотеку, которая бы помогла незнающим писать модули просто и быстро.

Эта статья была написана в рамках моего школьного проекта «упрощение написания linux-модулей». Так что, не судите строго, я всего лишь школьник.
Первым делом, хотелось бы абстрагироваться инициализации char-драйвера и создания device_driver. Во всех проектах их пишут, и каждый раз теряют время. Теперь не будут. За то, как этот код работает, вам могут объяснить на ютубе. Лично я пользовался вот этой серией роликов:https://www.youtube.com/watch?v=U7QFcpVh248&list=PL1zwAXk5ZrWKxLyCq73lzFn3oSLruM750
int Init_chrdev()
{
int retval = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if(retval < 0)
{
printk("Chardev was NOT initialised. Error code: %d", retval);
return 0;
}
else if (retval == 0)
{
printk(KERN_ALERT "Chardev was initialised");
return -1;
}
else
{
printk(KERN_ALERT "smt went wrong!");
return -1;
}
return -1;
}
int CreateDevice()
{
MyClass = class_create(THIS_MODULE, CLASS_NAME);
if(MyClass == NULL)
{
printk(KERN_ALERT "Couldn't initialize class");
unregister_chrdev_region(dev, DEVICE_NAME);
return -1;
}
if(device_create(MyClass, NULL, dev, NULL, DEVICE_NAME) == NULL) {
printk("Couldn't init file!\n");
unregister_chrdev_region(dev, DEVICE_NAME);
return -1;
}
return 0;
}
В линукс модулях есть такое понятие как файл. Это не тот файл, о котором вы думаете. Любое подключенное устройство в системе считается как файл, и всё взаимодействие происходит через него. Код для взаимодействия с этими файлами в линуксе тоже нормально не прописан. В итоге, приходится городить 4 метода и одну структуру. Ну, это повод внести это в библиотеку.
static ssize_t readDRiv(struct file *File, char *UserBuffer, size_t ammount, loff_t *offs)
{
int ToCopy, NotCopied, Delta;
ToCopy = min(ammount, BufferSize);
NotCopied = copy_to_user(UserBuffer, Buffer, ToCopy);
Delta = ToCopy - NotCopied;
printk("read is %d", Delta);
return Delta;
}
static ssize_t writeDRiv(struct file *File, const char *UserBuffer, size_t ammount, loff_t *offs)
{
int ToCopy, NotCopied, Delta;
ToCopy = min(ammount, sizeof(Buffer));
NotCopied = copy_from_user(Buffer, UserBuffer, ToCopy);
Delta = ToCopy - NotCopied;
BufferSize = ToCopy;
printk("write is %d", Delta);
return Delta;
}
static int openDRiv(struct inode *node, struct file *filee)
{
printk("opened an openDRiv");
return 0;
}
static int closeDRiv(struct inode *node, struct file *filee)
{
printk("closed an openDRiv");
return 0;
}
static struct file_operations f_ops = {
.owner = THIS_MODULE,
.open = openDRiv,
.write = writeDRiv,
.read = readDRiv,
.release = closeDRiv
};
Ну и под конец добавим пару имён, чтобы библиотека работала стабильно
Ну и вот, у нас получилась библиотека. Она есть на гитхабе вот здесь:https://github.com/NikitaZavortny/linux-modules-base
В этой статье я рассказал кратко о моей библиотеке. Хотелось бы поинтересоваться, что вы думаете о ней?