$24
In Assignment 5, you are required to make a prime device in Linux, and implement file operations in kernel module to control this device.
Outline:
We will make a device under /dev by mknod command. This device can find n-th prime number.
You will implement file operations in a kernel module to control this device. And implement ioctl function to change the device configuration.
Simulate registers on device by allocating a memory region.
Global View:
Specification:
Register character device and make it live:
◦ You can use alloc_chrdev_region() to allocate a range of char device numbers.
◦ And get available number by MAJOR() and MINOR() macro.
◦ In your kernel module, you could allocate a cdev structure by
cdev_alloc() and initialize it by cdev_init() to bind cdev file_operations.
◦ Add a device by cdev_add() to make it live.
Test program and printk:
◦ Before write module, we need to know what this module do. So we provide a test program to test this device.
◦ You can modify test program and test your module.
◦ We will check with our test cases.
◦ In kernel module, you need to write printk to help debug and use dmesg command to show message.
◦ To help demo program, your printk must be started with “OS_AS5: function_name: message”.
File operations:
◦ You should write a struct file_operations to map the operations to functions in this module.
◦ And use cdev_init() at module init to bind cdev and file_ operations.
ioctl:
◦ In Linux, device provide user mode program ioctl function to change the device configuration.
◦ ioctl define many types of operation with switch case to do coordinated work.
◦ And ioctl use mask to get value from these operation label.
• Here we provide “ioc_hw5.h” to define 6 works.
1) (HW5_IOC_SETSTUID) Set student ID: printk your student ID
2) (HW5_IOCSETRWOK) Set if RW OK: printk OK if you complete R/W function
3) (HW5_IOCSETIOCOK) Set if ioctl OK: printk OK if you complete ioctl function
4) (HW5_IOCSETIRQOK) Set if IRQ OK: printk OK if you complete bonus
5) (HW5_IOCSETBLOCK) Set blocking or non-blocking: set write function mode
6) (HW5_IOCWAITREADABLE) Wait if readable now (synchronize function): used before read to confirm it can read answer now when use non-blocking write mode.
• ioctl lables defined in “ioc_hw5.h”
“_IOW(type, nr, size )” is used for an ioctl to write data to the driver. It is to generate command numbers.
◦ Demo for ioctl call in user mode: ioctl(fd, HW5_IOCSETBLOCK, &ret)
▪ fd: an open file descriptor
▪ HW5_IOCSETBLOCK: device-dependent request code.
▪ &ret: an untyped pointer to memory
write:
◦ Define a data struct that is passed in write function.
◦ a is operator: '+', '-', '*', '/', or 'p' (‘p’ means find prime number)
◦ b is operand 1
◦ c is operand 2
◦ Use INIT_WORK() and schedule_work() to queue work to system queue.
Find Prime operation:
◦ It finds c-th prime number bigger than b.
(e.g, “1 p 3” means to find 3rd prime number which is bigger than 1, then it should be 5.)
◦ And you will feel the I/O latency when execute test program for “100 p 10000” and “100 p 20000”.
◦ We will check your blocking and non-blocking IO by observing the delay of the message printed by test program.
◦ R/W function packaged in arithmetic function in user mode program. arithmetic(fd, 'p', 100, 10000);
▪ fd: an open file descriptor
▪ p: operator
▪ 100: operand1
▪ 10000: operand2
Work Routine:
◦ The work you enqueued should be written in a work routine function in module.
◦ These work will be processed by another kernel thread.
◦ computation is written in a work routine in module
Blocking and Non-Blocking IO:
◦ The test program can use ioctl to set blocking or non-blocking.
◦ Your write function in module can be blocking or non-blocking.
◦ Blocking write need to wait computation completed.
◦ Non-blocking write just return after queuing work.
◦ Read function only has blocking, because not queuing work.
Blocking Write:
◦ In test program, we just need a write function.
◦ Do not need another synchronize function.
◦ But block when writing.
• Blocking write in test program:
Non- Blocking Write:
◦ In test program, we can do something after write function.
◦ Write function return after queueing work, it is non-blocking.
◦ But need another synchronize function to wait work completed.
◦ Non-blocking write in test program:
Interrupt driven IO:
◦ When implementing blocking write and synchronize function, they use a while loop busy waiting the interrupt.
◦ You can use a variable to simulate the interrupt.
◦ At the final of the work routine function, change this variable as triggering the interrupt.
◦ And then, blocking write and synchronize function can exit the while loop.
DMA Buffer:
◦ To simulate register and memory on device, you need to kmalloc a dma buffer.
◦ This buffer is as I/O port mapping in main memory.
◦ What device do is written in work routine function. This function get data from this buffer.
◦ Defined value written into dma buffer:
In and out functions:
◦ You need to implement in & out function to access dma buffer just like physical device.
◦ out function is used to output data to dma buffer.
◦ in function is used to input data from dma buffer.
◦ The 6 in & out functions are definded in module to operate dma_buf: ('c', 's' and 'i' maps with data type ‘char’, ‘short’ and ‘int’)
◦ Demo usage of in and out functions: myouti(value,
DMAIOCOKADDR)
▪ value: data you want to write into dma_buffer
▪ DMAIOCOKADDR: port in dma_buffer
Data transfer between kernel and user space:
• get_user(x, ptr)
◦ Get a simple variable from user space.
◦ x: Variable to store result.
◦ ptr: Source address, in user space.
• put_user(x, ptr)
◦ Write a simple value into user space.
◦ x: Value to copy to user space.
◦ ptr: Destination address, in user space.
Template structure:
Makefile is provided:
◦ Command: make
(It will firstly build your main.c as kernel module “mydev.ko”, insert “mydev.ko”, and then build “test.c” as executable file “test”.)
◦ Command: make clean
(It will remove “mydev.ko” and use “dmesg” to list kernel logs that includes keyword “OS_AS5”)
“mknod” script is provided:
▪ Script
▪ In mknod command: c means character device. Followed two number are Major and Minor number to specify device.
▪ You can get available number by MAJOR() and MINOR() macro after alloc_chrdev_region() in module_init() function.
▪ Demo of how to use mknod script: (Refer to Tutorial_11 Slide 3 to 6)
Steps you need to run the template:
◦ Run “make”
◦ Run “dmesg” to check available device number
◦ Run “sudo ./mkdev.sh MAJOR MINOR” to build file node (MAJOR and
MINOR are the available device number checked from previous step)
◦ Run “./test” to start testing
◦ Run “make clean” to remove the module and check the messages
◦ Run “sudo ./rmdev.sh” to remove the file node
◦ You will get output:
You should complete module init and exit functions:
Implement read/write/ioctl operations and arithmetic routine:
Function Requirements (90 points):
Register a character device when module initialized. (5 points) Initialized a cdev and add it to make it alive. (5 points)
Allocate DMA buffer. (5 points) Allocate work routine. (5 points)
Implement read operation for your device. (10 points) Implement write operation for your device. (20 points) Implement ioctl setting for your device. (15 points)
Implement arithmetic routine for your device. (10 points) Complete module exit functions. (5 points)
Update your student ID in test case and make it be print in kernel ioctl. (5 points)
Run test cases to check write and read operations. (5 points)
Demo Output:
Test case: (: '+', '-', '*', '/' is for your testing, we will mainly test ‘p’ operation)
User mode output:
Kernel mode output:
Steps for internal executions:
◦ find major and minor number
◦ allocate DMA buffer
◦ ioctl print set and get value
◦ write to queue work
◦ arithmetic routine to compute answer
◦ read to get answer
◦ free DMA buffer
◦ unregister device
Bonus (10 points)
Global View (Bonus)
Count the interrupt times of input device like keyboard. Hint: watch -n 1 cat /proc/interrupts
Use request_irq() in module_init to add an ISR into an IRQ number's action list.
And free_irq() when module_ exit, otherwise kernel panic. Please define IRQ_NUM at head of code.
Demo output:
Report (10 points)
Write a report (PDF) for your assignment, which should include main information as below:
How did you design your program?
What problems you met in this assignment and what is your solution? The steps to execute your program.
Screenshot of your program output.
What did you learn from this assignment?
Submission
Please submit the file as package with directory structure as below:
CSC3150_Assignment_5_Student ID
• Source
o main.c (if you complete bonus, submit only one “main.c”) o test.c
o ioc_hw5.h o makefile o mkdev.sh o rmdev.sh
◦ Report(PDF)
Due date: End (23:59) of 06 Dec, 2020
Grading rules
Completion
Marks
Report
10 points
Bonus
10 points
Completed with
80
~ 90
good quality
Completed accurately
80
+
Fully Submitted
60
+
(compile
successfully)
Partial submitted
0~60
No submission
0
Late submission
Not allowed