C LANGUAGE
linux
kernel
procfs, sysfs, character
Authors: WhoAmI, CrazyMonkey
Date: 20230303
email: kccddb@gmail.com
Copyright: CC BY-NC-SA
此為 Linux Kernel module 相關議題 請若是基本使用者 請詢查別的文章
目的:
A. 學會這 sysfs, procfs 您可以修改 Linux kernel source 或 kernel module 如此可以透過 user space 做一下簡單設定(wrtie) 也可觀察 (read)
B. 需要有 OOP 觀念
C. c language: function pointer, callback and event-driven
例如 起動 "IP 轉送 Route 的功能"
echo 1 > /proc/sys/net/ipv4/ip_forward
就是已有的 procfs 的 entry
例如 由ETH0 IP frame –> ETH1 (根據 routing table 轉送)
Please use "ip route" to see the route!
See also
(1) iproute2:
Linux Advanced Routing & Traffic Control HOWTO (ip command…)
請用 (a) ip command 代替 ifconfig, route,..
例如
ip addr …
ip route …
(b) tc: traffic control QoS (進階)
(2)基本Kernel Netfilter 觀念 與 user space command "iptables"
iptables 是user space 用來與 核心netfiter 溝通的 命令, udevd (event managing daemon) 也是
netlink - communication between kernel and user space (AF_NETLINK)
Please see
A Deep Dive into Iptables and Netfilter Architecture
ip, iptables 都是透過 netlink socket 與 kernel 運行!! 現在可以了解我敎 netlink socket 的目的了?
另一個 tc 有用到再去看 這是 QoS 控制 Queueing 又出現了…排隊理論與資源分享
當然重開機procfs, sysfs 要再重設(因為是在DRAM 記憶體, 不是在硬碟!!), 因此一般就加到 起動的 shell script 中
B. 學會小細節 licence and export, strip, Makefile
C. 簡單的 sysfs, procfs, kernel module
D. 更進一步請看很好的 Sysfs in Linux Kernel – Linux Device Driver Tutorial Part 11
strip -g
strip: Discard symbols from object files.
strip -g: remove debugging symbols only.
Be careful, you cannot use "strip hello_sys.ko" in building kernel module.
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
(a) "/lib/modules/$(shell uname -r)/build" have the default Makefile.
In this case, you use the default kernel!
or
"/linux-kernel-source" if you use other kernel version. e.g., /src/linux-3.2.0-64-generic
If you use a new kernel source, not your default kernel,
u must boot your Linux via your new kernel!!
(b) M=$(PWD) means your module path "/home/laikc/demo"
(c) "modules" means: make modules
**Use strip -g**
Makefile
root@laikc-virtual:/home/laikc/demo# cat Makefile
obj-m += hello_sys.o
all:
make -C /lib/modules/(PWD) modules
strip -g hello_sys.ko
clean:
make -C /lib/modules/(PWD) clean
root@laikc-virtual:/home/laikc/demo#
root@laikc-virtual:/home/laikc/demo# make
make -C /lib/modules/3.2.0-64-generic/build M=/home/laikc/demo modules
make[1]: Entering directory /usr/src/linux-headers-3.2.0-64-generic' Building modules, stage 2. MODPOST 1 modules make[1]: Leaving directory
/usr/src/linux-headers-3.2.0-64-generic'
strip -g hello_sys.ko
root@laikc-virtual:/home/laikc/demo#
扮演 檔案運作的 struct file_operations
Supplementary Information
How to test:
root@laikc-virtual:/home/laikc/demo# insmod hello_sys.ko
root@laikc-virtual:/home/laikc/demo# cat /sys/class/HelloSys/enable
Disabled
root@laikc-virtual:/home/laikc/demo# echo "1" >/sys/class/HelloSys/enable
root@laikc-virtual:/home/laikc/demo# cat /sys/class/HelloSys/enable
Enabled
root@laikc-virtual:/home/laikc/demo# rmmod hello_sys
root@laikc-virtual:/home/laikc/demo#
root@laikc-virtual:/home/laikc/demo# dmesg
you can see the printk info
Kobject Abstraction
Allowing objects to be arranged into hierarchies.
NETLINK_KOBJECT_UEVENT (since Linux 2.6.10)
Kernel messages to user space.
Ref. The zen of kobjects
Ref. Everything you never wanted to know about kobjects, ksets, and ktypes
Ref. Sysfs in Linux Kernel – Linux Device Driver Tutorial Part 11, by EmbeTronicX
至於 class…OOP 觀念很重要!!!
有興趣的 可以參考 Linux设备模型(7)_Class
You can download the other kernel sources
from
https://www.kernel.org/pub/linux/kernel/v2.6/
e.g.,
wget http://…/linux-2.6.29.1.tar.gz
If u use your new kernel source, you may use QEMU to simulate virtual machine and run your new Linux.
Linux 3.8 New ProcFS
If you need procfs, NOTICE that new linux kernel procfs is different
hello_proc.c
Write Makefile
Notice that TAB key and strip
Makefile
laikc@laikc-virtual-machine:~$ make
make -C /lib/modules/3.8.0-35-generic/build M=/home/laikc modules
make[1]: Entering directory /usr/src/linux-headers-3.8.0-35-generic' Building modules, stage 2. MODPOST 1 modules make[1]: Leaving directory
/usr/src/linux-headers-3.8.0-35-generic'
strip -g hello_proc.ko
Insert module
laikc@laikc-virtual-machine:~$ sudo insmod hello_proc.ko
[sudo] password for laikc:
laikc@laikc-virtual-machine:~$ cat /proc/Hello
Hello…Linux-3.8.0-35-generic-#50-Ubuntu SMP Tue Dec 3 01:25:33 UTC 2013
Linux Device Driver Tutorial Part 9 – Procfs in Linux
You can request dynamic assignment of a major number. If the argument major is set to 0 when you call register_chrdev, the function selects a free number and returns it.
Register Object and Use Object
Device File Creation – Linux Device Driver Tutorial Part 5, by by SLR
Linux Device Driver Tutorial Programming – Linux Device Driver Tutorial Part 7, by EmbeTronicX
OOP concept!
Register Objects and Use Objects
For example,
procfs:
define class hello_proc_fops
static const struct file_operations hello_proc_fops
EXPORT_SYMBOL () is a macro.
It makes a symbol accessible to dynamically loaded modules (provided that said modules add an extern declaration).
struct file_operations is an important data structure!
socket layer (Appendix proto_ops)
AP client user mode<->kernel mode: socket(AF_INET, …)<–>IPv4 inet_stream_ops<->Route, etc.<->Device Driver<->Device<–->network <––> AP server
藍色都是 kernel mode
Appendix: proto_ops
ipv4, ipv6, netfilter, packet, netlink,bridge…
Makefile 中的 $@, $^, $< , $? 符號
HW:
Futher Reading:
udevadm - udev management tool, udevadm monitor
Softirq in Linux Device Driver – Linux Device Driver Tutorial Part 45
主要 Multi-core processor 增進效能
What is RCU? – “Read, Copy, Update”
Using Kernel Timer In Linux Device Driver – Linux Device Driver Tutorial Part 26, by SLR
GPIO Linux Device Driver (GPIO Interrupt) – Linux Device Driver Tutorial Part 36, by SLR
有關 mmap
How to mmap a Linux kernel buffer to user space?
Frame buffer device initialization and setup routines
linux+v2.6.12/drivers/video/fbmem.c
1027static struct file_operations fb_fops = {
1028 .owner = THIS_MODULE,
1029 .read = fb_read,
1030 .write = fb_write,
1031 .ioctl = fb_ioctl,
1032#ifdef CONFIG_COMPAT
1033 .compat_ioctl = fb_compat_ioctl,
1034#endif
1035 .mmap = fb_mmap,
1036 .open = fb_open,
1037 .release = fb_release,
1038#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
1039 .get_unmapped_area = get_fb_unmapped_area,
1040#endif
1041};
Linux wait queue:
https://lxr.linux.no/linux+v6.0.9/include/linux/wait.h#L61
#define __WAITQUEUE_INITIALIZER(name, tsk) {
50 .private = tsk,
51 .func = default_wake_function,
52 .entry = { NULL, NULL } }
53
54#define DECLARE_WAITQUEUE(name, tsk)
55 struct wait_queue_entry name = __WAITQUEUE_INITIALIZER(name, tsk)
56
57#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {
58 .lock = __SPIN_LOCK_UNLOCKED(name.lock),
59 .head = LIST_HEAD_INIT(name.head) }
60
61#define DECLARE_WAIT_QUEUE_HEAD(name)
62 struct wait_queue_head name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
63
extern void __init_waitqueue_head(struct wait_queue_head *wq_head, const char *name, struct lock_class_key *);
#define init_waitqueue_head(wq_head)
do {
static struct lock_class_key __key;
__init_waitqueue_head((wq_head), #wq_head, &__key);
} while (0)
void __init_waitqueue_head(struct wait_queue_head *wq_head, const char *name, struct lock_class_key *key)
{
spin_lock_init(&wq_head->lock);
lockdep_set_class_and_name(&wq_head->lock, key, name);
INIT_LIST_HEAD(&wq_head->head);
}
#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
143/**
144 * __wake_up - wake up threads blocked on a waitqueue.
145 * @wq_head: the waitqueue
146 * @mode: which threads
147 * @nr_exclusive: how many wake-one or wake-many threads to wake up
148 * @key: is directly passed to the wakeup function
149 *
150 * If this function wakes up a task, it executes a full memory barrier before
151 * accessing the task state.
152 */
153void __wake_up(struct wait_queue_head *wq_head, unsigned int mode,
154 int nr_exclusive, void *key)
155{
156 __wake_up_common_lock(wq_head, mode, nr_exclusive, 0, key);
157}
https://lxr.linux.no/linux+v6.0.9/include/linux/spinlock.h#L347