turns-00023.parquet:38937
4cd04e54b2cacc2abd414031
turn 1/2gpt-4-turbo-2024-04-09PolishPoland591 words
degenerate_repetitionAbsentFinal dense release
USER
Napisać sterownik znakowy, który odbiera znak lub ciąg znaków i wyświetla go w dmesg zamieniając małe litery na duże. Zadanie można przygotować na PC i uruchomić na BB
ASSISTANT
Poniżej znajdziesz przykład sterownika znakowego dla systemu Linux, który odbiera znaki lub ciąg znaków od użytkownika, zamienia wszystkie małe litery na duże, a następnie loguje przetworzony ciąg do dziennika systemowego za pomocą `dmesg`. Poniższa implementacja zakłada, że masz już skonfigurowane środowisko deweloperskie na PC lub BB (BeagleBone) z kompilatorem GCC i odpowiednimi nagłówkami jądra.
### Przygotowanie
1. Przygotuj plik źródłowy dla sterownika znakowego (`chardev_upper.c`).
2. Przygotuj `Makefile`, aby móc zbudować moduł kernela.
### Kod źródłowy (`chardev_upper.c`):
```c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "upperchardev" ///< The device will appear at /dev/upperchardev using this value
#define CLASS_NAME "upper" ///< The device class will be named 'upper'
MODULE_LICENSE("GPL"); ///< The license type -- this affects available functionality
MODULE_AUTHOR("Anonimowy Autor"); ///< The author -- visible when you use modinfo on the kernel module
MODULE_DESCRIPTION("A simple Linux char driver that converts lowercase letters to uppercase"); ///< The description -- visible when you use modinfo
MODULE_VERSION("0.1"); ///< A version number to inform users
static int majorNumber; ///< Stores the device number -- determined automatically
static char message[256] = {0}; ///< Memory for the string that is passed from userspace
static short size_of_message; ///< Used to remember the size of the string stored
static struct class* uppercharClass = NULL; ///< The device-driver class struct pointer
static struct device* uppercharDevice = NULL; ///< The device-driver device struct pointer
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops =
{
.open = dev_open,
.write = dev_write,
.release = dev_release,
};
static int __init upperchar_init(void) {
printk(KERN_INFO "UpperChar: Initializing the UpperChar LKM\n");
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (majorNumber<0){
printk(KERN_ALERT "UpperChar failed to register a major number\n");
return majorNumber;
}
printk(KERN_INFO "UpperChar: registered correctly with major number %d\n", majorNumber);
uppercharClass = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(uppercharClass)){
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to register device class\n");
return PTR_ERR(uppercharClass);
}
printk(KERN_INFO "UpperChar: device class registered correctly\n");
uppercharDevice = device_create(uppercharThisClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
if (IS_ERR(uppercharDevice)){
class_destroy(uppercharClass);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Failed to create the device\n");
return PTR_ERR(uppercharDevice);
}
printk(KERN_INFO "UpperChar: device class created correctly\n");
return 0;
}
static void __exit upperchar_exit(void){
device_destroy(uppercharClass, MKDEV(majorNumber, 0));
class_unregister(uppercharClass);
class_destroy(uppercharClass);
unregister_chrdev(majorName, DEVICE_NAME);
printk(KERN_INFO "UpperChar: Goodbye from the LKM!\n");
}
static int dev_open(struct inode *inodep, struct file *filep){
printk(KERN_INFO "UpperChar: Device has been opened\n");
return 0;
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
copy_from_user(message, buffer, len);
print_uppercase(message, len);
printk(KERN_INFO "UpperChar: Received %zu characters from the user\n", len);
return len;
}
void print_uppercase(char *msg, size_t len) {
for (size_t i = 0; i < len; i++) {
msg[i] = toupper(msg[i]);
}
printk(KERN_INFO "UpperChar: %s\n", msg);
}
static int dev_release(struct inode *inodep, struct file *filep){
printk(KERN_INFO "UpperChar: Device successfully closed\n");
return 0;
}
module_init(upperchar_init);
module_exit(upperchar_exit);
```
### Makefile:
```Makefile
obj-m+=chardev_upper.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```
### Testowanie:
1. Skompiluj moduł: `make`.
2. Załaduj moduł do kernela: `sudo insmod chardev_upper.ko`.
3. Sprawdź numer przydzielony przez system: `dmesg | grep 'UpperChar'`.
4. Tworzenie pliku urządzenia: `sudo mknod /dev/upperchardev c <major-number> 0`, gdzie `<major-number>` to numer wydrukowany przez `dmesg`.
5. Użyj `echo` i `cat` do wysyłania danych do sterownika, a następnie przeczytaj odpowiednie logi z `dmesg`.
Tak przygotowany sterownik powinien działać zarówno na PC, jak i na BeagleBone.