I've searched on this a good deal, though I definitely may have missed something, and I'm coming from reading the http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html and this http://www.amazon.com/Essential-Device-Drivers-Sreekrishnan-Venkateswaran/dp/0132396556, but I'm having trouble reading out large arrays I've created in my linux kernel module ~200kB a piece. I'm developing on the ARM based ti-omap3530. I allocate the arrays like this:
static unsigned int* captured_params;
static unsigned int* time_params;
captured_params=vmalloc(3500*7*sizeof(unsigned int));
time_params=vmalloc(3500*7*sizeof(unsigned int));
My read function looks like this (I realize that I'm not doing this probably the best way):
ssize_t tgdev_read(struct file *file, char *buf, size_t count, loff_t *ppos){
/*This file will expect reads in 8-byte chunks, 4 for the data parameter
and 4 for the time parameter*/
struct tg_dev *tg_devp = file->private_data;
unsigned int num_pairs=sample_counter;
static unsigned int pairs_out=0;
static unsigned int sent_successfully=0;
unsigned int* param_ptr;
unsigned int* time_ptr;
pairs_out=(tg_devp->current_pointer)/8;
num_pairs=sample_counter;
if(pairs_out==num_pairs){//all returned end of file
return 0; //EOF
}
while((pairs_out*8)<count){
//update data pointers
time_ptr=&time_params[pairs_out];
param_ptr=&captured_params[pairs_out];
//send user time first
sent_successfully=copy_to_user(&buf[tg_devp->current_pointer],time_ptr,4);
//send param value for that time
sent_successfully=copy_to_user(&buf[tg_devp->current_pointer+4],param_ptr,4);
//update number of pairs sent to user
pairs_out+=1;
//update file_pointer
tg_devp->current_pointer +=8;
}
return pairs_out*8;
}
And I read it with a user space program like this:
int fp;
char* mode="r";
char* fname="/dev/my_device";
unsigned int param[3500*7]={0};
unsigned int time[3500*7]={0};
unsigned int* param_ptr;
unsigned int* time_ptr;
char buff[3500*7*4*2];
int i=0;
int rc=0;
int completed_reads;
fp=open(fname,O_RDONLY);
if(fp<0){
printf("failed to open file EXITING\n");
return 1;
}
rc=read(fp,buff,3500*7*4*2);
completed_reads=(rc-rc%8)/8;
printf("rc=%i cr=%i\n",rc,completed_reads);
for(i=0;i<completed_reads;i++){
param_ptr=¶m[i];
time_ptr=&time[i];
memcpy(param_ptr,&buff[i*8],4);
memcpy(time_ptr,&buff[i*8+4],4);
printf("[%i]%u,%u\n",i,param[i],time[i]);
}
close(fp);
The userspace read always reports reading the correct number of bytes, but I don't get the right data.
This solution seems to work fine if I replace the 3500s above with something smaller (up to 1000 behaves just fine), but above that I get strange behavior where the array I read out zero pads the last N of each array (same number of elements at the same point in each of the 2 arrays) and starts late in the series e.g. time/param[0]= some values much farther down the original arrays I wanted to read out.
I'm thinking this is because I don't understand the memory handling well enough, but I don't know how to make this do what I want to, which is store these data arrays in the module until I want to read them out into user space. Any suggestions or ideas where I'm going wrong would be greatly appreciated.
Thanks in advance for your time, efforts and patience in my regard.