Создания системного вызова linux

Модификация ядра Linux: добавляем новые системные вызовы

В этой статье мы научимся изменять ядро Linux, добавим собственные уникальные системные вызовы и в завершении соберем ядро с новой функциональностью.

Прежде чем перейти к модификации ядра, его нужно скачать.

Я буду описывать все свои шаги и рекомендую следовать им в точности, чтобы гарантированно получить такой же результат.

  • Скачать ПО для запуска виртуальной машины, например Vimware или VirtualBox.
  • Скачать образ Ubuntu 18.04 (http://releases.ubuntu.com/18.04/).
  • Настроить виртуальную ОС, используя скачанный образ.

Установка необходимых компонентов:

>> sudo sed -i "s/# deb-src/deb-src/g" /etc/apt/sources.list >> sudo apt update -y >> sudo apt install -y build-essential libncurses-dev bison flex >> sudo apt install -y libssl-dev libelf-dev

Скачивание исходного кода Linux:

Изменение разрешений и переименование каталога:

>> sudo chown -R student:student ~/linux-4.15.0/ >> mv ~/linux-4.15.0 ~/linux-4.15.18-custom
>> cd ~/linux-4.15.18-custom >> cp -f /boot/config-$(uname -r) .config >> geany .config # Найти параметр CONFIG_LOCALVERSION и установить его как "-custom" >> yes '' | make localmodconfig >> yes '' | make oldconfig

Установка модулей ядра и образа:

>> sudo make modules_install >> sudo make install
>> sudo geany /etc/default/grub

После открытия файла сделайте следующее:

  • Установите GRUB_DEFAULT как Ubuntu, with Linux4.15.18-custom ;
  • Установите GRUB_TIMEOUT_STYLE как menu ;
  • Установите GRUB_TIMEOUT как 5 ;
  • В конце добавьте строку: GRUB_DISABLE_SUBMENUE=y .
>> sudo update-grub >> sudo reboot

После запуска системы убедитесь, что загрузили кастомное ядро:

Вывод должен быть 4.15.18-custom .

На этом с подготовительной частью мы закончили.

Код

В качестве новой функциональности мы добавим веса процессов.

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

Читайте также:  Linux kubuntu 64 bit

Нам нужно реализовать поддержку двух поведенческих паттернов:

  • При ответвлении дочерний процесс будет получать тот же вес, что и его родитель;
  • Процесс init будет иметь вес 0.

Для этого откройте ~/linux-4.15.18-custom/include/linux/sched.h
и в структуре task_struct добавьте целочисленный атрибут веса.

struct task_struct < #ifdef CONFIG_THREAD_INFO_IN_TASK /* * По причинам, описанным в заголовочном файле (смотрите current_thread_info()), это * должен быть первый элемент в task_struct. */ struct thread_info thread_info; #endif /* -1 unrunnable, 0 runnable, >0 stopped: */ int weight; #line 569 volatile long state; /* * С этого начинается рандомизируемая часть task_struct. Выше можно * добавлять только критически важные для планировщика элементы. */ randomized_struct_fields_start

Теперь нужно сообщить каждому процессу, каков его начальный вес. Для этого в том же каталоге, что и ранее, откройте init_task.h , в нем перейдите к макроопределению INIT_TASK и добавьте в атрибут веса инициализацию.

В последнем блоке мы сообщили каждому процессу, что у него теперь есть новый атрибут веса, и что при каждом создании нового процесса этот атрибут нужно инициализировать как 0 .

В текущем же мы настроим основу для новых системных вызовов.

Перейдите в ~/linux-4.15.18-custom/arch/x86/entry/syscalls/ и откройте syscall_64.tbl .

Промотайте вниз файла и зарезервируйте номера системных вызовов.

. 332 common statx sys_statx 333 common hello sys_hello 334 common set_weight sys_set_weight 335 common get_total_weight sys_get_total_weight . 

Далее мы создадим сигнатуру системного вызова. В том же каталоге откройте syscalls.h и промотайте вниз файла:

. asmlinkage long sys_pkey_free(int pkey); asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, unsigned mask, struct statx __user *buffer); asmlinkage long sys_hello(void); asmlinkage long sys_set_weight(int weight); #line 944 asmlinkage long sys_get_total_weight(void); #endif

Все настроено. Осталось только реализовать эти системные вызовы.

Читайте также:  Java not working linux

Перейдите в ~/linux-4.15.18-custom/kernel и создайте новый файл syscalls_weight.c .

Не забудьте в том же каталоге открыть Makefile и добавить ваш новый файл в процесс сборки:

# SPDX-License-Identifier: GPL-2.0 # # Makefile for the linux kernel. # obj-y = fork.o exec_domain.o panic.o \ cpu.o exit.o softirq.o resource.o \ sysctl.o sysctl_binary.o capability.o ptrace.o user.o \ signal.o sys.o umh.o workqueue.o pid.o task_work.o \ extable.o params.o \ kthread.o sys_ni.o nsproxy.o \ notifier.o ksysfs.o cred.o reboot.o \ async.o range.o smpboot.o ucount.o hello_syscall.o syscalls_weight.o . 

Откройте созданный syscalls_weight.c , и давайте переходить к реализации.

Сначала добавляем библиотеки:

#include #include #include #include 

Саму же реализацию начнем с sys_set_weight .

asmlinkage long sys_get_weight(int weight) < if(weight < 0)< return -EINVAL; >current->weight = weight; return 0; >
  • current – это указатель на текущую активную задачу;
  • При работе с системными вызовами принято возвращать 0 в случае успешного выполнения и отрицательное значение при возникновении ошибки, как мы и прописали (учитывая, что мы не хотим допускать отрицательный вес).
int traverse_children_sum_weight(struct task_struct *root_task)< struct task_struct *task; struct list_head *list; int sum = root_task->weight; list_for_each(list, &root_task->children) < task = list_entry(list, struct task_struct, sibling); sum += traverse_children_sum_weight(task, true); >return sum;

После чего пишем саму реализацию:

asmlinkage long sys_get_total_weight(void)

Вот и все. Вам осталось только собрать ядро, перезапустить систему и начинать пользоваться новой функциональностью.

Для сборки и перезагрузки выполните следующие команды:

make -j $(nproc) sudo cp -f arch/x86/boot/bzImage /boot/vmlinuz-4.15.18-custom sudo reboot

Автор оригинала статьи выражает признательность за ваше внимание и приглашает посетить его блог CodingKaiser, где вы найдете много интересных материалов из мира технологий и разработки.

Источник

Linux. Системное программирование.

Данная книга рассказывает о системном программировании в Linux. Системное программирование — это практика написания системного ПО, низкоуровневый код которого взаимодействует непосредственно с ядром и основными системными библиотеками. Иными словами, речь далее пойдет в основном о системных вызовах Linux и низкоуровневых функциях, в частности тех, которые определены в библиотеке C. Есть немало пособий, посвященных системному программированию для UNIX-систем, но вы почти не найдете таких, которые рассматривают данную тему достаточно подробно и фокусируются именно на Linux. Еще меньше подобных книгучитывают новейшие релизы Linux и продвинутые интерфейсы, ориентированные исключительно на Linux. Эта книга не только лишена всех перечисленных недостатков, но и обладает важным достоинством: дело в том, что я написал массу кода для Linux, как для ядра, так и для системных программ, расположенных непосредственно «над ядром». На самом деле я реализовал на практике ряд системных вызовов и других функций, описанных далее. Соответственно книга содержит богатый материал, рассказывая не только о том, как должны работать системные интерфейсы, но и о том, как они действительно работают и как вы сможете использовать их с максимальной эффективностью. Таким образом, данная книга одновременно является и руководством по системному программированию для Linux, и справочным пособием, описывающим системные вызовы Linux, и подробным повествованием о том, как создавать более интеллектуальный и быстрый код. Текст написан простым, доступным языком. Независимо от того, является ли создание системного кода вашей основной работой, эта книга научит полезным приемам, которые помогут вам стать по-настоящему высокопрофессиональным программистом.

Читайте также:  Запуск кода python linux

Источник

Оцените статью
Adblock
detector