Try with these changes, I've just added the changes:
Refactor LCG.C
so that the random number generator is a separate function and make sure this function is not static. You should also need to export this SYMBOL.
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);
This way, the function can be directly invoked by the the LCG module as well as from outside.
Now to invoke this function from your module my_dev, and to return the output, you need these changes:
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;
}
In my_dev.h
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;
}
Few things to keep in mind:
- Update the value of MAX_SIZE as per your needs. If the number gets really big, you could think of using kmalloc instead to get the memory.
- It is a really bad coding practice to define function implementations within .h files except for inline functions.
- When
copy_from_user
orcopy_to_user
fails return0
instead of the output fromstrlen
.
The above is just a very crude implementaiton, you might also need extra checks to check for buffer overflows when printing the string using sprintf.