code is already there only edit some parts
__MACOSX/._untitled folder 2
untitled folder 2/project3
Project 3 Specification
Kernel Module Programming
Kernel Modules, Mutual Exclusion, and Scheduling
Final Submission Due: 3/27 at 11:59:59pm
Language Restrictions: C only
Purpose
This project introduces you to the nuts and bolts of kernel programming, concurrency, and
synchronization in the kernel. This project is divided into two parts and worth 40 points. This project
may be completed in partners or by yourself.
Part 1: remember Kernel Module
In Unix-like operating systems, the /proc interface is often used to set or read kernel information. For
example, take a look at /proc/cpuinfo and /proc/meminfo using the following commands:
$> cat /proc/cpuinfo
$> cat /proc/meminfo
Even though these proc files look like ordinary files, they are actually virtual kernel drivers! These
modules perform actions based on whether a user reads or writes to them.
You will write your own proc module called remember that
1. allows the user to write a string (max length 80)
2. allows the user to read back the string that was just added
For example:
$> echo “Hello there” > /proc/remember
$> cat /proc/remember
Hello there
$>
Please use the example proc module (hello_proc.c) and Makefile provided to you as a starting point.
Change the name of the module from helloworld to remember, create a global string of size 80 to hold
the string written, and use that global variable whenever a read is performed.
You can use the original 4.9 kernel or the 5.5.5 kernel.
Part 2: Your very own Virtual Printer
Congratulations, you are the proud owner of a new virtual printer called the penguin printer (a.k.a
“penguin”). Your task is to implement a printer scheduling algorithm. A printer is defined as a device
that accepts print jobs for documents into a queue and processes those documents. A maximum
number of jobs will be given. When a printer is loaded, it is initially running. Each job takes a specific
amount of time to process. Finally, the printer is stopped when the module is unloaded.
Your printer must keep track of the number and type of jobs in a queue. Jobs can come in at any time
and can be put on the queue instantaneously. A job must always be accepted if there is room. Jobs can
only be processed by the printer one at a time, and it takes the printer 1 second to look inside any spot
in the queue (whether it holds a job or not). Once a job is processed, the spot in the queue is cleared
and the printer can look for other jobs.
Task Specification
This is a classic exercise in modeling consumers and producers. The producer produces jobs and the
consumer is the printer. There are many pieces needed to provide a complete implementation discussed
below.
Step 1: Develop a penguin printer /proc module
Develop a /proc entry named /proc/penguin. In this project, you will be required to support a
printer job queue of size 10. You will accept the following 4 jobs:
• 1-page document (internally represented with a 1)
• 2-page document (internally represented with a 2)
• 3-page document (internally represented with a 3)
• 4-page document (internally represented with a 4)
As in a real printer, it takes varying time to process different types of jobs. Your printer must take 1
second to process a 1-page document, 2 seconds to process a 2-page document, 3 seconds to process a
3-page document, and 4 seconds to process a 4-page document. This processing time is in addition to
the 1 second it must take to look in any spot in the queue for an job.
Finally, the printer can break down. It also must accept the following job:
• maintenance (internally represented with a 5)
Maintenance takes a whopping 10 seconds, in addition to the 1 second it must take to look in any spot
in the queue for a job.
(Hint – you can “process” for a given amount of seconds by using the ssleep() function.)
You will place jobs on your queue by writing your jobs’s number to the /proc/penguin file. For
example, the following will put a 2-page document on the order queue:
$> echo 2 > /proc/penguin
If the queue is full, the printer code should return –ENOMEM and the job should not be placed on the
queue.
$> echo 2 > /proc/penguin
bash: echo: write error: Cannot allocate memory
Step 2: Reading from /proc/ penguin
In addition to accepting orders and commands, your printer must be able to display status information
by reading the device. Specifically, when someone reads from /proc/penguin, they should see:
• Current spot being looked at in the queue
• Current job being processed
• Total jobs processed
For example, take a look at this sample session:
$> insmod penguin.ko
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 0.
$> echo 4 > /proc/penguin
$> cat /proc/penguin
Processing nothing at slot 8. Total jobs processed: 0.
$> cat /proc/penguin
PriProcessing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 1.
$> rmmod penguin
The insmod and rmmod commands load and unload the kernel module, respectively. After starting the
printer, I placed 4-page document on the queue. However, when immediately reading from
/proc/penguin, my printer was not yet looking in the spot in the queue with the 4-page document.
Finally, it looks in the right spot and “processes” the 4-page for 4 seconds, so I was able to read from
/proc/penguin twice and get the same processing status.
Step 3: Use a kthread
You must use a kthread to allow the printer to run in the background and process orders. Please look at
my example, which starts a kthread on module load.
Step 4: Mutual Exclusion
You may have been getting lucky up until now, but what happens if the printer kthread is modifying a
spot in your job queue that you are trying to read at the same time? What happens if you are trying to
add a job to the queue at the same time that the printer is taking one away? If you have any global
variables in your code that can be accessed by more than one thread at a time, you must protect the
reading and writing of those variables with mutexes (semaphores with only 0 and 1 values). If not,
your entire driver could randomly crash. The probability of this goes up with the more cores you have
in your virtual machine. Use kernel mutexes to protect critical sections of code where you read or
write to global variables.
Extra Credit
The top five submissions as measured by the above evaluation procedure will receive +5 points to their
project 3 grade. The metric to optimize is: total jobs processed.
Full Project Submission Procedure
You will need to submit the following files:
• remember.c (not the .ko or the Makefile)
• penguin.c (not the .ko or the Makefile)
• The filled-in Project3-README x. (If you are a Mac user, please keep the format as Word or
else convert to a pdf. I have problems grading Pages documents on a non-Mac.)
__MACOSX/untitled folder 2/._project3
untitled folder 2/watch_syslog.sh
#!/bin/bash
tail -f /var/log/syslog
__MACOSX/untitled folder 2/._watch_syslog.sh
untitled folder 2/penguin.c MODULE_LICENSE(“GPL”); /* Kernel needs this license. */ /* The kitchen thread will run this function. The thread will stop int hello_proc_init(void) { /* This message will print in /var/log/syslog or on the first tty. */ return 0; /* Allocating kernel memory, don’t touch. */ /* Free the allocated memory, don’t touch. */ __MACOSX/untitled folder 2/._penguin.c untitled folder 2/Makefile.txt __MACOSX/untitled folder 2/._Makefile.txt untitled folder 2/Makefile-2.txt __MACOSX/untitled folder 2/._Makefile-2.txt untitled folder 2/hello_proc.c /* This function is called to create the special proc file entry on /* This message will print in /var/log/syslog or on the first tty. */ /* Take the string “Hello World!\n” and put it in ret_buf. Copy ret_buf /* Allocating kernel memory, don’t touch. */ /* Free the allocated memory, don’t touch. */ __MACOSX/untitled folder 2/._hello_proc.c untitled folder 2/watch_penguin.sh __MACOSX/untitled folder 2/._watch_penguin.sh Project 3 Specification Kernel Modules, Mutual Exclusion, and Scheduling Final Submission Due: 3/27 at 11:59:59pm Language Restrictions: C only Purpose This project introduces you to the nuts and bolts of kernel programming, concurrency, and Part 1: remember Kernel Module In Unix-like operating systems, the /proc interface is often used to set or read kernel information. For $> cat /proc/cpuinfo $> cat /proc/meminfo Even though these proc files look like ordinary files, they are actually virtual kernel drivers! These You will write your own proc module called remember that
1. allows the user to write a string (max length 80)
For example: Please use the example proc module (hello_proc.c) and Makefile provided to you as a starting point. You can use the original 4.9 kernel or the 5.5.5 kernel. Part 2: Your very own Virtual Printer Congratulations, you are the proud owner of a new virtual printer called the penguin printer (a.k.a amount of time to process. Finally, the printer is stopped when the module is unloaded. Your printer must keep track of the number and type of jobs in a queue. Jobs can come in at any time Task Specification This is a classic exercise in modeling consumers and producers. The producer produces jobs and the Step 1: Develop a penguin printer /proc module • 1-page document (internally represented with a 1)
As in a real printer, it takes varying time to process different types of jobs. Your printer must take 1 Finally, the printer can break down. It also must accept the following job:
• maintenance (internally represented with a 5) Maintenance takes a whopping 10 seconds, in addition to the 1 second it must take to look in any spot (Hint – you can “process” for a given amount of seconds by using the ssleep() function.) You will place jobs on your queue by writing your jobs’s number to the /proc/penguin file. For $> echo 2 > /proc/penguin If the queue is full, the printer code should return –ENOMEM and the job should not be placed on the $> echo 2 > /proc/penguin Step 2: Reading from /proc/ penguin
In addition to accepting orders and commands, your printer must be able to display status information • Current spot being looked at in the queue
For example, take a look at this sample session: The insmod and rmmod commands load and unload the kernel module, respectively. After starting the Step 3: Use a kthread You must use a kthread to allow the printer to run in the background and process orders. Please look at Step 4: Mutual Exclusion You may have been getting lucky up until now, but what happens if the printer kthread is modifying a Extra Credit The top five submissions as measured by the above evaluation procedure will receive +5 points to their Full Project Submission Procedure You will need to submit the following files: • remember.c (not the .ko or the Makefile) else convert to a pdf. I have problems grading Pages documents on a non-Mac.) Project 3 Specification Kernel Modules, Mutual Exclusion, and Scheduling Final Submission Due: 3/27 at 11:59:59pm Language Restrictions: C only Purpose This project introduces you to the nuts and bolts of kernel programming, concurrency, and Part 1: remember Kernel Module In Unix-like operating systems, the /proc interface is often used to set or read kernel information. For $> cat /proc/cpuinfo $> cat /proc/meminfo Even though these proc files look like ordinary files, they are actually virtual kernel drivers! These You will write your own proc module called remember that
1. allows the user to write a string (max length 80)
For example: Please use the example proc module (hello_proc.c) and Makefile provided to you as a starting point. You can use the original 4.9 kernel or the 5.5.5 kernel. Part 2: Your very own Virtual Printer Congratulations, you are the proud owner of a new virtual printer called the penguin printer (a.k.a amount of time to process. Finally, the printer is stopped when the module is unloaded. Your printer must keep track of the number and type of jobs in a queue. Jobs can come in at any time Task Specification This is a classic exercise in modeling consumers and producers. The producer produces jobs and the Step 1: Develop a penguin printer /proc module • 1-page document (internally represented with a 1)
As in a real printer, it takes varying time to process different types of jobs. Your printer must take 1 Finally, the printer can break down. It also must accept the following job:
• maintenance (internally represented with a 5) Maintenance takes a whopping 10 seconds, in addition to the 1 second it must take to look in any spot (Hint – you can “process” for a given amount of seconds by using the ssleep() function.) You will place jobs on your queue by writing your jobs’s number to the /proc/penguin file. For $> echo 2 > /proc/penguin If the queue is full, the printer code should return –ENOMEM and the job should not be placed on the $> echo 2 > /proc/penguin Step 2: Reading from /proc/ penguin
In addition to accepting orders and commands, your printer must be able to display status information • Current spot being looked at in the queue
For example, take a look at this sample session: The insmod and rmmod commands load and unload the kernel module, respectively. After starting the Step 3: Use a kthread You must use a kthread to allow the printer to run in the background and process orders. Please look at Step 4: Mutual Exclusion You may have been getting lucky up until now, but what happens if the printer kthread is modifying a Extra Credit The top five submissions as measured by the above evaluation procedure will receive +5 points to their Full Project Submission Procedure You will need to submit the following files: • remember.c (not the .ko or the Makefile) else convert to a pdf. I have problems grading Pages documents on a non-Mac.)
#include
#define ENTRY_NAME “penguin”
#define PERMS 0644
#define PARENT NULL
/* Function declarations */
ssize_t procfile_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos);
ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
static int t_penguin(void* data);
/* Global variables go here */
static struct file_operations hello_proc_ops = {
.owner = THIS_MODULE,
.read = procfile_read,
.write = procfile_write,
};
struct task_struct *t; /* Printer thread task struct (use to start/stop)*/
* when either kitchen_stop(t) is called or else the function ends. */
static int t_penguin(void* data) {
int i=0;
/* Print hello 50 times, then stop on it’s own */
while(!kthread_should_stop()) {
printk(“Hello from the penguin! Run %i\n”, i);
/* Sleep one second */
ssleep(1);
i++;
}
return 0;
}
proc_create_data(ENTRY_NAME, 0, NULL, &hello_proc_ops, NULL);
printk(“/proc/%s created\n”, ENTRY_NAME);
/* Start the printer — move out of here later. */
t = kthread_run(t_penguin, NULL, “penguin_thread”);
}
ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
static int finished = 0;
int ret;
char ret_buf[80];
/* Are we done reading? If so, we return 0 to indicate end-of-file */
if (finished) {
finished=0;
return 0;
}
finished = 1;
/* This message will print in /var/log/syslog or on the first tty. */
printk(“/proc/%s read called.\n”, ENTRY_NAME);
ret=sprintf(ret_buf, “Penguin read called.\n”);
if(copy_to_user(buf, ret_buf, ret)) {
ret = -EFAULT;
}
return ret;
}
ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char *page; /* don’t touch */
int my_data = 0;
page = (char *) vmalloc(count);
if (!page)
return -ENOMEM;
/* Copy the data from the user space. Data is placed in page. */
if (copy_from_user(page, buf, count)) {
vfree(page);
return -EFAULT;
}
/* Now do something with the data, here we just print it */
sscanf(page,”%d”,&my_data);
printk(“User has sent the value of %d\n”, my_data);
vfree(page);
return count;
}
void hello_proc_exit(void)
{
/* Will block here and wait until kthread stops */
kthread_stop(t);
remove_proc_entry(ENTRY_NAME, NULL);
printk(“Removing /proc/%s.\n”, ENTRY_NAME);
}
module_init(hello_proc_init);
module_exit(hello_proc_exit);
ifneq ($(KERNELRELEASE),)
obj-m := hello_proc.o
else
KERNELDIR ?= \
/lib/modules/`uname -r`/build/
PWD := `pwd`
default:
$(MAKE) -C $(KERNELDIR) \
M=$(PWD) modules
endif
clean:
rm -f *.ko *.o Module* *mod*
ifneq ($(KERNELRELEASE),)
obj-m := penguin.o
else
KERNELDIR ?= \
/lib/modules/`uname -r`/build/
PWD := `pwd`
default:
$(MAKE) -C $(KERNELDIR) \
M=$(PWD) modules
endif
clean:
rm -f *.ko *.o Module* *mod*
#include
#define ENTRY_NAME “helloworld”
#define PERMS 0644
#define PARENT NULL
/* Function declarations */
ssize_t procfile_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos);
ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
/* Global variables go here */
/* This global structure is necessary to bind the regular file read and write
* operations to our special “read” and “write” functions instead. Don’t
* modify. (structs in C are like objects in other languages.)
*/
static struct file_operations hello_proc_ops = {
.owner = THIS_MODULE,
.read = procfile_read,
.write = procfile_write,
};
* module load. This file is created as /proc/helloworld. */
int hello_proc_init(void) {
proc_create_data(ENTRY_NAME, 0, NULL, &hello_proc_ops, NULL);
printk(“/proc/%s created\n”, ENTRY_NAME);
return 0;
}
/* This function is called when someone tries to READ from the file
* /proc/helloworld. */
ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
/* Static variable? What does this do inside a C function? Take a look
* at the accepted answer in the link below:
* http://stackoverflow.com/questions/572547/what-does-static-mean-in-a-c-program
*/
static int finished = 0;
int ret;
char ret_buf[80];
/* Are we done reading? If so, we return 0 to indicate end-of-file */
if (finished) {
finished=0;
return 0;
}
finished = 1;
/* This message will print in /var/log/syslog or on the first tty. */
printk(“/proc/%s read called.\n”, ENTRY_NAME);
into the user-space buffer called buf. buf is what gets
* displayed to the user when they read the file. */
ret = sprintf(ret_buf, “Hello world!\n”);
if(copy_to_user(buf, ret_buf, ret)) {
ret = -EFAULT; //failed, let’s get out of here
}
/* Returning the number of characters returned to the reader. */
return ret;
}
/* This function is called when someone tries to WRITE to the file
* /proc/helloworld. */
ssize_t procfile_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char *page; /* don’t touch */
page = (char *) vmalloc(count);
if (!page)
return -ENOMEM;
/* Copy the data from the user space. Data is placed in page. */
if (copy_from_user(page, buf, count)) {
vfree(page);
return -EFAULT;
}
/* Now do something with the data, here we just print it */
printk(“User has sent the value of %s\n”, page);
vfree(page);
/* Return the number of bytes written to the file. */
return count;
}
/* Called when module is unloaded. Function removes the proc file and
* prints a message to /var/log/syslog. */
void hello_proc_exit(void)
{
remove_proc_entry(ENTRY_NAME, NULL);
printk(“Removing /proc/%s.\n”, ENTRY_NAME);
}
/* Necessary module stuff. Says init function is hello_proc_init and
* exit function is hello_proc_exit. */
module_init(hello_proc_init);
module_exit(hello_proc_exit);
#!/bin/bash
watch -n 1 cat /proc/penguin
Kernel Module Programming
synchronization in the kernel. This project is divided into two parts and worth 40 points. This project
may be completed in partners or by yourself.
example, take a look at /proc/cpuinfo and /proc/meminfo using the following commands:
modules perform actions based on whether a user reads or writes to them.
2. allows the user to read back the string that was just added
$> echo “Hello there” > /proc/remember
$> cat /proc/remember
Hello there
$>
Change the name of the module from helloworld to remember, create a global string of size 80 to hold
the string written, and use that global variable whenever a read is performed.
“penguin”). Your task is to implement a printer scheduling algorithm. A printer is defined as a device
that accepts print jobs for documents into a queue and processes those documents. A maximum
number of jobs will be given. When a printer is loaded, it is initially running. Each job takes a specific
and can be put on the queue instantaneously. A job must always be accepted if there is room. Jobs can
only be processed by the printer one at a time, and it takes the printer 1 second to look inside any spot
in the queue (whether it holds a job or not). Once a job is processed, the spot in the queue is cleared
and the printer can look for other jobs.
consumer is the printer. There are many pieces needed to provide a complete implementation discussed
below.
Develop a /proc entry named /proc/penguin. In this project, you will be required to support a
printer job queue of size 10. You will accept the following 4 jobs:
• 2-page document (internally represented with a 2)
• 3-page document (internally represented with a 3)
• 4-page document (internally represented with a 4)
second to process a 1-page document, 2 seconds to process a 2-page document, 3 seconds to process a
3-page document, and 4 seconds to process a 4-page document. This processing time is in addition to
the 1 second it must take to look in any spot in the queue for an job.
in the queue for a job.
example, the following will put a 2-page document on the order queue:
queue.
bash: echo: write error: Cannot allocate memory
by reading the device. Specifically, when someone reads from /proc/penguin, they should see:
• Current job being processed
• Total jobs processed
$> insmod penguin.ko
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 0.
$> echo 4 > /proc/penguin
$> cat /proc/penguin
Processing nothing at slot 8. Total jobs processed: 0.
$> cat /proc/penguin
PriProcessing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 1.
$> rmmod penguin
printer, I placed 4-page document on the queue. However, when immediately reading from
/proc/penguin, my printer was not yet looking in the spot in the queue with the 4-page document.
Finally, it looks in the right spot and “processes” the 4-page for 4 seconds, so I was able to read from
/proc/penguin twice and get the same processing status.
my example, which starts a kthread on module load.
spot in your job queue that you are trying to read at the same time? What happens if you are trying to
add a job to the queue at the same time that the printer is taking one away? If you have any global
variables in your code that can be accessed by more than one thread at a time, you must protect the
reading and writing of those variables with mutexes (semaphores with only 0 and 1 values). If not,
your entire driver could randomly crash. The probability of this goes up with the more cores you have
in your virtual machine. Use kernel mutexes to protect critical sections of code where you read or
write to global variables.
project 3 grade. The metric to optimize is: total jobs processed.
• penguin.c (not the .ko or the Makefile)
• The filled-in Project3-README x. (If you are a Mac user, please keep the format as Word or
Kernel Module Programming
synchronization in the kernel. This project is divided into two parts and worth 40 points. This project
may be completed in partners or by yourself.
example, take a look at /proc/cpuinfo and /proc/meminfo using the following commands:
modules perform actions based on whether a user reads or writes to them.
2. allows the user to read back the string that was just added
$> echo “Hello there” > /proc/remember
$> cat /proc/remember
Hello there
$>
Change the name of the module from helloworld to remember, create a global string of size 80 to hold
the string written, and use that global variable whenever a read is performed.
“penguin”). Your task is to implement a printer scheduling algorithm. A printer is defined as a device
that accepts print jobs for documents into a queue and processes those documents. A maximum
number of jobs will be given. When a printer is loaded, it is initially running. Each job takes a specific
and can be put on the queue instantaneously. A job must always be accepted if there is room. Jobs can
only be processed by the printer one at a time, and it takes the printer 1 second to look inside any spot
in the queue (whether it holds a job or not). Once a job is processed, the spot in the queue is cleared
and the printer can look for other jobs.
consumer is the printer. There are many pieces needed to provide a complete implementation discussed
below.
Develop a /proc entry named /proc/penguin. In this project, you will be required to support a
printer job queue of size 10. You will accept the following 4 jobs:
• 2-page document (internally represented with a 2)
• 3-page document (internally represented with a 3)
• 4-page document (internally represented with a 4)
second to process a 1-page document, 2 seconds to process a 2-page document, 3 seconds to process a
3-page document, and 4 seconds to process a 4-page document. This processing time is in addition to
the 1 second it must take to look in any spot in the queue for an job.
in the queue for a job.
example, the following will put a 2-page document on the order queue:
queue.
bash: echo: write error: Cannot allocate memory
by reading the device. Specifically, when someone reads from /proc/penguin, they should see:
• Current job being processed
• Total jobs processed
$> insmod penguin.ko
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 0.
$> echo 4 > /proc/penguin
$> cat /proc/penguin
Processing nothing at slot 8. Total jobs processed: 0.
$> cat /proc/penguin
PriProcessing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing 4-page document at slot 0. Total jobs processed: 0.
$> cat /proc/penguin
Processing nothing at slot 2. Total jobs processed: 1.
$> rmmod penguin
printer, I placed 4-page document on the queue. However, when immediately reading from
/proc/penguin, my printer was not yet looking in the spot in the queue with the 4-page document.
Finally, it looks in the right spot and “processes” the 4-page for 4 seconds, so I was able to read from
/proc/penguin twice and get the same processing status.
my example, which starts a kthread on module load.
spot in your job queue that you are trying to read at the same time? What happens if you are trying to
add a job to the queue at the same time that the printer is taking one away? If you have any global
variables in your code that can be accessed by more than one thread at a time, you must protect the
reading and writing of those variables with mutexes (semaphores with only 0 and 1 values). If not,
your entire driver could randomly crash. The probability of this goes up with the more cores you have
in your virtual machine. Use kernel mutexes to protect critical sections of code where you read or
write to global variables.
project 3 grade. The metric to optimize is: total jobs processed.
• penguin.c (not the .ko or the Makefile)
• The filled-in Project3-README x. (If you are a Mac user, please keep the format as Word or