Skip to content

Instantly share code, notes, and snippets.

@pvsousalima
Last active August 29, 2015 14:04
Show Gist options
  • Save pvsousalima/15f30029471a49f998cc to your computer and use it in GitHub Desktop.
Save pvsousalima/15f30029471a49f998cc to your computer and use it in GitHub Desktop.
Módulo de Kernel do Linux que calculo números primos a partir de um device montado no /dev/primo e imprime o resultado na entrada /proc/primo
/* Necessary includes for device drivers */
#include <linux/module.h> /* modulo de kernel */
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h> /* /proc */
#include <linux/miscdevice.h>
#include <linux/seq_file.h> // for sequence files
#include <asm/uaccess.h> /* copy_from_user e copy_to_user */
MODULE_LICENSE("Dual BSD/GPL");
/* Global variables of the driver */
/* Major number */
int primo_major = 60;
/* Buffer to store data */
char *primo_buffer;
/* Valor a ser calculado */
long iesimo_primo = 0, last = 0;
struct proc_dir_entry *proc_file_entry;
/* Funcao de calculo do i-esimo primo */
int primo_calculate(void){
int i = 3, count, c;
if (iesimo_primo == 1) {
printk("The %ld prime numbers is: ", iesimo_primo);
last = 2;
printk("2\n");
}else{
printk("The %ld prime numbers is: ", iesimo_primo);
for (count = 2 ; count <= iesimo_primo;){
for ( c = 2 ; c <= i - 1 ; c++ ){
if ( i%c == 0 )
break;
}
if ( c == i ) {
last = i;
count++;
}
i++;
}
printk("%ld\n",last);
}
return 0;
}
/* Inicializa uma estrutura de dados buffer no lado do kernel para receber dados */
int primo_open(struct inode *inode, struct file *filp) {
/* Allocating memory for the buffer */
primo_buffer = kzalloc(20, GFP_KERNEL);
return 0;
}
/* Release do buffer */
int primo_release(struct inode *inode, struct file *filp) {
kfree(primo_buffer);
return 0;
}
/* Leitura de dados do /dev nao permitida */
ssize_t primo_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) {
/*Transfering data to user space */
printk("Read from /dev not allowed\n");
return 0;
}
/*Escrita de dados do usuario no /dev/primo */
ssize_t primo_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos){
/* Transfere dados do user para o buffer do kernel */
copy_from_user(primo_buffer, buf, count);
/* Conversao da entrada para long */
kstrtol(primo_buffer, 0, &iesimo_primo);
/* Calcula o i-esimo primo */
primo_calculate();
return count;
}
/* Structure that declaiesimo_primo the usual file */
/* access functions */
struct file_operations dev_fops = {
.read = primo_read,
.write = primo_write,
.open = primo_open,
.release = primo_release
};
/**
* Operações de arquivo para /proc/primo
*/
int proc_read(struct seq_file *m, void *v){
seq_printf(m, "%ld\n", last);
return 0;
}
int proc_open(struct inode *inode, struct file *file){
return single_open(file, proc_read, NULL);
}
struct file_operations proc_file_fops = {
.open = proc_open,
.read = seq_read,
.llseek = seq_lseek
};
int primo_init(void) {
int primo_dev=0;
/* Registering device */
primo_dev = register_chrdev(primo_major, "primo", &dev_fops);
if (primo_dev < 0) {
printk("memory: cannot obtain major number %d\n", primo_major);
return primo_dev;
}
printk("Inserting primo device on /dev \n");
proc_file_entry = proc_create("primo", 0, NULL, &proc_file_fops);
if(proc_file_entry == NULL)
printk("deu caca");
printk("Inserting primo entry in /proc");
return 0;
}
void primo_exit(void) {
unregister_chrdev(primo_major, "primo");
proc_remove(proc_file_entry);
printk("Removing primo module\n");
}
/* Declaration of the init and exit functions */
module_init(primo_init);
module_exit(primo_exit);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment