2
static ssize_t device_read (struct file* filp, char *bufStoreData, size_t bufCount, loff_t* curOffset)
{
    printk(KERN_INFO"reading from the device");
    ret = copy_to_user(bufStoreData,virtual_device.data,bufCount);
    return ret;
}
  1. does copy_to_user returns number of bytes remaining to read or number of bytes read?

  2. whats the use of bufcount if i am using cat

  3. if all the data is not read in single call how it can read the remaining data?Is this responsibility of application to issue system call again or the driver works automatically?

I need to understand this basic concept.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
mrigendra
  • 1,472
  • 3
  • 19
  • 33

2 Answers2

3

copy_to_user() returns the number of bytes that couldn't be copied to user space. If the complete buffer could be copied, it returns 0.

Normally, if !=0, means that there was some sort of memory problem (writting past a legal memory address), so these situations should be detected and reported to the user.

static ssize_t device_read (struct file* filp, char *bufStoreData, 
                            size_t bufCount, loff_t* curOffset)
{
  size_t bytes_to_copy;

  printk(KERN_INFO"reading from the device");

  /* do stuff to get device data into virtual_device.data . Also
     update virtual_device.datasize */

  bytes_to_copy = (virtual_device.datasize <= bufCount)? 
                             virtual_device.datasize : bufCount;
  /* note that I'm not using bufCount, but an hypothetical field in 
     virtual_device that gives me how much data the device has ready 
     for the user. I choose the lower of both */
  /* Also recall that if the number of bytes requested by the user is
     less than the number of bytes the device has generated, then the
     next read should return the remainder of the device data, so the
     driver should carry the count of how many bytes have been copied
     to the user and how many are left. This is not covered in this
     example. */

  ret = copy_to_user(bufStoreData,virtual_device.data, bytes_to_copy);
  if (ret != 0)
    return -EPERM; /* if copy was not successful, report it */
  return bytes_to_copy;
}

When the user issues ret = read (fd, buffer, sizebuff); it expects one of these things and should react accordingly:

  • ret is equal to sizebuff. That means that read could return all the data the user requested. Nothing else to do here.

  • ret is positive, but less than sizebuff. That means that the read gave the user some data, but not as much as he requested. The user process must re-issue the read syscall to retrieve the remaining data, if needed. Something like: ret = read (fd, buffer+ret, sizebuff-ret);

  • ret is 0. This means that the device has no more data to send. It's the EOF condition. User process should close the device.

  • ret is < 0. This is an error condition. User process must check errno and take appropiate measures.

Your device driver will have to return an appropiate value in device_read according to what happened to the device when it was read.

On the other hand, a process like cat expects to read as much as 4096 bytes per read call. If the device sends less than that, it will print the received data and will ask for more. cat will only stop if it receives a signal (Ctrl-C for example), or if a read call returns an unrecoverable error (such as ENODEVICE, which should be generated by your driver if such condition arises), or if reads 0 bytes (EOF condition).


A rather silly device that returns "Hello, world" to the user process. It employs some global data that must be reset in device_open function. Note that if several processes are going to use your device at the same time, these global data must be turned into instance data (using file->private_data). This device_read example shows how to deal with device buffers and user buffers, and how to keep track of bytes sent to the user, so the device never sends more data than it has, never sends more data than the user requests, and when the device runs out of data, it returns 0 to the user.

int curindx = 0; /* should be reset upon calling device_open */

static ssize_t device_read (struct file* filp, char *bufStoreData, 
                            size_t bufCount, loff_t* curOffset)
{
  size_t bytes_to_copy;
  char device_data[]="Hello, world!\n";
  size_t remaindersize;

  remaindersize = strlen(device_data) - curindx;
  bytes_to_copy = (remaindersize <= bufCount)? 
                             remaindersize : bufCount;
  ret = copy_to_user(bufStoreData,device_data+curindx, bytes_to_copy);
  if (ret != 0)
    return -EPERM; /* if copy was not successful, report it */
  curindx += bytes_to_copy;
  return bytes_to_copy;
}
mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
  • I've done what you said , but using cat /dev/my prints infinite amount of data from my device. I am not using application program here, just using cat to read. – mrigendra Dec 26 '13 at 11:52
  • Read the last paragraph of my answer. You need to send EOF from your device driver when it does not more data to transfer to user space. This usually means that you have to keep track of how many data the driver sent to the user. The next time read_device is called, check that, and if there's no more data to transfer, just return 0. – mcleod_ideafix Dec 26 '13 at 12:01
0

1) does copy_to_user returns number of bytes remaining to read or number of bytes read?

copy_to_user returns a number of bytes that could not be copied.

2) whats the use of bufcount if i am using cat

bufCount is a number of bytes user can read. In other words, it's a buffer size of user space application. I guess cat uses multiple of PAGE_SIZE for buffer size, actually you can check it yourself by adding printk to your device_read() function:

print(KERN_INFO "bufCount=%ld\n", bufCount);

3) if all the data is not read in single call how it can read the remaining data? Is this responsibility of application to issue system call again or the driver works automatically?

User space programs use read() system call to read data from files (including block and character devices) which returns 0 only if the end of file is reached. That's how they know when to stop. So, yes, it's responsibility of user-space program to read remaining data (if it needs to).

ssize_t ret;
...
while ((ret = read(fd, buf, bufsize)) > 0) {...};
if (ret < 0)
   error();

On the other hand, the responsibility of device driver is to correctly maintain offsets inside its internal structures and return values that make sense.

P/S: I'd recommend you to read a book "Linux device drivers" which is freely available in internet (http://lwn.net/Kernel/LDD3/) and touches these topics in details.

Dan Kruchinin
  • 2,945
  • 1
  • 17
  • 21