Hide minor edits - Show changes to markup
int seq_printf(struct seq_file *, const char *, ...)
include/linux/seq_file.h
include/linux/seq_file.h:
void * (*start) (struct seq_file *m, loff_t *pos);
void (*stop) (struct seq_file *m, void *v);
void * (*next) (struct seq_file *m, void *v, loff_t *pos);
int (*show) (struct seq_file *m, void *v);
struct file_operations needs open, read, and release methods, and open and read can be no-ops. The prototypes from these functions (from include/linux/fs.h) are:\\
struct file_operations needs open, read, and release methods, and open and read can be no-ops. The prototypes from these functions (from include/linux/fs.h) are:
Due: Friday 9/22/06
current timestring when opened. (note - use a miscellaneous device here, as the misc interface will do all the nonsense required to get /dev/sxtime to show up properly with udev)
current timestring when opened.
pointer passed to read() is invalid, then make sure you return -EFAULT. Note about errors.
pointer passed to read() is invalid, then return -EFAULT.
struct seq_operations and initialize it with start, show, next, and stop methods.
include/linux/seq_file.h
struct file_operations and a struct miscdevice
struct file_operations needs open, read, and release methods, and open and read can be no-ops. The prototypes from these functions (from include/linux/fs.h) are: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
int (*release) (struct inode *, struct file *);
struct miscdevice you need to set .minor = MISC_DYNAMIC_MINOR, .fops to the address of your file_operations structure, and .name = "sxtime".
note - if you follow the proceeding instructions exactly, you'll have to find out the device major number and create /dev/sxtime manually, or else do a lot of nonsense with class_device_create(). Use misc_register(), instead, as shown in rather dated article, and everything will be done for you.
note - if you follow the proceeding instructions exactly, you'll have to find out the device major number and create /dev/sxtime manually, or else do a lot of nonsense with class_device_create(). Use misc_register(), instead, as shown in this rather dated article, and everything will be done for you.
note - if you follow the proceeding instructions exactly, you'll have to find out the device major number and create /dev/sxtime manually, or else do a lot of nonsense with class_device_create(). Use misc_register()], instead, as shown in [[href="http://www.linuxjournal.com/node/2920/print|this rather dated article, and everything will be done for you.
note - if you follow the proceeding instructions exactly, you'll have to find out the device major number and create /dev/sxtime manually, or else do a lot of nonsense with class_device_create(). Use misc_register(), instead, as shown in rather dated article, and everything will be done for you.
current timestring when opened.
current timestring when opened. (note - use a miscellaneous device here, as the misc interface will do all the nonsense required to get /dev/sxtime to show up properly with udev)
note - if you follow the proceeding instructions exactly, you'll have to find out the device major number and create /dev/sxtime manually, or else do a lot of nonsense with class_device_create(). Use misc_register()], instead, as shown in [[href="http://www.linuxjournal.com/node/2920/print|this rather dated article, and everything will be done for you.
Assignment: Add a system call, 'sxtime', which takes 3 arguments - flag, buf, and size.
Assignment: Add a system call, 'sxtime', which takes 3 arguments - flag, buf, and len.
The sxtime() function. This is a hack which will only work for September 2006.
The sxtime() function. This is a hack which will only work for September 2006.
Note that this describes "hooking" an existing call. We are going to\
Note that this describes "hooking" an existing call. We are going to \
return snprintf(buf, size, "d 2006 %02d:%02d:%02d",
return snprintf(buf, size, "d %02d:%02d:%02d 2006",
static char *days = {"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"};
static char *days[] = {"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"};
There is a very simple module skeleton on this site, here.
There is a very simple module skeleton elsewhere on this site, here.
pointer passed to read() is invalid, then make sure you return -EFAULT. Note (optional)
Hand in: Makefile and sxtime.c
pointer passed to read() is invalid, then make sure you return -EFAULT. Note about errors.
Hand in: Makefile and sxtime.c
Hand in: a patch to the 2.6.15 kernel source (as distributed on the course CD) which adds this system call. Note patch instructions below. (optional) - add a configuration option which enables or disables whether the system call is compiled into the kernel.
Hand in: a patch to the 2.6.15 kernel source (as distributed on the course CD) which adds this system call. Note patch instructions below. (optional) - add a configuration option which enables or disables whether the system call is compiled into the kernel.
Until Linux 2.6, system calls were implemented with the int 0x80 instruction, which is still used for some x86 processors. (on newer CPUs the SYSENTER instruction is used - see here for details)
Until Linux 2.6, system calls were implemented on x86 processors with the int 0x80 instruction. (In 2.6, on newer CPUs the sysenter instruction is used - see here for details.)
int 0x80 jumps to a particular exception address - entry 0x80 - of 256, and the other entries available for software interrupts are unused. In the following exercise we implement a new "fast trap" into the kernel using int 0x81.
Start with the following files:
You will need to get ftrap.S to compile, which should be an exercise in adding include files and #defines; arch/i386/kernel/entry.S should provide a good example. Then you need a fast_trap function - if it just does a printk indicating it ran, that should be enough - and a user-space program to invoke the trap.
Until Linux 2.6, system calls were implemented with the int 0x80 instruction, which is still used for some x86 processors. (on newer CPUs the SYSENTER instruction is used - see here for details)
There is a description of how to modify system calls in the LMPG here:
There is a description of how to modify system calls in the KMPG here:
add a syscall - most of the explanation from the LMPG is still applicable, but the steps are:
add a syscall - most of the explanation from the KMPG is still applicable, but the steps are:
question 1:
You may want to start with the Kernel Module Programming Guide:
There is a very simple module skeleton on this site, here.
After looking at that, you may want to refer to the Kernel Module Programming Guide:
Question 2: A description of system call modification:
There is a description of how to modify system calls in the LMPG here:
add a syscall, which involves:
add a syscall - most of the explanation from the LMPG is still applicable, but the steps are:
Since the system call list is kept in a fixed table in the kernel, this cannot be done in a module and must instead be done by modifying and recompiling the kernel itself. To hand in the assignment you will use a common method for packaging and exchanging kernel modifications, the patch.
Since the system call list is kept in a fixed table in the kernel, this cannot be done in a module and must instead be done by modifying and recompiling the kernel itself. (see ) To hand in the assignment you will use a common method for packaging and exchanging kernel modifications, the patch.
/* 1/1/70 was a Thursday. */
/* 1/1/70 was a Thursday. */
Question 2: A description of system call modification:
Note that this describes "hooking" an existing call. We are going toadd a syscall, which involves:
At the end of this assignment, here, is a list of resources, one of which is a simple function to return the date and time as a formatted string. We will use this function as a data source in our code below.
At the end of this assignment, here, is a list of resources, one of which is a simple function (sxtime) to return the date and time as a formatted string. We will use this function as a data source in our code below.
If flag has any other value, return an error. (-EINVAL)
If flag has any other value, return an error. (-EINVAL) As for the read() call, generate -EFAULT if necessary.
The sxtime() function. This is a hack which will only work for September 2006.
#include <linux/time.h>
int sxtime(char *buf, size_t size)
{
/* 1/1/70 was a Thursday.
*/
static char *days = {"Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed"};
int n = xtime.tv_sec - 4*3600; /* adjust for GMT->EDT */
int s = n % 60; n = n / 60;
int m = n % 60; n = n / 60;
int h = n % 24; n = n / 24;
int dow = n % 7;
int date = n - 13391; /* crude hack - works for 9/2006 */
return snprintf(buf, size, "%s Sep %d 2006 %02d:%02d:%02d",
days[dow], date, h, m, s);
}
question 1:
You may want to start with the Kernel Module Programming Guide:
In particular:
For the /proc file interface, look at this first (esp. the last para.)
then you can check the LMPG at:
To create and register a character device:
Note in particular any information on copying back and forth between kernel and user space.
The simplest way to get information out of the kernel to a user is via printk; however, to get information
Create a module named sxtime which does the following:
Here we investigate methods of moving information out of and into the kernel. Printk allows us to output information directly to the user; however, to get information to a program we use a file. The /proc filesystem has a set of kernel hooks to allow us to easily output information, and for more control we can create our own character device and implement its read and write methods.
Assignment: Create a module named sxtime which does the following:
should be returned, truncated to the read length if necessary.
should be returned, truncated to the read length if necessary. If the buffer pointer passed to read() is invalid, then make sure you return -EFAULT. Note (optional)
Hand in: Makefile and sxtime.c
The basic method for entering the kernel from user space is the kernel call - e.g. in the section above, the open() and read() system calls were used. Here we implement a custom kernel call.
Since the system call list is kept in a fixed table in the kernel, this cannot be done in a module and must instead be done by modifying and recompiling the kernel itself. To hand in the assignment you will use a common method for packaging and exchanging kernel modifications, the patch.
Assignment: Add a system call, 'sxtime', which takes 3 arguments - flag, buf, and size.
If flag has any other value, return an error. (-EINVAL)
Hand in: a patch to the 2.6.15 kernel source (as distributed on the course CD) which adds this system call. Note patch instructions below. (optional) - add a configuration option which enables or disables whether the system call is compiled into the kernel.
Error codes - in (almost?) all cases, system calls return positive or zero values for success, and negative values for errors. For a full list of error codes, look at include/asm/errno.h.
Patches - the simplest way to generate a patch is to keep two copies of the kernel source tree - a pristine one and the one you are working on. To generate the patch we then run a recursive diff:
# ls
linux-2.6.15.pristine
linux-2.6.15
# diff -Naur linux-2.6.15.pristine linux-2.6.15 > changes.patch
#
You may want to investigate the use of the following diff option:
--exclude=pattern
When comparing directories, ignore files and subdirectories
whose basenames match pattern.
The file changes.patch - the patch file - will now show the changes in any files between the two versions; in addition (the -N flag) it will contain any new files in the modified version. To apply this patch file we use the patch command, along with the '-p' option to tell it to use the path names in the diff file:
# cp -r linux-2.6.15.pristine linux-2.6.15.new-copy
# cd linux-2.6.15.new-copy
# patch -p1 < ../changes.patch
(since the new directory wasn't named 'linux-2.6.15', we couldn't use -p0. Instead we use -p1, which trims off the first directory in every path, and we change directories so the modified paths will work.) Note also that you can reverse a patch by applying the -R flag; thus applying the patch in reverse to your working tree should cause it to match the pristine tree.
At the end of this assignment, here, is a list of resources, one of which is a simple function to return the date and time as a formatted string. We will use this function as a data source in our code below.
The simplest way to get information out of the kernel to a user is via printk; however, to get information
Create a module named sxtime which does the following:
(:title Homework 1 :)
This assignment has two goals: