Linux Device Driver Tutorial Part 5 – Device File Creation

This article is a continuation of the  Series on Linux Device Driver and carries on the discussion on character drivers and their implementation. In this tutorial, we will discuss Device File Creation for Character Drivers.

Device File Creation for Character Drivers

In our last tutorial we have seen how to assign a major and minor number. But if you see there it will create a major and minor numbers. But I did not create any device files in /dev/ directory. The device file is important to communicate with the hardware. Let’s start our tutorial.

Device Files

The device file allows transparent communication between user-space applications and hardware.

They are not normal “files”, but look like files from the program’s point of view: you can read from them, write to them, mmap() onto them, and so forth. When you access such a device “file,” the kernel recognizes the I/O request and passes it a device driver, which performs some operation, such as reading data from a serial port or sending data to hardware.

Device files (although inappropriately named, we will continue to use this term) provide a convenient way to access system resources without requiring the application programmer to know how the underlying device works. Under Linux, as with most Unix systems, device drivers themselves are part of the kernel.

All device files are stored in /dev directory. Use ls command to browse the directory:

ls -l /dev/

Each device on the system should have a corresponding entry in /dev. For example, /dev/ttyS0 corresponds to the first serial port, known as COM1 under MS-DOS/dev/hda2 corresponds to the second partition on the first IDE drive. In fact, there should be entries in /dev for devices you do not have. The device files are generally created during system installation and include every possible device driver. They don’t necessarily correspond to the actual hardware on your system. There are a number of pseudo-devices in /dev that don’t correspond to any actual peripheral. For example, /dev/null acts as a byte sink; any write request to /dev/null will succeed, but the data are written will be ignored.

When using ls -l to list device files in /dev, you’ll see something like the following:

First of all, note that the first letter of the permissions field is denoted that driver type. Device files are denoted either by b, for block devices, or c, for character devices.

Also, note that the size field in the ls -l listing is replaced by two numbers, separated by a comma. The first value is the major device number and the second is the minor device number. This we have discussed in the previous tutorial.

Creating Device File

We can create a dive file in two ways.

  1. Manually
  2. Automatically

We will see one by one.

Manually Creating Device File

We can create the device file manually by using mknod.

mknod -m <permissions> <name> <device type> <major> <minor>

<name> – your device file name that should have a full path (/dev/name)

<device type> – Put c or b

c – Character Device

b – Block Device

<major> – major number of your driver

<minor> – minor number of your driver

-m <permissions> – optional argument that sets the permission bits of the new device file to permissions

Example:

sudo mknod -m 666 /dev/etx_device c 246 0

If you don’t want to give permission, You can also use chmod to set the permissions for a device file after creation.

Advantages

  • Anyone can create the device file using this method.
  • You can create the device file even before loading the driver.

Programming

I took this program from the previous tutorial. I’m going to create a device file manually for this driver.

  • Build the driver by using Makefile (sudo make)
  • Load the driver using sudo insmod
  • Check the device file using ls -l /dev/. By this time device file is not created for your driver.
  • Create a device file using mknod and then check using ls -l /dev/.

 

  • Now our device file got created and registered with a major number.
  • Unload the driver using sudo rmmod

Automatically Creating Device File

The automatic creation of device files can be handled with udev. Udev is the device manager for the Linux kernel that creates/removes device nodes in the /dev directory dynamically. Just follow the below steps.

  1. Include the header file linux/device.h and linux/kdev_t.h
  2. Create the struct Class
  3. Create Device with the class which is created by the above step

Create the class

This will create the struct class for our device driver. It will create a structure under/sys/class/.

struct class * class_create (struct module *owner, const char *name);

owner – pointer to the module that is to “own” this struct class

name – pointer to a string for the name of this class

This is used to create a struct class pointer that can then be used in calls to class_device_create.

Note, the pointer created here is to be destroyed when finished by making a call to class_destroy.

void class_destroy (struct class * cls);

Create Device

This function can be used by char device classes. A struct device will be created in sysfs, registered to the specified class.

struct device *device_create (struct *class, struct device *parent, dev_t dev, const char *fmt, ...);

class – pointer to the struct class that this device should be registered to

parent – pointer to the parent struct device of this new device, if any

devt – the dev_t for the char device to be added

fmtstring for the device’s name

… – variable arguments

A “dev” file will be created, showing the dev_t for the device, if the dev_t is not 0,0. If a pointer to a parent struct device is passed in, the newly created struct device will be a child of that device in sysfs. The pointer to the struct device will be returned from the call. Any further sysfs files that might be required can be created using this pointer.

Note, you can destroy the device using device_destroy().

void device_destroy (struct class * class, dev_t devt);

If you don’t understand please refer the below program, Then you will understand.

Programming

  • Build the driver by using Makefile (sudo make)
  • Load the driver using sudo insmod
  • Check the device file using ls -l /dev/ | grep "etx_device"

  • Unload the driver using sudo rmmod

By this time, we have created the device file using those methods mentioned above. So Using this device file we can communicate the hardware. In our next tutorial, we will show how to open that file, how to read that device file, how to write a device file, and how to close the device file. If you have any doubt, please comment below.

 

5 1 vote
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Anonymous
Anonymous
August 21, 2017 1:52 AM

In this post you have created a device file using mknod and assigned major number 246, but it is getting dynamicly allocating major and minor number in helloworld program. How the dynamically allocated hello world uses the major number 246 created by mknod for etx_device ?

Anonymous
Anonymous
August 21, 2017 1:54 AM

Does both the major number created by dynamic allocation and major number created by mknod for etx_device file are same?

Sana Srikar
Sana Srikar
September 2, 2018 9:09 PM

hi embedtronicx ,
General doubt on device_create() ,my question is little off the topic.
any known use case of struct device *parent feild in device_create() API ?
if any known use case could you please help me with it ?

5
0
Would love your thoughts, please comment.x
()
x
%d bloggers like this: