CSC3150 Assignment 1 to 5 solutions

$120.00

Original Work ?

Download Details:

  • Name: Assignments-muxyj9.zip
  • Type: zip
  • Size: 34.46 MB

Category: You will Instantly receive a download link upon Payment||Click Original Work Button for Custom work

Description

5/5 - (1 vote)

CSC3150 Assignment 1

Task 1 (30 points)
In this task, you should write a program ( program1.c ) that implement the functions below:
In user mode, fork a child process to execute the test program. (10 points)
When child process finish execution, the parent process will receive the SIGCHLD signal by
wait() function. (5 points)
There are 15 test programs provided. 1 is for normal termination, and the rest are exception
cases. Please use these test programs as your executing programs.
The termination information of child process should be print out. If normal termination, print
normal termination and exit status. If not, print out how did the child process terminates and
what signal was raised in child process. (15 points)
The main flow chart for Task 1 is:
Demo outputs:
Demo output for normal termination:
Demo output for hangup:
Demo output for stopped:
Task 2 (60 points)
In this task, a template (β€œprogram2.c”) is provided. Within the template, please implement the
functions below:
main@ubuntu:~/Desktop/Assignment_1_example/source/program1$ ./program1
./normal
Process start to fork
I’m the Parent Process, my pid = 4903
I’m the Child Process, my pid = 4904
Child process start to execute test program:
————CHILD PROCESS START————
This is the normal program
————CHILD PROCESS END————
Parent process receiving the SIGCHLD signal
Normal termination with EXIT STATUS = 0
main@ubuntu:~/Desktop/Assignment_1_example/source/program1$ ./program1
./hangup
Process start to fork
I’m the Parent Process, my pid = 4908
I’m the Child Process, my pid = 4909
Child process start to execute test program:
————CHILD PROCESS START————
This is the SIGHUP program
Parent process receiving the SIGCHLD signal
child process get SIGHUP signal
child process is hung up
CHILD EXECUTION FAILED
main@ubuntu:~/Desktop/Assignment_1_example/source/program1$ ./program1
./stop
Process start to fork
I’m the Parent Process, my pid = 4931
I’m the Child Process, my pid = 4932
Child process start to execute test program:
————CHILD PROCESS START————
This is the SIGSTOP program
Parent process receiveing the SIGCHLD signal
child prcess get SIGSTOP signal
child process stopped
CHILD PROCESS STOPPED
When program2.ko being initialized, create a kernel thread and run my_fork function. (10
points)
Within my_fork, fork a process to execute the test program. (10 points)
The parent process will wait until child process terminates. (10 points)
Print out the process id for both parent and child process. (5 points)
Within this test program, it will raise signal. The signal could be caught and related message
should be printed out in kernel log. (10 points)
All 15 signals from Tasks 1 should be tested again in Task 2.
Follow the hints below to implement your function. If the function is non-static, you should
firstly export this symbol so that it could be used in your own kernel module. After that, you
should compile the kernel source code and install it. (Kernel compile: 15 points)
Hints:
Use β€œ_do_fork” to fork a new process. (/kernel/fork.c)
Use β€œdo_execve” to execute the test program. (/fs/exec.c)
Use β€œgetname” to get filename. (/fs/namei.c)
Use β€œdo_wait” to wait for child process’ termination status. (/kernel/exit.c)
The main flow chart for Task 2 is:
Demo output:
Bonus Task (10 pionts)
In this task, you should create an executable file named β€œmyfork” to implement the functions
below:
Execute β€œ./myfork test_program” will show the signal message that child process executes
test_program. (3 points)
We can add multiple executable files as the argument of myfork, like β€œ./myfork
test_program1 test_program2 test_program3”. From second argument, the queue indicates
the relationship of parent and child. The proceeding one is parent, and the tailing one is
child. For example: test_program_1 is parent of test_program_2, and test_program_2 is the
parent of test_program_3. (3 points)
Print out a process tree, which can indicate the relationship of the test programs.
For example: 1 -> 2 -> 3 (1/2/3 is the process ID) (4 points)
Demo output:
Report (10 points)
Write a report for your assignment, which should include main information as below:
[ 3769.385776] [program2] : module_init
[ 3769.385777] [program2] : module_init create kthread start
[ 3769.385777] [program2] : module_init kthread start
[ 3769.389787] [program2] : The child process has pid = 2914
[ 3769.389793] [program2] : This is the parent process, pid = 2912
[ 3769.391602] [program2] : child process
[ 3769.391604] [program2] : get SIGTERM signal
[ 3769.391605] [program2] : child process terminated
[ 3769.391605] [program2] : The return signal is 15
[ 3773.346070] [program2] : module_exit./my
main@ubuntu:~/Desktop/Assignment_1_117010033/source/bonus$ ./myfork hangup
normal8 alarm
————CHILD PROCESS START————
This is the SIGALRM program
This is normal8 program
————CHILD PROCESS START————
This is the SIGHUP program

Process tree: 5712->5713->5714->5715
Child process 5715 of parent process 5714 is terminated by signal 14 (Alarm
clock)
Child process 5714 of parent process 5713 terminated normally with exit code 0
Child process 5713 of parent process 5712 is terminated by signal 1 (Hangup)
Myfork process (5712) terminated normally
Completion Marks
Bonus 10 points
Report 10 points
Completed with good quality 80 ~ 90
Completed accurately 80 +
Fully Submitted (compile successfully) 60 +
Partial submitted 0 ~ 60
No submission 0
Late submission Not allowed
Your name and student id.
How did you design your program?
The environment of running your program (e.g., version of OS and kernel).
The steps to execute your program.
Screenshot of your program output.
What did you learn from the tasks?
Grading rules
Here is a sample grading scheme. Differ from the points specified above, this is the general guide
when TA’s grading.

CSC3150 Assignment 2

In Assignment 2, you are required to complete the multithread program to implement the game β€œFrog crosses river”.
Game rules:
A river has logs floating on it, and a frog must cross the river by jumping on the logs as they pass by.
Objects:
Log: =================
Frog: 0
River bank: |||||||||||||||||||||
When the game starts, the frog stands in the middle of bottom bank of river. The user can control the frog
jumps by keyboards. The logs will move from left to right or right to left staggerly. Please take care of the edge
cases.
W: UP
S: Down
A: Left
D: Right
Q: Quit the game
You will win if the frog jumps to the other bank of river successfully.
You will lose if the frog lands in the river, or reaches the left/right side of the river.
Please note that this is a game. If the player suffers from extereme difficulty, high latency, and other
unexpected situations for a game, your grade will suffer as well.
Function Requirements (90 points):
To run the template, you will see the frog stands in the middle at bottom bank of river. There are 9 blank rows
which means the river. Compile the program to see the static output. (5 points)
You should complete the function named β€œlogs_move” to let the logs can move staggerly from left to right or
from right to left. (20 points)
You should create pthread and use mutex lock for logs and frog movement control. (30 points)
β€œkbhit” function is provided for keyboard capture. You should complete the jump rules for keyboard actions.
And the frogΚΌs position should be updated when keyboard hits. (15 points)
When the logs are moving, the program should be able to judge the game status (win, lost or quit). Print out the
message for user whether he/she wins or lost the game. (15 points)
If the user quits the game, print the message. (5 points)
Demo Output
Demo output for user wins the game
You win the game!!
main@ubuntu:~/Desktop/Assignment_2_example/source$
Demo output for user loses the game:
You lose the game!!
main@ubuntu:~/Desktop/Assignment_2_example/source$
Demo output for user quits the game:
You exit the game.
main@ubuntu:~/Desktop/Assignment_2_example/source$
Bonus Task (10 pionts)
You have to implement a graphical output of your river and frog game. (5 points)
You can use any library you like to show your graphical output
The length of log must be different by random generating. (2 points)
You need to design a slide bar to adjust the speed of floating logs. (3 points)
Report (10 points)
Write a report for your assignment, which should include main information as below:
Your name and student id.
How did you design your program?
The environment of running your program. (E.g., version of OS and kernel)
The steps to execute your program.
Screenshot of your program output.
What did you learn from the tasks?
Grading rules
Here is a sample grading scheme. Different from the points specified above, this is the general guide when TA’s
grading.
Completion Marks
Bonus 10 points
Report 10 points
Completed with good quality 80 ~ 90
Completed accurately 80 +
Fully Submitted (compile successfully) 60 +
Partial submitted 0 ~ 60
No submission 0
C
o
m
ple
tio
n
M
a
r
k
s
L
a
t
e
s
u
b
mis
sio
n
N
o
t
allo
w
e
d

CSC3150 Assignment 3

In Assignment 3, you are required to simulate a mechanism of virtual memory via GPU’s
memory.
Background:
β€’ Virtual memory is a technique that allows the execution of processes that are
not completely in memory. One major advantage of this scheme is that programs
can be larger than physical memory.
β€’ In this project, you should implement simple virtual memory in a kernel function
of GPU that have single thread, limit shared memory and global memory.
β€’ We use CUDA API to access GPU. CUDA (Compute Unified Device Architecture) is
a parallel computing platform and programming model.
β€’ We don’t consider any parallel computing technique in this project, only use
single thread to serial access that let us focus our virtual memory
implementation.
β€’ There are many kinds of memory in CUDA GPU, we only introduce two memories
(global memory and shared memory) which relate to our project.
β€’ Global memory
– Typically implemented in DRAM
– High access latency: 400-800 cycles
β€’ Shared memory
– Extremely fast
– Configurable cache
– Memory size is small (16 or 48 KB)
The GPU Virtual Memory we need to design:
β€’ Because the shared memory in GPU with small size and low latency access, we
take the shared memory as the traditional CPU physical memory.
β€’ Take the global memory as the disk storage (secondary memory).
β€’ In CUDA, the function executed on GPU that defined by programmer, is called
kernel function.
β€’ A kernel function would no longer be constrained by the amount of shared
memory that is available. Users would be able to write kernel functions for an
extremely large virtual address space, simplifying the programming task.
β€’ Implement a paging system with swapping where the thread access data in
shared memory and retrieves data from global memory (secondary memory).
β€’ We only implement the data swap when page fault occurs (not in the instruction
level).
Specification of the GPU Virtual Memory we designed:
β€’ Secondary memory (global memory)
– 128KB (131072 bytes)
β€’ Physical memory (share memory)
– 48KB (32768 bytes)
. 32KB for data access
. 16KB for page table setting β€’
Memory replacement policy for page fault:
– If shared memory space is available, place data to the available page,
otherwise, replace the LRU set. Pick the least indexed set to be the victim
page in case of tie.
β€’ We have to map virtual address (VA) to physical address (PA).
β€’ The valid bit of each page table block is initialized as false before first data access
in shared memory.
β€’ Page size
– 32 bytes
β€’ Page table entries
– 1024 (32KB / 32 bytes)
Template structure:
β€’ At first, load the binary file, named β€œdata.bin” to input buffer before kernel
launch and return the size of input buffer: input_size.
β€’ Launch to GPU kernel with single thread, and dynamically allocate 16KB of share
memory, which will be used for variables declared as β€œextern __shared__”
β€’ Initialize the virtual memory.
β€’ Initialize the page table
(Considering the page entries is limited here, we’re using invert page table).
β€’ Under vm_write, you should implement the function to write data into vm
buffer.
β€’ Under vm_read, you should implement the function to read data from vm
buffer.
β€’ Under vm_snapshot, together with vm_read, you should implement the
program to load the elements of vm buffer (in shared memory, as physical
memory) to results buffer (in global memory).
β€’ For user_program (operations on vm_read/vm_write/vm_snapshot), you should
strictly follow the name and input parameters as:
– user_program(VirtualMemory *vm, uchar *input,
uchar *results, int input_size)
We will replace user_program for testing, please do not change any symbol of
these parameters.
β€’ Count the page fault number when executing paging replacement.
β€’ In Host, dump the contents of binary file into β€œsnapshot.bin”.
β€’ Print out page fault number when the program finish execution.
Functional Requirements (90 points):
β€’ Implement vm_write to write data to vm buffer (shared memory, as physical
memory) (10 points)
β€’ Implement vm_read to read data from vm buffer (shared memory, as physical
memory) (10 points)
β€’ Implement vm_snapshot together with vm_read to load the elements of vm
buffer (in shared memory, as physical memory) to results buffer (in global
memory, as secondary storage). (10 points)
β€’ Use provided user program to test memory management. (5 points)
β€’ When swapping memory, you need to implement with LRU paging algorithm. (40
points)
Notes: In tutorial we may discuss multiple ways of algorithm to implement the paging,
some of them are complicated but somehow efficient, so the way you choose to implement will to some
extent affect you score.
β€’ Print out correct page fault number. (5 points)
β€’ Correctly dump the contents to β€œsnapshot.bin”. (10 points)
Bonus (15 points)
Background:
β€’ We used only one page-table in basic task, if we want to launch multiple threads
and each thread use the mechanism of paging, we should design a new page
table for managing multiple threads.
β€’ Usually, each thread has an associated page-table, but we don’t have enough
memory size (shared memory) to setup.
β€’ To solve this problem, we can use an inverted page table (refers to Chapter 8).
Requirement:
β€’ Basing on Assignment 3, launch 4 threads in kernel function, all threads
concurrently execute it. (2 point)
β€’ To avoid the race condition, threads execute vm_read() / vm_write() should be a
non-preemptive priority scheduling, the priority of threads should be as:
Thread 0 > Thread 1 > Thread 2 > Thread 3.
Maintain the scheduling when operating on vm_read() / vm_write() /
vm_snapshot(). (5 points)
β€’ Modify your paging mechanism to manage multiple threads. (5 points)
β€’ Print the times of page fault of whole system before the program end. (2 point)
β€’ Correctly dump the contents to β€œsnapshot.bin”. (1 point)
Report (10 points)
Write a report for your assignment, which should include main information as below:
β€’ Environment of running your program. (E.g., OS, VS version, CUDA version, GPU
information etc.)
β€’ Execution steps of running your program.
β€’ How did you design your program?
β€’ What’s the page fault number of your output? Explain how does it come out.
β€’ What problems you met in this assignment and what are your solution?
β€’ Screenshot of your program output.
β€’ What did you learn from this assignment?
Submission
β€’ Please submit the file as package with directory structure as below:
Assignment_3_Student ID.zip
– Source
β€’ main.cu
β€’ virtual_memory.cu
β€’ virtual_memory.h
β€’ user_program.cu
β€’ data.bin
β€’ snapshot.bin (auto generated after running your program)
β€’ Makefile or Script
– Bonus
– Report
β€’ Due date: End (23:59) of 8 Nov, 202

CSC3150 Assignment 4

In Assignment 4, you are required to implement a mechanism of file system
management via GPU’s memory.
Background:
β€’ File systems provide efficient and convenient access to the disk by allowing data
to be stored, located, and retrieved easily.
β€’ A file system poses two quite different design problems. The first problem is
defining how the file system should look to the user. This task involves defining a
file with its attributes, the operations allowed on a file, and the directory
structure for organizing files.
β€’ The second problem is creating algorithms and data structures to map the logical
file system on to the physical secondary-storage devices.
β€’ The file-organization module knows about files and their logical blocks, as well as
physical blocks. By knowing the type of file allocation used and the location of
the file, the file-organization module can translate logical block address to
physical block address for the basic file system to transfer.
β€’ Each file’s logical blocks are numbered from 0 (or 1) through N. Since the
physical blocks containing the data usually do not match the logical numbers, a
translation is required to locate each block.
β€’ The logical file system manages metadata information.
β€’ Metadata includes all of the file-system structure except the actual data (or
contents of the files).
β€’ The file-organization module also includes the free-space manager, which tracks
unallocated blocks and provides these blocks to the file-organization module
when requested.
β€’ The logical file system manages the directory structure to provide the fileorganization module with the information the latter needs, given a symbolic file
name. It maintains file structure via file-control blocks.
β€’ A file-control block (FCB) (an inode in UNIX file systems) contains information
about the file, including ownership, permissions, and location of the file
contents.
β€’ Because there have no OS in GPU to maintain the mechanism of the logical file
system, we can try to implement a simple file system in CUDA GPU with single
thread, and limit global memory as volume.
The GPU File System we need to design:
β€’ We take the global memory as a volume (logical drive) from a hard disk.
β€’ No directory structure stored in volume, only one root directory, no
subdirectory in this file system.
β€’ A set of file operations should be implemented.
β€’ In this project, we use only one of GPU memory, the global memory as a
volume. We don’t create the shared memory as physical memory for any data
structures stored in, like system-wide open file table in memory.
β€’ In this simple file system, we just directly take the information from a volume (in
global memory) by single thread.
Specification:
β€’ The size of volume is 1085440 bytes (1060KB).
β€’ The size of files total is 1048576 bytes (1024KB).
β€’ The maximum number of file is 1024.
β€’ The maximum size of a file is 1024 bytes (1KB).
β€’ The maximum size of a file name is 20 bytes.
β€’ File name end with β€œ\0”.
β€’ FCB size is 32 bytes.
β€’ FCB entries is 32KB/ 32 bytes = 1024.
β€’ Storage block size is 32 bytes.
β€’ fs_open:
Open a file
Give a file pointer to find the file’s location.
Space in the file system must be found for the file.
An entry for the new file must be made in the directory.
Also accept access-mode information: read/write
When to use write mode, if no such file name can be found, create a new
zero byte file.
Return a write/read pointer.
Function definition:
De

CSC3150 Assignment 5

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.
static struct file_operations fops = {
owner: THIS_MODULE,
read: drv_read,
write: drv_write,
unlocked_ioctl: drv_ioctl,
open: drv_open,
release: drv_release,
};
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.
a. (HW5_IOC_SETSTUID) Set student ID: printk your student ID
b. (HW5_IOCSETRWOK) Set if RW OK: printk OK if you complete R/W function
c. (HW5_IOCSETIOCOK) Set if ioctl OK: printk OK if you complete ioctl function
d. (HW5_IOCSETIRQOK) Set if IRQ OK: printk OK if you complete bonus
e. (HW5_IOCSETBLOCK) Set blocking or non-blocking: set write function mode
f. (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.
#ifndef IOC_HW5_H
#define IOC_HW5_H
#define HW5_IOC_MAGIC ‘k’
#define HW5_IOCSETSTUID _IOW(HW5_IOC_MAGIC, 1, int)
#define HW5_IOCSETRWOK _IOW(HW5_IOC_MAGIC, 2, int)
#define HW5_IOCSETIOCOK _IOW(HW5_IOC_MAGIC, 3, int)
#define HW5_IOCSETIRQOK _IOW(HW5_IOC_MAGIC, 4, int)
#define HW5_IOCSETBLOCK _IOW(HW5_IOC_MAGIC, 5, int)
#define HW5_IOCWAITREADABLE _IOR(HW5_IOC_MAGIC, 6, int)
#define HW5_IOC_MAXNR 6
#endif
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.
struct dataIn {
char a;
int b;
short c;
};
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
// Arithmetic function
static void drv_arithmetic_routine(struct work_struct* ws);
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:
/******************Blocking IO******************/
printf(“Blocking IO\n”);
ret = 1;
if (ioctl(fd, HW5_IOCSETBLOCK, &ret) < 0) {
printf(“set blocking failed\n”);
return -1;
}
write(fd, &data, sizeof(data));
//Do not need to synchronize
//But need to wait computation completed
read(fd, &ret, sizeof(int));
printf(“ans=%d ret=%d\n\n”, ans, ret);
/***********************************************/
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:
/****************Non-Blocking IO****************/
printf(“Non-Blocking IO\n”);
ret = 0;
if (ioctl(fd, HW5_IOCSETBLOCK, &ret) < 0) {
printf(“set non-blocking failed\n”);
return -1;
}
printf(“Queueing work\n”);
write(fd, &data, sizeof(data));
//Can do something here
//But cannot confirm computation completed
printf(“Waiting\n”);
//synchronize function
while (1) {
if (ioctl(fd, HW5_IOCWAITREADABLE, &readable), readable)
break;
sleep(1);
}
printf(“Can read now.\n”);
read(fd, &ret, sizeof(int));
printf(“ans=%d ret=%d\n\n”, ans, ret);
/***********************************************/
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:
// DMA
#define DMA_BUFSIZE 64
#define DMA_STUID_ADDR 0x0 // Student ID
#define DMA_RWOK_ADDR 0x4 // RW function complete
#define DMA_IOCOK_ADDR 0x8 // ioctl function complete
#define DMA_IRQOK_ADDR 0xc // ISR function complete
#define DMA_COUNT_ADDR 0x10 // interrupt count function complete
#define DMA_ANS_ADDR 0x14 // Computation answer
#define DMA_READABLE_ADDR 0x18 // READABLE variable for synchronize
#define DMA_BLOCK_ADDR 0x1c // Blocking or non-blocking IO
#define DMA_OPCODE_ADDR 0x20 // data.a opcode
#define DMA_OPERAND_B_ADDR 0x21 // data.b operand1
#define DMA_OPERAND_C_ADDR 0x25 // data.c operand2
static void *dma_buf;
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.
On 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 )
// in and out function
static void myoutc(unsigned char data,unsigned short int port);
static void myouts(unsigned short data,unsigned short int port);
static void myouti(unsigned int data,unsigned short int port);
static unsigned char myinc(unsigned short int port);
static unsigned short myins(unsigned short int port);
static unsigned int myini(unsigned short int port);
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”.)
mname := mydev
$(mname)-objs := main.o
obj-m := $(mname).o
KERNELDIR := /lib/modules/`uname -r`/build
all:
$(MAKE) -C $(KERNELDIR) M=`pwd` modules
sudo insmod mydev.ko
gcc -o test test.c
Command: make clean
(It will remove β€œmydev.ko” and use β€œdmesg” to list kernel logs that includes keyword β€œOS_AS5”)
clean:
$(MAKE) -C $(KERNELDIR) M=`pwd` clean
sudo rmmod mydev
rm test
dmesg | grep OS_AS5
mknod script is provided:
#!/bin/bash
mknod /dev/mydev c $1 $2
chmod 666 /dev/mydev
ls -l /dev/mydev
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.
How to use mknod script is shown on 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 should complete module init and exit functions:
static int __init init_modules(void) {
printk(“%s:%s():……………Start……………\n”, PREFIX_TITLE, __func__);
/* Register chrdev */
/* Init cdev and make it alive */
/* Allocate DMA buffer */
/* Allocate work routine */
return 0;
}
static void __exit exit_modules(void) {
/* Free DMA buffer when exit modules */
/* Delete character device */
/* Free work routine */
printk(“%s:%s():…………..End…………..\n”, PREFIX_TITLE, __func__);
}
– Implement read/write/ioctl operations and arithmetic routine:
“`C
static ssize_t drv_read(struct file *filp, char __user *buffer, size_t ss, loff_t* lo) {
/* Implement read operation for your device */
return 0;
}
static ssize_t drv_write(struct file *filp, const char __user *buffer, size_t ss, loff_t* lo) {
/* Implement write operation for your device */
return 0;
}
static long drv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
/* Implement ioctl setting for your device */
return 0;
}
static void drv_arithmetic_routine(struct work_struct* ws) {
/* Implement arthemetic 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)
arithmetic(fd, ‘+’, 100, 10);
arithmetic(fd, ‘-‘, 100, 10);
arithmetic(fd, ‘*’, 100, 10);
arithmetic(fd, ‘/’, 100, 10);
arithmetic(fd, ‘p’, 100, 10000);
arithmetic(fd, ‘p’, 100, 20000);
User mode output:
……………Start……………
100 + 10 = 110
Blocking IO
ans=110 ret=110
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=110 ret=110
100 – 10 = 90
Blocking IO
ans=90 ret=90
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=90 ret=90
100 * 10 = 1000
Blocking IO
ans=1000 ret=1000
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=1000 ret=1000
100 / 10 = 10
Blocking IO
ans=10 ret=10
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=10 ret=10
100 p 10000 = 105019
Blocking IO
ans=105019 ret=105019
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=105019 ret=105019
100 p 20000 = 225077
Blocking IO
ans=225077 ret=225077
Non-Blocking IO
Queueing work
Waiting
Can read now.
ans=225077 ret=225077
……………End……………
Kernel mode output:
[35962.261080] OS_AS5:init_modules():……………Start……………
[35962.261081] OS_AS5:init_modules(): register chrdev(244,0)
[35962.261087] OS_AS5:init_modules(): allocate dma buffer
[35984.556209] OS_AS5:drv_open(): device open
[35984.556212] OS_AS5,drv_ioctl(): My STUID is =
[35984.556213] OS_AS5,drv_ioctl(): RM OK
[35984.556213] OS_AS5,drv_ioctl(): IOC OK
[35990.337307] OS_AS5,drv_ioctl(): Blocking IO
[35990.337310] OS_AS5:drv_write(): queue work
[35990.337311] OS_AS5:drv_write(): block
[35993.161033] OS_AS5,drv_arithmetic_routine(): 100 p 20000 = 225077
[35993.161125] OS_AS5:drv_read(): ans = 225077
[35993.161140] OS_AS5,drv_ioctl(): Non-Blocking IO
[35993.161142] OS_AS5:drv_write(): queue work
[35993.161145] OS_AS5,drv_ioctl(): wait readable 1
[35996.012354] OS_AS5,drv_arithmetic_routine(): 100 p 20000 = 225077
[35996.116977] OS_AS5:drv_read(): ans = 225077
[35996.117106] OS_AS5:drv_release(): device close
[36010.064424] OS_AS5:exit_modules(): free dma buffer
[36010.064426] OS_AS5:exit_modules(): unregister chrdev
[36010.064426] OS_AS5:exit_modules():…………..End…………..
Bonus Task (10 pionts)
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:
[35962.261080] OS_AS5:init_modules():……………Start……………
[35962.261081] OS_AS5:init_modules(): register chrdev(244,0)
[35962.261087] OS_AS5:init_modules(): request_irq 1 returns 0
[35962.261087] OS_AS5:init_modules(): allocate dma buffer
[35984.556209] OS_AS5:drv_open(): device open
[35984.556212] OS_AS5,drv_ioctl(): My STUID is =
[35984.556213] OS_AS5,drv_ioctl(): RM OK
[35984.556213] OS_AS5,drv_ioctl(): IOC OK
[35984.556214] OS_AS5,drv_ioctl(): IRQ OK
[35990.337307] OS_AS5,drv_ioctl(): Blocking IO
[35990.337310] OS_AS5:drv_write(): queue work
[35990.337311] OS_AS5:drv_write(): block
[35993.161033] OS_AS5,drv_arithmetic_routine(): 100 p 20000 = 225077
[35993.161125] OS_AS5:drv_read(): ans = 225077
[35993.161140] OS_AS5,drv_ioctl(): Non-Blocking IO
[35993.161142] OS_AS5:drv_write(): queue work
[35993.161145] OS_AS5,drv_ioctl(): wait readable 1
[35996.012354] OS_AS5,drv_arithmetic_routine(): 100 p 20000 = 225077
[35996.116977] OS_AS5:drv_read(): ans = 225077
[35996.117106] OS_AS5:drv_release(): device close
[36010.064423] OS_AS5:exit_modules(): interrupt count = 90
[36010.064424] OS_AS5:exit_modules(): free dma buffer
[36010.064426] OS_AS5:exit_modules(): unregister chrdev
[36010.064426] OS_AS5:exit_modules():…………..End…………..
Report (10 points)
Write a report for your assignment, which should include main information as below:
Your name and student id.
How did you design your program?
The environment of running your program. (E.g., version of OS and kernel)
The steps to execute your program.
Screenshot of your program output.
What did you learn from the tasks?
Grading rules
Here is a sample grading scheme. Different from the points specified above, this is the general guide when TA’s
grading.
Completion Marks
Bonus 10 points
Report 10 points
Completed with good quality 80 ~ 90
Completed accurately 80 +
Fully Submitted (compile successfully) 60 +
Partial submitted 0 ~ 60
No submission 0
Late submission Not allowed