Linux Kernel Tag

Add Schedule Counter in Kernel

Objective

Add a feature to the linux kernel, which records the total times a process is scheduled to be executed on CPU.

Basic Idea

Add a counter varible to the struct task_struct, init the counter varible to 0 when a process is created/forked. Every time the process is scheduled to be executed, increase the counter and write the number to a proc file.

Details of how to modify the kernel

0. Environment
  • VMware Fusion 7
  • Ubuntu 12.04.5
  • Kernel Version 3.18.8
1. /include/linux/sched.h
line#1234
1
2
3
4
struct task_struct{
+ unsigned long ctx;
...
}
2. /kernel/fork.c
line#1622
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr){
...
p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace);
+ p->ctx = 0;
...
}
3. /kernel/sched/core.c
line#2864
1
2
3
4
5
6
7
8
9
asmlinkage __visible void __sched schedule(void)
{
struct task_struct *tsk = current;
+ tsk->ctx = tsk->ctx + 1;
sched_submit_work(tsk);
__schedule();
}
4. /fs/proc/base.c
line #319
1
2
3
4
5
6
7
8
+ /*
+ * Provides /proc/PID/ctx
+ */
+ static int proc_pid_ctx(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
+ {
+ return seq_printf(m, "%llu\n", (unsigned long long)task->ctx);
+ }
line #2603
1
+ ONE("ctx", S_IRUGO, proc_pid_ctx),
line #2949
1
+ ONE("ctx", S_IRUGO, proc_pid_ctx),
5. Compile

Results

1.Test Code
1
2
3
4
5
6
// block.c
#include <stdio.h>
int main(){
while(1) getchar();
return 0;
}
1
2
gcc block.c -o block
./block
2.Find the process id
1
ps -e | grep block
3.Observe the counter
1
2
cd /proc/[PID]
cat ctx
4.Increse the counter

Type anything to the block process to make it scheduled to be executed and check the content of ctx file again.

5.End
1
kill [PID]

Compiling Linux Kernel

To be prepared to make changes to the kernel, it’s necessary to give it a try to compile the linux kernel successfully.

Environment

  • VMware Fusion 7
  • Ubuntu 12.04.5
  • Root permission

Objective

Initially, the kernel version of the Ubuntu 12.04.5 is 3.13.0-32-generic according to

1
uname -r

If you wanna check your ubuntu version, use

1
cat /etc/issue

Our goal is to update the version of kernel to newer one, in this case, 3.18.

Compile the Linux Kernel

1. Download the kernel from here.
2. Copy to a directory and extract.
1
2
3
4
5
cp linux-3.X.X.tar.xz /usr/src
cd /usr/src
xz -d linux-3.X.X.tar.xz
tar -xf linux-3.X.X.tar
cd linux-3.X.X
3. If not the first time to compile
1
2
make clean
make mrproper
4. Configuration
1
make menuconfig

There might be a tiny prob here saying

1
fatal error: curses.h: No such file or directory

Solution under Ubuntu:

1
sudo apt-get install libncurses5-dev libncursesw5-dev
5. Compile
1
2
3
make
make modules_install
make install

Suggestion here: enlarge the memory size of your virtual system, which may help reduce the compiling time dramatically.

It takes hours to compile with 1 core and 1-GB memory with GUI turned on…

6. Update GRUB
1
2
3
4
5
cd /boot
mkinitramfs 3.18.8 -o initrd.img-3.18.8
cp /usr/src/linux-3.18.8/arch/x86_64/boot/bzImage /boot/vmlinuz-3.18.8
ln -s /boot/System.map-3.18.8 /boot/System.map
sudo update-grub2
7. Reboot and Check!