2

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=&param[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.

Kiran
  • 20,167
  • 11
  • 67
  • 99
gorgoth
  • 123
  • 1
  • 8
  • I dont understand why `3500*7*4*2`. Why `*2` in your `read`?? – Pavan Manjunath Mar 21 '12 at 18:10
  • The buffer is being filled from the 2 original arrays, each 3500*7*4 bytes in size, (at least that's what I'm trying to do). – gorgoth Mar 22 '12 at 11:26
  • Just a note, most of the numbers in my actual code, like the `3500`,`7`,`4`,and `2` are handled by `#define`s, but I put in the literal numbers above to _try_ to help communicate what I'm trying to do more clearly, (not generally a strong point of mine)... – gorgoth Mar 22 '12 at 20:00
  • Update, after a bit more troubleshooting, I discovered that the output index seems to stop at 8192 then it begins writing back at 0, is it possible that the math I do to calculate write index locations is cast to a smaller data type? – gorgoth Jul 17 '12 at 19:33

1 Answers1

0

You can (should) avoid doing reads by mmaping the arrays to userspace process' address space with mmap. See the following example:

http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-8.html

moorray
  • 577
  • 3
  • 9
  • Thanks for the advice! I'm checking it out right now. I'm new to kernel development and I can use all the advice I can get. – gorgoth May 18 '12 at 01:07