Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
766 views
in Technique[技术] by (71.8m points)

c - how to use 'cat' in following simple device read program

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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!
";
  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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...