***************************************************************************** * CREATING A NEW PROC FILE MODULE * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.1) * ***************************************************************************** We shall use as example the same kdbgvars proc file that was implemented statically inside the kernel (see patch 2.4.12kh4). This time the new kdbgvars proc file will be inserted in the /proc/sys/kernel directory. ***************************************************************************** STEP 0: set the proper EXTRAVERSION value in Makefile ***************************************************************************** replace: EXTRAVERSION = with: EXTRAVERSION = kh6 ***************************************************************************** STEP 1: add tristate CONFIG_KDBGVARS entry in arch/i386/config.in ***************************************************************************** add right after: bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE the following line: dep_tristate ' Kernel debug variables' CONFIG_KDBGVARS $CONFIG_PROC_FS ***************************************************************************** STEP 2: document CONFIG_KDBGVARS in Documentation/Configure.help ***************************************************************************** add right after: Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even if the system crashes for example during kernel debugging (e.g., you will be able to flush the buffer cache to disk, reboot the system immediately or dump some status information). This is accomplished by pressing various keys while holding SysRq (Alt+PrintScreen). It also works on a serial console (on PC hardware at least), if you send a BREAK and then within 5 seconds a command keypress. The keys are documented in Documentation/sysrq.txt. Don't say Y unless you really know what this hack does. the following lines: Kernel debug variables support CONFIG_KDBGVARS Enabling this option will include in your /proc filesystem a new entry, /proc/kdbgvars, which displays the current values of five new kernel variables denoted as kdbgvar0, ..., kdbgvar3, and kdbgflag. The value of these variables can be set arbitrarily while debugging the kernel. They are displayed in hexadecimal format. ***************************************************************************** STEP 3: create a new directory linux/new_procs that will contain the kdbgvars.c file ***************************************************************************** a) mkdir new_procs ***************************************************************************** STEP 4: modify the main linux/Makefile ***************************************************************************** a) replace: CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o with: CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o new_procs/new_procs.o b) replace: SUBDIRS =kernel drivers mm fs net ipc lib with: SUBDIRS =kernel drivers mm fs net ipc lib new_procs ***************************************************************************** STEP 5: Add new kernel variables kdbgvar0, ..., kdbgvar3 ***************************************************************************** add in kernel/sched.c file right after: struct kernel_stat kstat; the following lines: #if defined(CONFIG_KDBGVARS) || defined(CONFIG_KDBGVARS_MODULE) unsigned long kdbgvar0 = 0x00000000; unsigned long kdbgvar1 = 0x11111111; unsigned long kdbgvar2 = 0x22222222; unsigned long kdbgvar3 = 0x33333333; #endif ***************************************************************************** STEP 6: Add new export symbols in linux/kernel/ksyms.c ***************************************************************************** add at the bottom of the file the following lines: /* implementing new proc file as a module */ #ifdef CONFIG_KDBGVARS_MODULE extern unsigned long kdbgvar0, kdbgvar1, kdbgvar2, kdbgvar3; EXPORT_SYMBOL(kdbgvar0); EXPORT_SYMBOL(kdbgvar1); EXPORT_SYMBOL(kdbgvar2); EXPORT_SYMBOL(kdbgvar3); #endif ***************************************************************************** STEP 7: Create the Makefile for the linux/new_procs directory ***************************************************************************** # # Makefile for linux/new_procs # # Note: dependencies are done automatically by "make dep", which also removes # any old dependency. DON'T put your own dependencies ere unless it's something # special (ie not a .c file). # # Note2: the CFLAGS definition is now in the main Makefile... # O_TARGET := new_procs.o obj-m := obj-y := ifeq ($(CONFIG_KDBGVARS),y) obj-y += kdbgvars_read_proc.o else ifeq ($(CONFIG_KDBGVARS),m) obj-m += kdbgvars_read_proc.o endif endif include $(TOPDIR)/Rules.make ***************************************************************************** STEP 8: Add a file in the new_procs directory to do the work ***************************************************************************** /* */ /* linux/new_procs/kdbgvars_read_proc.c */ /* */ /* This file contains the function that reads the kdbgvars proc file */ /* */ #include #include #include #include #include #include extern unsigned int kdbgvar0, kdbgvar1, kdbgvar2, kdbgvar3; static int kdbgvars_read_only(char *, char **, off_t, int, int *, void *); struct proc_dir_entry *kdbgvars_pde; static int __init kdbgvars_init(void) { printk(KERN_INFO "kdbgvars module loaded\n"); kdbgvars_pde = create_proc_read_entry("sys/kernel/kdbgvars", 0644, NULL, kdbgvars_read_only, NULL); kdbgvars_pde->owner = THIS_MODULE; return 0; } static void __exit kdbgvars_exit(void) { remove_proc_entry("sys/kernel/kdbgvars", NULL); printk(KERN_INFO "kdbgvars1 module unloaded\n"); } static int kdbgvars_read_only(char *page, char **start, off_t off, int count, int *eof, void *data) { int written; MOD_INC_USE_COUNT; written = sprintf(page, "kdbgvar0= %x, kdbgvar1= %x, kdbgvar2= %x, kdbgvar3= %x\n", kdbgvar0, kdbgvar1, kdbgvar2, kdbgvar3); MOD_DEC_USE_COUNT; return written; } EXPORT_NO_SYMBOLS; module_init(kdbgvars_init); module_exit(kdbgvars_exit); ***************************************************************************** STEP 9: Test the new proc file as a module component ***************************************************************************** a) run make menuconfig and set to 'm' the CONFIG_KDBGVARS kernel hackers option b) run make dep, recompile the kernel and copy the arch/i386/boot/bzImage in /boot/vmlinuz-2.4.12kh6 or on a floppy c) run make modules and make modules_install d) run lilo and reboot the system and select linux-2.4.12kh6 as the system to boot e) login as root and insert the module: insmod /usr/src/linux/new_procs/kdbgvars_read_proc.o or: modprobe kdbgvars_read_proc f) test whether it has been loaded correctly by typing: lsmod If everything is OK, you should get the following answer: Module Size Used by kdbgvars_read_proc 728 0 (unused) g) instead of the cat command, you can use a regular C program to read the kdbgvars proc file: /* Tkdbgvars.c */ /* */ /* Read data from the /proc/kdbgvars file */ /* */ #include #include #include int main(void) { int fd, i, cc; char c[128]; fd = open("/proc/sys/kernel/kdbgvars", "O_RDONLY"); for (i=0; i < 4096; i++) { cc = read(fd, &c[i], 1); if (cc == 0) break; } c[i] = '\0'; printf("%s", c); cc = close(fd); exit(0); } h) if everything went right you should get a display like: kdbgvar0= 0, kdbgvar1= 11111111, kdbgvar2= 22222222, kdbgvar3= 33333333