parametry pro překlad první dva identifikují jaké nástroje pro překlad se mají použít (VUT FIT merlin)
CC=x86_64-linux-gcc CROSS_COMPILE=x86_64-linux- ARCH=um SUBARCH=x86_64
vyčístí přeložené věci
make mrproper
použije jako konfigurační soubor .config
make oldconfig
spuštění jádra s imagem a umid
./vmlinux umid=debian ubd0=./image.lenny64.ext3
mirror jádra na VUT FIT serveru merlin http://merlin.fit.vutbr.cz/mirrors/kernel.org/linux/kernel/v3.x/ vyhledávání ve zdrojovém kódě jádra http://lxr.free-electrons.com/ident
načtení modulu
mkdir -p /lib/modules/<verze jádra>/misc cp <soubor.ko> /lib/modules/<verze jádra>/misc/<soubor.ko> depmod -a modprobe <soubor>
vypíše moduly
lsmod
vypíše informace o modulu
modinfo <modul> modinfo </cesta/k/modulu.ko>
smaže modul
rmmod <modul>
ukázka makefile pro překlad jaderného modulu
# Makefile for mod-2.6.c NAME = cdev-test obj-m := $(NAME).o default: $(NAME).c make -C ./linux-stable SUBDIRS=$(PWD) modules
překlad pro architekturu x86_64
ARCH=um SUBARCH=x86_64 make
modul, který vytvoří soubor /proc/test
, který vypíše aktuální čas a datum
#include <linux/init.h> #include <linux/module.h> #include <linux/seq_file.h> #include <linux/proc_fs.h> #include <linux/kernel.h> #include <linux/time.h> MODULE_LICENSE("GPL"); static struct proc_dir_entry * entry; /*struktura pro file v proc*/ static int show(struct seq_file *m, void *p) { struct timespec s_timespec; struct tm s_tm; getnstimeofday(&s_timespec); time_to_tm(s_timespec.tv_sec, 0, &s_tm); seq_printf(m, "%ld-%02d-%02dT%02d:%02d:%02dZ\n", 1900+s_tm.tm_year, s_tm.tm_mon+1, s_tm.tm_mday, s_tm.tm_hour, s_tm.tm_min, s_tm.tm_sec); return 0; } static int my_open(struct inode *inode, struct file *file) { return single_open(file, show, NULL); }; static struct file_operations ct_file_ops = { .owner = THIS_MODULE, .open = my_open, .read = seq_read, .llseek = seq_lseek, .release = single_release }; static int ct_init(void) { entry = create_proc_entry("test",0, NULL); if (entry) entry->proc_fops = &ct_file_ops; return 0; } static void __exit ct_exit(void) { remove_proc_entry("test", NULL); } module_init(ct_init); module_exit(ct_exit);
modul, který vytvoří znakové zařízení test, které při zápisu počítá počet mezer a nových řádků a při čtení vypíše větu:
X words written\n
.
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/kernel.h> #include <linux/slab.h> MODULE_LICENSE("GPL"); /* alloc major number from 120-127 */ #define MAJORNUMBER 120 #define DEV_NAME "test" #define OUTPUT_MAX_SIZE 50 dev_t dev; struct cdev *test_cdev; int my_word_count = 0; char my_output [OUTPUT_MAX_SIZE]; int my_output_size = 0; int my_position = 0; static ssize_t test_read(struct file *f, char *ch, size_t s, loff_t *o) { int count_to_end = my_output_size - my_position; int result_size = s >= count_to_end ? count_to_end : s; printk(KERN_DEBUG "jsem ve funkci test_read\n"); if(my_position < my_output_size) { if(copy_to_user(ch, my_output+my_position, result_size)) { return -EFAULT; } my_position += result_size; return result_size; } return 0; } static ssize_t test_write(struct file *f, const char *ch, size_t s, loff_t *o) { int i; char *buffer; printk(KERN_DEBUG "jsem ve funkci test_write\n"); if((buffer = kmalloc(s, GFP_KERNEL)) == NULL) { return -ENOMEM; } if(copy_from_user(buffer, ch, s)) { kfree(buffer); return -EFAULT; } for(i=0; i < s; i++) { if(buffer[i] == ' ' || buffer[i] == '\n') { my_word_count++; } } kfree(buffer); return s; } static int test_open(struct inode *i, struct file *f) { printk(KERN_DEBUG "jsem ve funkci test_open\n"); my_output_size = snprintf(my_output, OUTPUT_MAX_SIZE, "%d words written\n", my_word_count); my_position = 0; return 0; } static int test_release(struct inode *i, struct file *f) { printk(KERN_DEBUG "jsem ve funkci test_release\n"); return 0; } static loff_t test_lseek(struct file *file, loff_t offset, int orig) { printk(KERN_DEBUG "jsem ve funkci test_lseek\n"); my_position += offset; return my_position; } static struct file_operations test_fops = { .owner = THIS_MODULE, .read = test_read, .write = test_write, .open = test_open, .release = test_release, .llseek = test_lseek, }; static int __init cdev_test_init(void) { dev = MKDEV(MAJORNUMBER, 0); register_chrdev_region(dev, 1, DEV_NAME); test_cdev = cdev_alloc(); test_cdev->owner = THIS_MODULE; test_cdev->ops = &test_fops; /* get entry in /sysfs */ kobject_set_name(&test_cdev->kobj, DEV_NAME); cdev_add(test_cdev, dev, 1); return 0; } static void __exit cdev_test_exit(void) { cdev_del(test_cdev); unregister_chrdev_region(dev, 1); } module_init(cdev_test_init); module_exit(cdev_test_exit);
zařízení je možné přidat příkazem
mknod /dev/test c 120 0
tabulka systémových volání pro architekturu x86 se nachází v adresáři arch/x86/syscalls/
v souborech syscall_<architektura>.tbl
(jádro 3.4.41).
systémové volání, které vrátí součet dvou jeho argumentů:
do arch/x86/syscalls/syscall_32.tbl
přidat řádek
223 i386 add sys_add
do arch/x86/syscalls/syscall_64.tbl
přidat řádek
312 64 add sys_add
do include/linux/syscalls.h
přidat řádek
asmlinkage long sys_add(int number1, int number2);
do kernel/Makefile
přidat řádek
obj-y += add.o
vytvořit soubor kernel/add.c
#include <linux/kernel.h> #include <linux/linkage.h> asmlinkage long sys_add(int number1, int number2) { return number1 + number2; }
instalace Fedora
su -c "yum install uml_utilities"
spuštění s umid jádra
uml_mconsole <umid>