Para compilar este módulo utiliza:
gcc -I/usr/src/linux-2.4/include -Wall -DMODULE -D__KERNEL__ -DLINUX -c ejemplo_procfs.c
/*
* ejemplo_procfs.c: un ejemplo de la interface proc
*
* Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
*
* Este archivo acompaña la guía de procfs en el código del
* núcleo Linux. Su uso principal es demostrar los conceptos y
* funciones descritas en la guía.
*
* Este software ha sido desarrollado mientras se trabajaba en
* el LART computing board (http://www.lart.tudelft.nl/), que
* está patrocinado por los proyectos Mobile Multi-media
* Communications (http://www.mmc.tudelft.nl/) y Ubiquitous
* Communications (http://www.ubicom.tudelft.nl/).
*
* El autor puede ser encontrado en:
*
* Erik Mouw
* Information and Communication Theory Group
* Faculty of Information Technology and Systems
* Delft University of Technology
* P.O. Box 5031
* 2600 GA Delft
* The Netherlands
*
*
* Este programa es software libre; puedes redistribuirlo
* y/o modificarlo bajo los términos de la GNU General
* Public License tal como ha sido publicada por la Free
* Software Foundation; por la versión 2 de la Licencia,
* o (a tu elección) cualquier versión posterior.
*
* Este programa es distribuido con la esperanza de que
* sea útil, pero SIN NINGUNA GARANTÍA; sin incluso la
* implicada de COMERCIABILIDAD o ADECUACCION PARA UN
* PROPOSITO PARTICULAR. Para más detalles refiérase a la
* GNU General Public License.
*
* Deberías de haber recibido una copia de la GNU General
* Public License con este programa; si no es así, escribe a
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#define MODULE_VERSION "1.0"
#define MODULE_NAME "ejemplo_procfs"
#define FOOBAR_LEN 8
struct fb_data_t {
char name[FOOBAR_LEN + 1];
char value[FOOBAR_LEN + 1];
};
static struct proc_dir_entry *example_dir, *foo_file,
*bar_file, *jiffies_file, *tty_device, *symlink;
struct fb_data_t foo_data, bar_data;
static int proc_read_jiffies(char *page, char **start,
off_t off, int count,
int *eof, void *data)
{
int len;
MOD_INC_USE_COUNT;
len = sprintf(page, "jiffies = %ld\n",
jiffies);
MOD_DEC_USE_COUNT;
return len;
}
static int proc_read_foobar(char *page, char **start,
off_t off, int count,
int *eof, void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
MOD_INC_USE_COUNT;
len = sprintf(page, "%s = '%s'\n",
fb_data->name, fb_data->value);
MOD_DEC_USE_COUNT;
return len;
}
static int proc_write_foobar(struct file *file,
const char *buffer,
unsigned long count,
void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
MOD_INC_USE_COUNT;
if(count > FOOBAR_LEN)
len = FOOBAR_LEN;
else
len = count;
if(copy_from_user(fb_data->value, buffer, len)) {
MOD_DEC_USE_COUNT;
return -EFAULT;
}
fb_data->value[len] = '\0';
MOD_DEC_USE_COUNT;
return len;
}
static int __init init_procfs_example(void)
{
int rv = 0;
/* crea directorio */
example_dir = proc_mkdir(MODULE_NAME, NULL);
if(example_dir == NULL) {
rv = -ENOMEM;
goto out;
}
example_dir->owner = THIS_MODULE;
/* crea jiffies usando la función conveniente */
jiffies_file = create_proc_read_entry("jiffies",
0444, example_dir,
proc_read_jiffies,
NULL);
if(jiffies_file == NULL) {
rv = -ENOMEM;
goto no_jiffies;
}
jiffies_file->owner = THIS_MODULE;
/* crea los archivos foo y bar usando las mismas
* funciones de retrollamada
*/
foo_file = create_proc_entry("foo", 0644, example_dir);
if(foo_file == NULL) {
rv = -ENOMEM;
goto no_foo;
}
strcpy(foo_data.name, "foo");
strcpy(foo_data.value, "foo");
foo_file->data = &foo_data;
foo_file->read_proc = proc_read_foobar;
foo_file->write_proc = proc_write_foobar;
foo_file->owner = THIS_MODULE;
bar_file = create_proc_entry("bar", 0644, example_dir);
if(bar_file == NULL) {
rv = -ENOMEM;
goto no_bar;
}
strcpy(bar_data.name, "bar");
strcpy(bar_data.value, "bar");
bar_file->data = &bar_data;
bar_file->read_proc = proc_read_foobar;
bar_file->write_proc = proc_write_foobar;
bar_file->owner = THIS_MODULE;
/* crea dispositivo tty */
tty_device = proc_mknod("tty", S_IFCHR | 0666,
example_dir, MKDEV(5, 0));
if(tty_device == NULL) {
rv = -ENOMEM;
goto no_tty;
}
tty_device->owner = THIS_MODULE;
/* crea enlace simbólico */
symlink = proc_symlink("tambien_jiffies", example_dir,
"jiffies");
if(symlink == NULL) {
rv = -ENOMEM;
goto no_symlink;
}
symlink->owner = THIS_MODULE;
/* todo está OK */
printk(KERN_INFO "%s %s inicializado\n",
MODULE_NAME, MODULE_VERSION);
return 0;
no_symlink:
remove_proc_entry("tty", example_dir);
no_tty:
remove_proc_entry("bar", example_dir);
no_bar:
remove_proc_entry("foo", example_dir);
no_foo:
remove_proc_entry("jiffies", example_dir);
no_jiffies:
remove_proc_entry(MODULE_NAME, NULL);
out:
return rv;
}
static void __exit cleanup_procfs_example(void)
{
remove_proc_entry("tambien_jiffies", example_dir);
remove_proc_entry("tty", example_dir);
remove_proc_entry("bar", example_dir);
remove_proc_entry("foo", example_dir);
remove_proc_entry("jiffies", example_dir);
remove_proc_entry(MODULE_NAME, NULL);
printk(KERN_INFO "%s %s borrado\n",
MODULE_NAME, MODULE_VERSION);
}
module_init(init_procfs_example);
module_exit(cleanup_procfs_example);
MODULE_AUTHOR("Erik Mouw");
MODULE_DESCRIPTION("ejemplos procfs");
EXPORT_NO_SYMBOLS;
|