2013-04-05 2 views
0

Основываясь на моем учебном проекте, моя текущая задача состоит в том, чтобы сгенерировать 10 случайных чисел, используя модуль ядра, и моя программа пользовательского пространства (c-программа) должна иметь возможность отображать эти числа. Я изучал пространство ядра и программы пользовательского пространства. И я столкнулся с созданием персональных устройств. Я создал устройство, использующее эту команду.реализация символьного устройства для генерации случайных чисел

mknod /dev/my_device c 222 0 

От этого я понял, что это устройство является промежуточным звеном между пользовательским пространством и программами пространства ядра. Таким образом, я создал модуль ядра регистров Wich и отменяет регистрацию мой характер device.Saved в my_dev.c

#include<linux/module.h> 
#include<linux/init.h> 
#include"my_dev.h" 

MODULE_AUTHOR("Krishna"); 
MODULE_DESCRIPTION("A simple char device"); 

static int r_init(void); 
static void r_cleanup(void); 

module_init(r_init); 
module_exit(r_cleanup); 


static int r_init(void) 
{ 
printk("<1>hi\n"); 
if(register_chrdev(222,"my_device",&my_fops)){ 
    printk("<1>failed to register"); 
} 
return 0; 
} 
static void r_cleanup(void) 
{ 
printk("<1>bye\n"); 
unregister_chrdev(222,"my_device"); 
return ; 
} 

Мой файл Make для compling этот модуль является

obj-m += my_dev.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 

Этот модуль ядра компилируется и загружается в память используя команду insmod.

Вот программа, которая записывает и читает какой-либо текст в пользовательский буфер, сохраненный как my_dev.h.

/* 
* my device header file 
*/ 
#ifndef _MY_DEVICE_H 
#define _MY_DEVICE_H 

#include <linux/fs.h> 
#include <linux/sched.h> 
#include <linux/errno.h> 
#include <asm/current.h> 
#include <asm/segment.h> 
#include <asm/uaccess.h> 

char my_data[80]="heloooo"; /* our device */ 

int my_open(struct inode *inode,struct file *filep); 
int my_release(struct inode *inode,struct file *filep); 
ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp); 
ssize_t my_write(struct file *filep,const char *buff,size_t count,loff_t *offp); 

struct file_operations my_fops={ 
    open: my_open, 
    read: my_read, 
write: my_write, 
release:my_release, 
}; 

int my_open(struct inode *inode,struct file *filep) 
{ 
    /*MOD_INC_USE_COUNT;*/ /* increments usage count of module */ 
return 0; 
} 

int my_release(struct inode *inode,struct file *filep) 
{ 
/*MOD_DEC_USE_COUNT;*/ /* decrements usage count of module */ 
return 0; 
} 
ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp) 
{ 
/* function to copy kernel space buffer to user space*/ 
if (copy_to_user(buff,my_data,strlen(my_data)) != 0) 
    printk("Kernel -> userspace copy failed!\n"); 
return strlen(my_data); 

} 
ssize_t my_write(struct file *filep,const char *buff,size_t count,loff_t *offp) 
{ 
/* function to copy user space buffer to kernel space*/ 
if (copy_from_user(my_data,buff,count) != 0) 
    printk("Userspace -> kernel copy failed!\n"); 
return 0; 
} 
#endif 

Вот моя космическая программа acs.c пользователя, который при запуске печатает «heloooo», читая текст из буфера ядра из приведенной выше программы.

#include<stdio.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 

int main() 
{ 
int fd=0,ret=0; 
char buff[80]=""; 

fd=open("/dev/my_device",O_RDONLY); 

printf("fd :%d\n",fd); 

ret=read(fd,buff,10); 
buff[ret]='\0'; 

printf("buff: %s ;length: %d bytes\n",buff,ret); 
close(fd); 
} 

Теперь моя проблема в том, что мне нужно написать программу пользовательского пространства, которая при запуске печатает 10 случайных чисел. Но эти числа должны быть сгенерированы с использованием модуля ядра. Так что в основном выше трех кодов хорошо работает и печатает «helooo». что мне нужно сделать, вместо «helooo» мне нужно получить случайные числа в качестве вывода.

Вот модуль памяти, который генерирует некоторые случайные числа, используя алгоритм линейного конгруэнтного генератора. LCG.c

#include <linux/module.h> /* Needed by all modules */ 
#include <linux/kernel.h> /* Needed for KERN_INFO */ 

int init_module(void) 
{ 
int M = 8; //Modulus, M>0 
    int a = 9; //Multiplier, 0 <= a < M. 
    int c = 3; //Increment, 0 <= c < M. 
    int X = 1; //seed value, 0 <= X(0) < M 
    int i;  //iterator, i < M 
    for(i=0; i<8; i++) 
    { 
      X = (a * X + c) % M; 
      printk(KERN_INFO "%d\n",X); 

    } 
    return 0; 
} 
void cleanup_module(void) 
{ 
printk(KERN_INFO "Task Done ! :D.\n"); 
} 

У меня есть все коды. Но я не знаю, как поместить этот код генератора случайных чисел в код активации моего устройства charecter. Когда я запускаю программу acs.c, мне нужно получить вывод модуля памяти LCG.c, используя персональное устройство. Пожалуйста, помогите мне найти решение.

+0

'ret = read (fd, buff);' 'read()' принимает 3 параметра, вы забываете последний (nbytes) –

+0

Но эта программа работает даже без третьего параметра – Krishna

+0

Вы уверены? Он не компилируется: 'error: инициализатор массива должен быть списком инициализатора int buff [80] =" ";' –

ответ

0

Попробуйте с этими изменениями, я только добавил изменения:

Refactor LCG.C так, что генератор случайных чисел является отдельной функцией и убедитесь, что эта функция не статична. Вам также необходимо экспортировать этот СИМВОЛ.

void generate_random_lcg(char* output_str) 
{ 
    static const int M = 8; //Modulus, M>0 
    static const int a = 9; //Multiplier, 0 <= a < M. 
    static const int c = 3; //Increment, 0 <= c < M. 
    static int X = 1; //seed value, 0 <= X(0) < M 

    int i;  //iterator, i < M 
    ssize_t index = 0; 
    for(i=0; i<8; i++) 
    { 
     X = (a * X + c) % M; 
     index += sprintf(output_str + index, "%d\n", X); 
    } 
    output_str[index] = '\0'; 
} 

EXPORT_SYMBOL(generate_random_lcg); 

Таким образом, функция может быть непосредственно вызвана модулем LCG, а также снаружи.

Теперь, чтобы вызвать эту функцию из вашего модуля my_dev и вернуть результат, вам нужны эти изменения:

my_dev.c:

static int r_init(void) 
{                 
    printk("<1>hi\n"); 
    if(register_chrdev(222,"my_device",&my_fops)){     
      printk("<1>failed to register");      
    } 

    memset(output_str, 0, MAX_SIZE);        

    return 0;              
} 

В my_dev.ч

extern void generate_random_lcg(char* output_str); 

#define MAX_SIZE 1024 
static char output_str[MAX_SIZE]; 

ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp) 
{ 
    ssize_t output_str_size = 0; 
    generate_random_lcg(output_str); 
    output_str_size = strlen(output_str); 
    /* function to copy kernel space buffer to user space*/ 
    if (copy_to_user(buff,output_str,output_str_size) != 0) 
    { 
     printk("Kernel -> userspace copy failed!\n"); 
     return 0; 
    } 
    return output_str_size; 
} 

Несколько вещей, чтобы иметь в виду:

  • Обновить значение MAX_SIZE в соответствии с вашими потребностями. Если число становится действительно большим, вы можете подумать об использовании kmalloc вместо этого, чтобы получить память.
  • Это очень плохая практика кодирования для определения реализации функций в файлах .h, кроме встроенных функций.
  • Когда copy_from_user или copy_to_user сбой возвращается 0 вместо вывода strlen.

Вышеупомянутое является очень грубым вариантом реализации, вам также могут потребоваться дополнительные проверки для проверки переполнения буфера при печати строки с использованием sprintf.

+0

Большое вам спасибо. Это было так полезно :) – Krishna

Смежные вопросы