Navy2k
26-10-2006, 14:39
Hi, ich verzweifel schon seit Stunden daran. Ich hab folgendes Modul -->
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#define MAJOR_NUMBER 254
#define DEVICE_NAME "scull"
#define MAX_DEVICE 2
MODULE_LICENSE("GPL");
/* scull_size is the default value for the size of the array */
unsigned int scull_size = 1000;
/* MODULE_PARM is a macro which initialises module-variables at load time.
In this case, scull_size is the variable to be initialised
and i is the type of the varialbe. (i stands for Integer) */
// MODULE_PARM (scull_size, "i"); //Das Makro MODULE_PARM ist durch die Makros module_param, module_param_array und module_param_string ersetzt worden.
module_param(scull_size, int, 0);
ssize_t scull_write(struct file *, const char *, size_t, loff_t *);
ssize_t scull_read(struct file *, char *, size_t, loff_t *);
int scull_release (struct inode *, struct file *);
int scull_open(struct inode *, struct file *);
// old-fashioned Style
/*
struct file_operations scull_fops = {
NULL,NULL,scull_read,scull_write,NULL,NULL,NULL,NU LL,scull_open,NULL,scull_release,NULL,NULL,NULL,NU LL,NULL,NULL,NULL
};
*/
// C99 Style
struct file_operations scull_fops = {
read: scull_read,
write: scull_write,
open: scull_open,
release: scull_release,
};
typedef struct scull
{
char *array;
int position;
} scull;
scull scull_dev[MAX_DEVICE];
int scull_open(struct inode *inode, struct file *filp)
{
int minor;
// MOD_INC_USE_COUNT; //Die Makros MOD_INC_USE_COUNT und MOD_DEC_USE_COUNT existieren nicht mehr. In Kernel 2.6 werden sie normalerweise nicht gebraucht und k�nen gel�cht werden. Kernel 2.6 versucht selbst�dig mitzuz�len, wie viele Instanzen auf ein Modul zugreifen.
/* The minor number is stored in inode->i_rdev */
minor = MINOR(inode->i_rdev);
if ((minor < 0) || (minor >= MAX_DEVICE))
{
printk ("\n Unbekanntes Ger?t!!!\n");
return -ENODEV;
}
printk("\nOeffnen von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\nFehler beim Zugriff auf filp\n");
return -ENODEV;
}
filp->private_data = &scull_dev[minor];
return 0;
}
int scull_release (struct inode *inode, struct file *filp)
{
printk("\nSchliessen von %s\n",DEVICE_NAME);
// MOD_DEC_USE_COUNT; //Die Makros MOD_INC_USE_COUNT und MOD_DEC_USE_COUNT existieren nicht mehr. In Kernel 2.6 werden sie normalerweise nicht gebraucht und k�nen gel�cht werden. Kernel 2.6 versucht selbst�dig mitzuz�len, wie viele Instanzen auf ein Modul zugreifen.
return 0;
}
ssize_t scull_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
scull *dev;
printk("\nlesen von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\n Fehler beim oeffnen von filp\n");
return -ENODEV;
}
dev = (scull *) filp->private_data;
if (count > dev->position)
count = dev->position;
if (copy_to_user(buf, dev->array,count))
{ printk("\nFehler bei copy_to_user\n");
return -EFAULT;
}
*f_pos -= count;
dev->position -= count;
filp->private_data = dev;
return count;
}
ssize_t scull_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
scull *dev;
printk("\nschreiben von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\n Fehler beim oeffnen von filp\n");
return -ENODEV;
}
dev = (scull *) filp->private_data;
if (count + dev->position >= scull_size)
{
count = scull_size - dev->position;
if (!count)
{
printk ("\n %s ist voll!!!\n",DEVICE_NAME);
return -ENOMEM;
}
}
if (copy_from_user( dev->array + dev->position, buf, count))
{
printk("\nFehler bei copy_from_user\n");
return -EFAULT;
}
*f_pos += count;
dev->position += count;
filp->private_data = dev;
return count;
}
int scull_init(void)
{
int result,i,e;
SET_MODULE_OWNER(&scull_fops);
printk("\n Initialisierung von %s!!!\n",DEVICE_NAME);
printk("\nGroesse von scull_size: %i\n",scull_size);
result = register_chrdev(MAJOR_NUMBER,DEVICE_NAME, &scull_fops);
if (result < 0) {
printk(KERN_WARNING "%s: major number %i kann nicht eingebunden werden \n",DEVICE_NAME, MAJOR_NUMBER);
return result;
}
for (i=0;i<MAX_DEVICE;++i)
{
if(!(scull_dev[i].array = (char *) kmalloc(GFP_KERNEL, scull_size * sizeof(char))))
{
printk ("\n%s: Speicherallokierung fehlgeschlagen!!",DEVICE_NAME);
for (e = 0;e < i; ++e)
kfree(scull_dev[i].array);
unregister_chrdev(MAJOR_NUMBER,DEVICE_NAME);
return -EFAULT;
}
scull_dev[i].position = 0;
}
return 0;
}
void scull_exit(void)
{
int i;
printk("\n Beenden von Scull!!!\n");
for (i = 0;i<MAX_DEVICE;++i)
kfree(scull_dev[i].array);
unregister_chrdev(MAJOR_NUMBER,DEVICE_NAME);
}
module_init(scull_init);
module_exit(scull_exit);
Welcher sich leider nicht mehr kompiliren lässt unter 2.6. Weiß jemand bescheid was cih noch ändern müsste?
Makefile:
TARGET := scull
WARN := -Wall
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
CFLAGS := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE}
CC := gcc
${TARGET}.o: ${TARGET}.c
.PHONY: clean
clean:
rm -rf ${TARGET}.o
Das ganze is nen Demo um Studenten zu zeigen wie man Module ins System einbindet und lief unter 2.4er Kernel Tadellos. Bedingt durch SerialATA in einigen neuen Rechner sind wir jetzt auf SuSE 10.1 umgestiegen (ehemals 8.x), also is ein Rückschritt auf 2.4 auf keine Lösung.
Gruß Ben
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#define MAJOR_NUMBER 254
#define DEVICE_NAME "scull"
#define MAX_DEVICE 2
MODULE_LICENSE("GPL");
/* scull_size is the default value for the size of the array */
unsigned int scull_size = 1000;
/* MODULE_PARM is a macro which initialises module-variables at load time.
In this case, scull_size is the variable to be initialised
and i is the type of the varialbe. (i stands for Integer) */
// MODULE_PARM (scull_size, "i"); //Das Makro MODULE_PARM ist durch die Makros module_param, module_param_array und module_param_string ersetzt worden.
module_param(scull_size, int, 0);
ssize_t scull_write(struct file *, const char *, size_t, loff_t *);
ssize_t scull_read(struct file *, char *, size_t, loff_t *);
int scull_release (struct inode *, struct file *);
int scull_open(struct inode *, struct file *);
// old-fashioned Style
/*
struct file_operations scull_fops = {
NULL,NULL,scull_read,scull_write,NULL,NULL,NULL,NU LL,scull_open,NULL,scull_release,NULL,NULL,NULL,NU LL,NULL,NULL,NULL
};
*/
// C99 Style
struct file_operations scull_fops = {
read: scull_read,
write: scull_write,
open: scull_open,
release: scull_release,
};
typedef struct scull
{
char *array;
int position;
} scull;
scull scull_dev[MAX_DEVICE];
int scull_open(struct inode *inode, struct file *filp)
{
int minor;
// MOD_INC_USE_COUNT; //Die Makros MOD_INC_USE_COUNT und MOD_DEC_USE_COUNT existieren nicht mehr. In Kernel 2.6 werden sie normalerweise nicht gebraucht und k�nen gel�cht werden. Kernel 2.6 versucht selbst�dig mitzuz�len, wie viele Instanzen auf ein Modul zugreifen.
/* The minor number is stored in inode->i_rdev */
minor = MINOR(inode->i_rdev);
if ((minor < 0) || (minor >= MAX_DEVICE))
{
printk ("\n Unbekanntes Ger?t!!!\n");
return -ENODEV;
}
printk("\nOeffnen von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\nFehler beim Zugriff auf filp\n");
return -ENODEV;
}
filp->private_data = &scull_dev[minor];
return 0;
}
int scull_release (struct inode *inode, struct file *filp)
{
printk("\nSchliessen von %s\n",DEVICE_NAME);
// MOD_DEC_USE_COUNT; //Die Makros MOD_INC_USE_COUNT und MOD_DEC_USE_COUNT existieren nicht mehr. In Kernel 2.6 werden sie normalerweise nicht gebraucht und k�nen gel�cht werden. Kernel 2.6 versucht selbst�dig mitzuz�len, wie viele Instanzen auf ein Modul zugreifen.
return 0;
}
ssize_t scull_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
scull *dev;
printk("\nlesen von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\n Fehler beim oeffnen von filp\n");
return -ENODEV;
}
dev = (scull *) filp->private_data;
if (count > dev->position)
count = dev->position;
if (copy_to_user(buf, dev->array,count))
{ printk("\nFehler bei copy_to_user\n");
return -EFAULT;
}
*f_pos -= count;
dev->position -= count;
filp->private_data = dev;
return count;
}
ssize_t scull_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
scull *dev;
printk("\nschreiben von %s\n",DEVICE_NAME);
if (!filp)
{
printk("\n Fehler beim oeffnen von filp\n");
return -ENODEV;
}
dev = (scull *) filp->private_data;
if (count + dev->position >= scull_size)
{
count = scull_size - dev->position;
if (!count)
{
printk ("\n %s ist voll!!!\n",DEVICE_NAME);
return -ENOMEM;
}
}
if (copy_from_user( dev->array + dev->position, buf, count))
{
printk("\nFehler bei copy_from_user\n");
return -EFAULT;
}
*f_pos += count;
dev->position += count;
filp->private_data = dev;
return count;
}
int scull_init(void)
{
int result,i,e;
SET_MODULE_OWNER(&scull_fops);
printk("\n Initialisierung von %s!!!\n",DEVICE_NAME);
printk("\nGroesse von scull_size: %i\n",scull_size);
result = register_chrdev(MAJOR_NUMBER,DEVICE_NAME, &scull_fops);
if (result < 0) {
printk(KERN_WARNING "%s: major number %i kann nicht eingebunden werden \n",DEVICE_NAME, MAJOR_NUMBER);
return result;
}
for (i=0;i<MAX_DEVICE;++i)
{
if(!(scull_dev[i].array = (char *) kmalloc(GFP_KERNEL, scull_size * sizeof(char))))
{
printk ("\n%s: Speicherallokierung fehlgeschlagen!!",DEVICE_NAME);
for (e = 0;e < i; ++e)
kfree(scull_dev[i].array);
unregister_chrdev(MAJOR_NUMBER,DEVICE_NAME);
return -EFAULT;
}
scull_dev[i].position = 0;
}
return 0;
}
void scull_exit(void)
{
int i;
printk("\n Beenden von Scull!!!\n");
for (i = 0;i<MAX_DEVICE;++i)
kfree(scull_dev[i].array);
unregister_chrdev(MAJOR_NUMBER,DEVICE_NAME);
}
module_init(scull_init);
module_exit(scull_exit);
Welcher sich leider nicht mehr kompiliren lässt unter 2.6. Weiß jemand bescheid was cih noch ändern müsste?
Makefile:
TARGET := scull
WARN := -Wall
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
CFLAGS := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE}
CC := gcc
${TARGET}.o: ${TARGET}.c
.PHONY: clean
clean:
rm -rf ${TARGET}.o
Das ganze is nen Demo um Studenten zu zeigen wie man Module ins System einbindet und lief unter 2.4er Kernel Tadellos. Bedingt durch SerialATA in einigen neuen Rechner sind wir jetzt auf SuSE 10.1 umgestiegen (ehemals 8.x), also is ein Rückschritt auf 2.4 auf keine Lösung.
Gruß Ben