下文切换后的存储(硬件注册表、程序计数器等).
进程管理
现在,让我们来看看如何在 Linux 内管理进程.在很多情况下,进程都是动态创建并由一个动态分配的 task_struct 表示.一个例外是 init 进程本身,它总是存在并由一个静态分配的 task_struct 表示.在 ./linux/arch/i386/kernel/init_task.c 内可以找到这样的一个例子.
最大进程数
在 Linux 内虽然进程都是动态分配的,但还是需要考虑最大进程数.在内核内最大进程数是由一个称为 max_threads 的符号表示的,它可以在 ./linux/kernel/fork.c 内找到.可以通过 /proc/sys/kernel/threads-max 的 proc 文件系统从用户空间更改此值. |
Linux 内所有进程的分配有两种方式.第一种方式是通过一个哈希表,由 PID 值进行哈希计算得到;第二种方式是通过双链循环表.循环表非常适合于对任务列表进行迭代. 列表是循环的,没有头或尾;但是 init_task 总是存在, 可以将其用作继续向前迭代的一个锚点.让我们来看一个遍历当前任务集的例子.
任务列表无法从用户空间访问,但该问题很容易解决,方法是以模块形式向内核内插入代码.清单 2 中所示的是一个很简单的程序,它会迭代任务列表并会提供有关每个任务的少量信息(name、pid 和 parent 名).注意,在这里,此模块使用 printk 来发出结果.要查看具体的结果,可以通过 cat 实用工具(或实时的 tail -f /var/log/messages)查看 /var/log/messages 文件.next_task 函数是 sched.h 内的一个宏,它简化了任务列表的迭代(返回下一个任务的 task_struct 引用).
清单 2. 发出任务信息的简单内核模块(procsview.c)
#include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h>
int init_module( void ) { /* Set up the anchor point */ struct task_struct *task = &init_task;
/* Walk through the task list, until we hit the init_task again */ do {
printk( KERN_INFO "*** %s [%d] parent %sn", task->comm, task->pid, task->parent->comm );
} while ( (task = next_task(task)) != &init_task );
return 0;
}
void cleanup_module( void ) { return; }
|
可以用清单 3 所示的 Makefile 编译此模块.在编译时,可以用 insmod procsview.ko 插入模块对象,也可以用 rmmod procsview 删除它.
清单 3. 用来构建内核模块的 Makefile
obj-m = procsview.o
KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd)
default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
插入后,/var/log/messages 可显示输出,如下所示.从中可以看到,这里有一个空闲任务(称为 swapper)和 init 任务(pid 1).
Nov 12 22:19:51 mtj-desktop kernel: [8503.873310] *** swapper [0] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904182] *** init [1] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904215] *** kthreadd [2] parent swapper
Nov 12 22:19:51 mtj-desktop kernel: [8503.904233] *** migration/0 [3] parent kthreadd
...
|
注意,还可以标识当前正在运行的任务.Linux 维护一个称为 current 的符号,代表的是当前运行的进程(类型是 task_struct).如果在 init_module 的尾部插入如下这行代码:
printk( KERN_INFO, "Current task is %s [%d], current->comm, current->pid );
|
会看到:
Nov 12 22:48:45 mtj-desktop kernel: [10233.323662] Current task is insmod [6538]
|
注 |