Skip to content
Rafael do Nascimento Pereira edited this page Feb 16, 2015 · 9 revisions

1 What is it for ?

This driver is a further development from the one driver. It implements additionally 2 features:

  • store (write) data (integer) provided from user space
  • implements basic concurrency

In other words, the user can set a desired value (integer) and more than one user space programm can read/write in a coherent way. In order to test this driver a user space programm was written additionally, where it can start n threads in parallel (default: 4) that read the driver value, increment it and write it back.

2 Looking at the code

A struct was created to gather all the related data structures:

struct intn2_dev {
	struct cdev    intn_cdev;
	struct class  *intn_class;
	struct device *intn_device;
	struct mutex   intn_mutex;
};

2.1 Common code

The necessary header are the same as in the intndriver.

2.2 User-space communication

We take care now the concurrency operations in the open and release functions, so we must deal with multiple user-space accesses. They are executed when the user-space invoke the openand close system calls respectively.

int intn2_release(struct inode *inode, struct file *filp)
{
	mutex_unlock(&intn2->intn2_mutex);
	return 0;
}

int intn2_open(struct inode *inode, struct file *filp)
{
	mutex_lock(&intn2->intn2_mutex);
	return 0;
}

Write: write data from the device.

ssize_t (*read)(struct file *f, char __user *u, size_t size, loff_t *l);
Parameters type Description
*f input pointer to the structure that represents the file to be open
*u input pointer to the buffer that stores data to be read from the device
size input number of bytes to be read
*l input pointer to the current reading position/offset
ssize_t return a non-negative return value represents the number of bytes successfully read, on failure a negative error code

The one_read implements this operation, returning only a "1" to user-space. In order to do so, the copy_to_userfunction is used. If an error occurs, an -EFAULT is returned to user space.

unsigned long copy_from_user(void __user *to, const void *from, unsigned long count);
Parameters type Description
*to output pointer to the buffer in kernel space
*from input pointer to the buffer holding the data in user space
count input number of bytes to be copied from user-space
unsigned long return returns zero on success or non-zero to indicate the number of bytes that weren't transferred

3 Executing the code

Run make and make test to compile the driver and the user space test program. Run sudo make ins or sudo insmod one.ko to insert the driver in the Linux Kernel memory space. Then take a look at the kernel log and you should see the following line:

Jun 16 21:09:19 localhost kernel: [41443.956311] intn<Major, Minor>: <248, 0>

and also run lsmod and the output should be like this:

% lsmod | grep intn
intn                    14724  0

To read from /dev/intn execute:

dd if=/dev/intn of=intn.txt bs=1 count=10

Open the intn.txt file in an editor capable of show the hexadecimal representation and this should be ten 1's:

01 01 01 01 01 01 01 01 01 01

The same result as the one driver. As we can run our test program:

./test_intn

TODO: finish this section

In the end remove the driver from the kernel using:

sudo rmmod intn.ko