Рубрики
c

linux kernel module / simple module / tty

Makefile hello world

cat  > Makefile << "EOF" 
CONFIG_MODULE_SIG=n
 
CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)
DEST = /lib/modules/$(CURRENT)/misc
TARGET = hello_printk
 
obj-m      := $(TARGET).o
 
all: default clean
#all: default
 
default: 
        $(MAKE) -C $(KDIR) M=$(PWD) modules
 
install:
        cp -v $(TARGET).ko $(DEST)
#      /sbin/depmod -v | grep $(TARGET)
        /sbin/depmod
        /sbin/insmod $(TARGET).ko
        /sbin/lsmod | grep $(TARGET)
 
uninstall:
        /sbin/rmmod $(TARGET)
        rm -v $(DEST)/$(TARGET).ko
        /sbin/depmod
 
clean:
        @rm -f *.o .*.cmd .*.flags *.mod.c *.order
        @rm -f .*.*.cmd *.symvers *~ *.*~
        @rm -fR .tmp* *.mod
        @rm -rf .tmp_versions
 
disclean: clean
        @rm -f *.ko
EOF

# Исправить восемь пробелов на TAB
sed -i 's/        /tt/g' Makefile 

hello world c

cat >  hello_printk.c << "EOF" 
#include 
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LALA >");
 
static int __init hello_init(void) {
   printk("Hello, world!n");
   return 0;
}
 
static void __exit hello_exit(void) {
   printk("Goodbye, world!n");
}
 
module_init(hello_init);
module_exit(hello_exit);
EOF


make

file hello_print.ko
modinfo ./hello_print.ko

modprobe  ./hello_print.ko


rmmod hello_print

simple tty Makefile

cat > Makefile << "EOF" 
CONFIG_MODULE_SIG=n

CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)
DEST = /lib/modules/$(CURRENT)/misc
TARGET = simple_tty

obj-m      := $(TARGET).o

all: default clean

default:
                $(MAKE) -C $(KDIR) M=$(PWD) modules

install:
                cp -v $(TARGET).ko $(DEST)
                /sbin/depmod
                /sbin/insmod $(TARGET).ko
                /sbin/lsmod | grep $(TARGET)

uninstall:
                /sbin/rmmod $(TARGET)
                rm -v $(DEST)/$(TARGET).ko
                /sbin/depmod

clean:
                @rm -f *.o .*.cmd .*.flags *.mod.c *.order
                @rm -f .*.*.cmd *.symvers *~ *.*~
                @rm -fR .tmp* *.mod
                @rm -rf .tmp_versions

disclean: clean
                @rm -f *.ko

EOF




symple tty c

cat > simple_tty.c << "EOF"
#include 
#include 
#include 
#include 
#include 

#define DRIVER_NAME "simple_tty"
#define DEVICE_NAME "ttySIMPLE"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LALA ");
MODULE_DESCRIPTION("Simple TTY Driver");
MODULE_VERSION("1.0");

static struct tty_driver *simple_tty_driver;
static struct tty_port *simple_tty_port; // Pointer to tty_port

static int simple_tty_open(struct tty_struct *tty, struct file *file)
{
    printk(KERN_INFO "simple_tty: open()n");
    return 0;
}

static void simple_tty_close(struct tty_struct *tty, struct file *file)
{
    printk(KERN_INFO "simple_tty: close()n");
}

static ssize_t simple_tty_write(struct tty_struct *tty, const unsigned char *buf, size_t count)
{
    size_t i;
    printk(KERN_INFO "simple_tty: write()n");
    for (i = 0; i < count; i++) {
        printk(KERN_INFO "simple_tty: %cn", buf[i]);
    }
    return count;
}

static struct tty_operations simple_tty_ops = {
    .open = simple_tty_open,
    .close = simple_tty_close,
    .write = simple_tty_write,
};

static int __init simple_tty_init(void)
{
    int retval;

    // Allocate memory for the tty_port structure
    simple_tty_port = kzalloc(sizeof(struct tty_port), GFP_KERNEL);
    if (!simple_tty_port) {
        printk(KERN_ERR "simple_tty: failed to allocate tty portn");
        return -ENOMEM;
    }

    // Initialize the tty_port structure
    tty_port_init(simple_tty_port);

    // Register TTY driver
    simple_tty_driver = tty_alloc_driver(1, TTY_DRIVER_RESET_TERMIOS);
    if (!simple_tty_driver) {
        printk(KERN_ERR "simple_tty: failed to allocate tty drivern");
        kfree(simple_tty_port); // Free allocated tty_port on error
        return -ENOMEM;
    }

    simple_tty_driver->owner = THIS_MODULE;
    simple_tty_driver->driver_name = DRIVER_NAME;
    simple_tty_driver->name = DEVICE_NAME;
    simple_tty_driver->major = 0; // Auto-assign major number
    simple_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
    simple_tty_driver->subtype = SERIAL_TYPE_NORMAL;
    simple_tty_driver->init_termios = tty_std_termios;
    simple_tty_driver->flags = TTY_DRIVER_REAL_RAW;

    // Set the ports field of the driver
    simple_tty_driver->ports = &simple_tty_port; // Assign the port

    tty_set_operations(simple_tty_driver, &simple_tty_ops);

    // Register the driver in the kernel
    retval = tty_register_driver(simple_tty_driver);
    if (retval) {
        printk(KERN_ERR "simple_tty: failed to register tty drivern");
        kfree(simple_tty_port); // Free allocated tty_port on error
        return retval;
    }

    printk(KERN_INFO "simple_tty: driver registeredn");
    return 0;
}

static void __exit simple_tty_exit(void)
{
    tty_unregister_driver(simple_tty_driver);
    tty_port_destroy(simple_tty_port); // Free the tty_port
    kfree(simple_tty_port); // Free allocated tty_port memory
    printk(KERN_INFO "simple_tty: driver unregisteredn");
}

module_init(simple_tty_init);
module_exit(simple_tty_exit);

EOF



Описание драйвера:
Основные структуры:
tty_driver — структура, которая описывает драйвер устройства TTY.
tty_operations — набор операций, которые драйвер поддерживает (открытие, запись, закрытие и т.д.).
Функции драйвера:
simple_tty_open() — вызывается при открытии устройства.
simple_tty_close() — вызывается при закрытии устройства.
simple_tty_write() — функция записи данных в устройство.
Регистрация драйвера:
Драйвер регистрируется с помощью tty_register_driver(), после чего его можно использовать как стандартное устройство TTY.
Деконструкция драйвера:
tty_unregister_driver() — используется при выгрузке модуля для корректной очистки драйвера.



make
modprobe  simple_tty.ko
dmesg | grep simple_tty
echo "test" > /dev/ttySIMPLE
lsmod | grep simple_tty
rmmod simple_tty


Рубрики
c

GDB

Описание:

GNU Debugger - переносимый отладчик проекта GNU, который работает на многих UNIX-подобных системах/

Команды:

gdb name_program - запуск отладки программы с именем name_program
quit - выход
q - выход
run - запустить отладку
r - запустить отладку
break - создать точку остановки или прерывания
b - создать точку остановки или прерывания
  main - начало программы
b main - программа будет прерываться от самого начала
next - продолжить выполнение дебага
n - продолжить выполнение дебага 
list - показать исходный код (если он есть)
l - показать исходный код (если он есть)
l 12 - перейти на 12 строку исходного кода
print ИМЯ_переменной - покажет текущее значение переменной
r - вернутся в начало программы
info locals - показать все локальные переменные
с - продолжить (continuum)
disable - отключает все точки b
!!! при нажатии клавиши enter выполнится последняя команда (удобно использовать с командой n)
!!! make program_name
!!! gdb ./name_orogram