Device drivers programming in linux

Linux Device Driver Tutorial Programming – Linux Device Driver Tutorial Part 7

This article is a continuation of the Series on Linux Device Drivers and carries the discussion on character drivers and their implementation. The aim of this series is to provide easy and practical examples that anyone can understand. This is the simple Linux Device Driver Programming Tutorial – Linux Device Driver Tutorial Part 7.

From our previous tutorials, we know about major, and minor numbers, device files, and file operations of device drivers using the dummy drivers. But today we are going to write a real driver without hardware.

Prerequisites

To continue with this tutorial, you must have set up the Ubuntu or Raspberry Pi or Beaglebone. If you aren’t set up anything yet, we suggest you to set up the boards that you have using the below-given tutorials.

You can find a video explanation of this tutorial here. You can also find all the Linux device driver’s video playlists here.

Linux Device Driver Programming Tutorial

Introduction

We already know that in Linux everything is a File. So in this tutorial, we are going to develop two applications.

The user Program will communicate with the kernel space program using the device file. Lets Start.

Kernel Space Program (Device Driver)

We already know about major, and minor numbers, device files, and file operations of the device drivers. If you don’t know please visit our previous tutorials. Now we are going to discuss more file operations in the device driver. Basically, there are four functions in the device driver.

Читайте также:  Linux segmentation fault dump

Now we will see one by one of these functions. Before that, I will explain the concept of this driver.

Concept

Using this driver we can send strings or data to the kernel device driver using the write function. It will store that string in the kernel space. Then when I read the device file, it will send the data which is written by write by function to the userspace application.

Functions used in this driver

kmalloc()

We will see the memory allocation methods available in the kernel, in our next tutorials. But now we will use only the kmalloc in this tutorial.

kmalloc function is used to allocate the memory in kernel space. This is like a malloc() function in userspace. The function is fast (unless it blocks) and doesn’t clear the memory it obtains. The allocated region still holds its previous content. The allocated region is also contiguous in physical memory.

#include void *kmalloc(size_t size, gfp_t flags);

size how many bytes of memory are required.

flags the type of memory to allocate.

The flags argument may be one of:

GFP_USER – Allocate memory on behalf of the user. May sleep.

GFP_KERNEL – Allocate normal kernel ram. May sleep.

GFP_ATOMIC – Allocation will not sleep. May use emergency pools. For example, use this inside interrupt handler.

GFP_HIGHUSER – Allocate pages from high memory.

GFP_NOIO – Do not do any I/O at all while trying to get memory.

GFP_NOFS – Do not make any fs calls while trying to get memory.

GFP_NOWAIT – Allocation will not sleep.

__GFP_THISNODE – Allocate node-local memory only.

Читайте также:  Драйвера принтеров astra linux

GFP_DMA – Allocation is suitable for DMA. Should only be used for kmalloc caches. Otherwise, use a slab created with SLAB_DMA.

Also, it is possible to set different flags by OR’ing in one or more of the following additional flags :

__GFP_COLD – Request cache-cold pages instead of trying to return cache-warm pages.

__GFP_HIGH – This allocation has high priority and may use emergency pools.

__GFP_NOFAIL – Indicate that this allocation is in no way allowed to fail (think twice before using).

__GFP_NORETRY – If memory is not immediately available, then give up at once.

__GFP_NOWARN – If allocation fails, don’t issue any warnings.

__GFP_REPEAT – If allocation fails initially, try once more before failing.

There are other flags available as well, but these are not intended for general use, and so are not documented here. For a full list of potential flags, always refer to linux/gfp.h .

kfree()

This is like a free() function in the userspace. This is used to free the previously allocated memory.

void kfree(const void *objp)

*objp – pointer returned by kmalloc

copy_from_user()

This function is used to Copy a block of data from user space (Copy data from user space to kernel space).

unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);

to – Destination address, in the kernel space

from – The source address in the user space

n – Number of bytes to copy

Returns number of bytes that could not be copied. On success, this will be zero.

copy_to_user()

This function is used to Copy a block of data into userspace (Copy data from kernel space to user space).

unsigned long copy_to_user(const void __user *to, const void *from, unsigned long n);

to – Destination address, in the user space

Читайте также:  Linux сколько всего запущено процессов

from – The source address in the kernel space

n – Number of bytes to copy

Returns number of bytes that could not be copied. On success, this will be zero.

Open()

This function is called first, whenever we are opening the device file. In this function, I am going to allocate the memory using kmalloc . In the userspace application, you can use open() system call to open the device file.

static int etx_open(struct inode *inode, struct file *file) < /*Creating Physical memory*/ if((kernel_buffer = kmalloc(mem_size , GFP_KERNEL)) == 0)< printk(KERN_INFO "Cannot allocate memory in kernel\n"); return -1; >printk(KERN_INFO "Device File Opened. \n"); return 0; >

write()

When writing the data to the device file it will call this write function. Here I will copy the data from user space to kernel space using copy_from_user() function. In the userspace application, you can use write() system call to write any data the device file.

static ssize_t etx_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)

read()

When we read the device file it will call this function. In this function, I used copy_to_user() . This function is used to copy the data to the userspace application. In the userspace application, you can use read() system call to read the data from the device file.

static ssize_t etx_read(struct file *filp, char __user *buf, size_t len, loff_t *off)

close()

When we close the device file that will call this function. Here I will free the memory that is allocated by kmalloc using kfree() . In the userspace application, you can use close() system call to close the device file.

static int etx_release(struct inode *inode, struct file *file)

Linux Device Driver Tutorial Programming – Full Driver Code

[Get the source code from GitHub]

Источник

Оцените статью
Adblock
detector