Как стать автором
Обновить

Как писать linux — модули просто и быстро

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

Так как я профессионально раскрашиваю кнопочки в 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

В этой статье я рассказал кратко о моей библиотеке. Хотелось бы поинтересоваться, что вы думаете о ней?

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.