How to Implement the Write File Operation Method in a Linux Device Driver

Beaglebone black board






In this article, we show how to implement the write file operation method in a linux device driver.

So the write file operation method originates from the write user system call.

The write file operation method writes data from the user space and transfers this data to the kernel space.

In our example in this code, our character device represents a memory array, which is a contiguous memory location. It can be seen as a device memory buffer.

So when a write user system call is issued to the device file, we transfer data from our user buffer to the device memory buffer.

The write method implementation is done by taking our write file operation method and carrying out a few steps.

The general format for the write file operation method is shown below. copy_from_user()





Implementing the write method is very similar to implementing the read method.

It's just in reverse. Instead of reading data, we are writing data. And the data from the user buffer is written to the kernel space.

One of the first things that we have to do is check the user request 'count' value against the memory size of the device.

In our example, we are dealing with a memory array that is 512 bytes.

This means that there can only be 512 bytes written to it. This goes from a starting position of 0 for the first byte and 511 for the last byte.

The file position represents the 'cursor', where the write file operation will start from.

If the file position plus the count is greater than the device memory size, then we have to readjust the count. To set the count to 0, we readjust the count to the memory size of the device - the file position. This ensures that we write to the file from the beginning of the file.

Next, we copy the 'count' number of bytes from the user buffer to the device buffer. This is done using the copy_from_user() function. We will go over the parameters of this function later.

Next, we update the file position, meaning we set it manually to where it is now that has copied the 'count' number of bytes.

Then, we return the number of bytes successfully written or an error code if there is some type of error in the process.

If the file position is at the end of the file, we simply return 0.

And this would be our write file operation method to write to a device.

The general format for the copy_from_user() function is shown below.





So the copy_from_user() function takes in 3 parameters.

The first parameter is the destination address, which is the address of the device memory buffer in the kernel space. After all, the user is writing the data to the device. So the destination must be the device memory buffer in the kernel space. So the *to is the pointer to the device memory buffer.

The second parameter is the source address, which is the address of the user buffer in the kernel space. The write file operation method writes data to the device memory buffer in the kernel space from the user buffer.

The third parameter, n, is the number of bytes that is to be written to the device memory buffer in the kernel space.

This function returns 0 on success or the number of bytes that could not be copied. Therefore, we must implement an if statement to check what is returned. If there is a return value other than 0, this means that there is an error. We return the error of -EFAULT.

So let's now go through the complete code of this write file operation, which is shown below.





So let's now go through this code.

So we have our write method, which is called pcd_write(). You can call this function anything appropriate for your device.

The input parameters to this function is standard.

*filp is a pointer to the file that we are reading.

*buff is a pointer to the user buffer, which reads in the data from the device memory from the kernel space.

count is the number of bytes that we want to read.

*f_pos is a pointer to the file position of the cursor.

So the pr_info statements are optional. You can put them in your code for debugging purposes.

So the first thing we do in our code is have an if statement that checks the position of the file cursor. If the value is greater than DEV_MEM_SIZE, then we set the value equal to, count= DEV_MEM_SIZE - *f_pos;

Different from the read file operation method, with the write method, we cannot count of 0. If we have a count value of 0, this creates an error situation, because this signifies that there is no space left in the file to write any bytes. This is why we check to see if count is 0; if it is, we return the error of -ENOMEM (which signifies there is no memory left in our device memory buffer to write any bytes).

We then use the copy_from_user() function to write data to the device.

buff is where the source of the data that is to be written.

count is how many bytes are to be written.

If the value is greater than 0, we return an error.

We then update the current file position using the statement, *f_pos += count;

We then return count, which will show how many bytes were written.

The full entire code for this project is shown below.





So when you build this code, you should see that you do not get any errors, such as that shown below.


Building the write file operation method of a linux device driver


Once you have this, you can test this write method out.

So this is how to implement the write file operation method in a linux device driver.



Related Resources





HTML Comment Box is loading comments...