// sekcja Dominik Moszczynski i Paweł Kowol
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
static int __init chardev_init(void);
static void __exit chardev_exit(void);
static int device_open( struct inode*, struct file*);
static int device_release(struct inode*, struct file*);
static ssize_t device_read(struct file*, char*, size_t, loff_t*);
static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
#define SUCCESS 0
#define DEVICE_NAME "chardev"
static int Major = 122;
DEFINE_MUTEX(Device_Open);
//static char msg[BUF_LEN];
static char *begin = NULL;
static char *old = NULL;
//static int licznik = 0;
static int rozmiarlancucha;
int old_dlugosc = 0;
static struct cdev *chcdev;
static struct file_operations fops = {.read=device_read, .write=device_write, .open=device_open, .release=device_release};
static int __init chardev_init(void)
{
int ret;
dev_t num;
num = MKDEV(Major, 0);
ret = register_chrdev_region(num, 3, DEVICE_NAME);
if(ret < 0)
{
printk( KERN_ALERT "Nieudana próba przydziału obszaru urządzenia w jądrze - zwrócony numer %d\n", ret);
return ret;
}
chcdev = cdev_alloc();
chcdev->owner = THIS_MODULE;
chcdev->ops = &fops;
ret = cdev_add(chcdev, num, 3);
if(ret < 0)
{
printk(KERN_ALERT "Nieudana próba zarejestrowania urządzenia w jądrze - zwrócony numer %d\n", ret);
return ret;
}
printk(KERN_INFO "Przydzielono numer urzadzenia %d. Otwórz plik\n", Major);
printk(KERN_INFO "urządzenia za pomocą "
"'mknod /dev/%s c %d 0', a potem\n", DEVICE_NAME, Major);
printk(KERN_INFO "z inną ostatnią cyfrą. Próbuj czytać i pisać do tego\n");
printk(KERN_INFO "urządzenia. Po usunięciu usuń i plik");
return SUCCESS;
}
static void __exit chardev_exit(void)
{
dev_t num;
num = MKDEV(Major, 0);
cdev_del(chcdev);
unregister_chrdev_region(num,3);
printk(KERN_INFO"Żegnaj świecie\n");
//zwolnienie
kfree(begin);
begin = NULL;
}
module_init(chardev_init);
module_exit(chardev_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("XYZ");
MODULE_DESCRIPTION("Przykład modułu z plikime urządzenia");
MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
static int device_open(struct inode* inoda, struct file* plik)
{
printk( KERN_INFO "Otwarcie pliku urządzenia o numerze pobocznym"
"%d\n", iminor(inoda));
if(mutex_lock_interruptible(&Device_Open))
{
printk(KERN_INFO "Próba przjęcia semafora przerwana\n");
return -ERESTARTSYS;
}
try_module_get(THIS_MODULE);
//rozmiarlancucha = sprintf(msg, "Hello world! Mówię po raz %d\n", ++licznik);
return SUCCESS;
}
static int device_release(struct inode* inoda, struct file* plik)
{
mutex_unlock(&Device_Open);
module_put(THIS_MODULE);
return SUCCESS;
}
static ssize_t device_read(struct file* plik, char* buforUz, size_t dlugosc, loff_t* offset)
{
if(rozmiarlancucha - *offset == 0)
{
return 0;
}
if((rozmiarlancucha - *offset) < dlugosc)
{
dlugosc = rozmiarlancucha - *offset;
}
char *czytaj;
czytaj = begin;
copy_to_user(buforUz, czytaj, dlugosc);
*offset += dlugosc;
return dlugosc;
}
static ssize_t device_write( struct file* plik, const char* bufor, size_t dlugosc, loff_t* offset)
{
int nie_zapisano;
old = begin;
begin = kmalloc(dlugosc + old_dlugosc,GFP_KERNEL); //alokacja pamieci
int i = 0;
for(; i < old_dlugosc; i++)
{
*(begin+i) = *(old+i);
}
kfree(old);
old = NULL;
dlugosc += old_dlugosc;
char *zapisz;
zapisz = begin + old_dlugosc;
ssize_t zapisano = dlugosc;
nie_zapisano = copy_from_user(zapisz, bufor, dlugosc);
rozmiarlancucha = zapisano;
old_dlugosc = dlugosc;
return zapisano;
}
Learn More :