赞
踩
首先来区分一下进程和线程,新手上路,各位大神多多指教;
在中断服务程序、内核软中断服务程序以及其他设备驱动程序的设计中,注意不能让这些函数嵌套太深,不宜使用太多、太大的局部变量,入以下例子;
int function()
{
char buf [1024]; //buf为局部变量,在堆栈中消耗了1KB
...............
}
进程task_struct结构以及系统空间堆栈的特殊安排,决定了内核中的一些宏定义;
#define THREAD_SIZE (2*PAGE_SIZE)
//2的1次方个PAGE_SIZE
#define alloc_task_struct() (struct_task_struct*)get_free_pages(GFP_KERNEL,1);
#define free_task_struct(p) free_pages((unsigned long) (p), 1);
static __always_inline struct task_struct *get_current(void)
{
unsigned long sp_el0;
asm ("mrs %0, sp_el0" : "=r" (sp_el0));
return (struct task_struct *)sp_el0;
}
#define current get_current()
current.h定义了一个宏操作指向当前进程的task_struct结构的指针;
AND指令需要4个CPU时钟周期,从寄存器到寄存器MOV指令只需要2个时钟周期;
task_struct结构体在include/linux/sched.h中给出定义,太大了就不往这里粘贴了,一起学一学重要的数据结构;
#ifdef CONFIG_THREAD_INFO_IN_TASK /* * For reasons of header soup (see current_thread_info()), this * must be the first element of task_struct. */ struct thread_info thread_info; #endif /* -1 unrunnable, 0 runnable, >0 stopped: */ volatile long state; /* Used in tsk->state: */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 /* Used in tsk->exit_state: */ #define EXIT_DEAD 16 #define EXIT_ZOMBIE 32 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) /* Convenience macros for the sake of set_current_state: */ #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) #define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
state表示进程的当前状态,其各自含义如下所示;
代码中的flag也反映进程管理有关的其他信息sched.h;
/* * Per process flags */ #define PF_IDLE 0x00000002 /* I am an IDLE thread */ #define PF_EXITING 0x00000004 /* Getting shut down */ #define PF_EXITPIDONE 0x00000008 /* PI exit done on shut down */ #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ #define PF_FORKNOEXEC 0x00000040 /* Forked but didn't exec */ #define PF_MCE_PROCESS 0x00000080 /* Process policy on mce errors */ #define PF_SUPERPRIV 0x00000100 /* Used super-user privileges */ #define PF_DUMPCORE 0x00000200 /* Dumped core */ #define PF_SIGNALED 0x00000400 /* Killed by a signal */ #define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_NPROC_EXCEEDED 0x00001000 /* set_user() noticed that RLIMIT_NPROC was exceeded */ #define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */ #define PF_USED_ASYNC 0x00004000 /* Used async_schedule*(), used by module init */ #define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */ #define PF_FROZEN 0x00010000 /* Frozen for system suspend */ #define PF_KSWAPD 0x00020000 /* I am kswapd */ #define PF_MEMALLOC_NOFS 0x00040000 /* All allocation requests will inherit GFP_NOFS */ #define PF_MEMALLOC_NOIO 0x00080000 /* All allocation requests will inherit GFP_NOIO */ #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ #define PF_KTHREAD 0x00200000 /* I am a kernel thread */ #define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */ #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ #define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ #define PF_SUSPEND_TASK 0x80000000 /* This thread called freeze_processes() and should not be frozen */
除了state和flag之外,反映当前状态的还有一些,比如说sigpending、counter、nee_sched、add_limit、Personality等;
说了这么多,我在内核驱动中如何获取线程的状态呢?
从简单到复杂吧,先看看怎么遍历所有的线程;
//thread.c #include <linux/module.h> // Needed by all modules #include <linux/kernel.h> // KERN_INFO #include <linux/sched.h> // for_each_process, pr_info void procs_info_print(void) { struct task_struct* task_list; size_t process_counter = 0; for_each_process(task_list) { pr_info("== %s [%d]\n", task_list->comm, task_list->pid); ++process_counter; } printk(KERN_INFO "== Number of process: %zu\n", process_counter); } int init_module(void) { printk(KERN_INFO "[ INIT ==\n"); procs_info_print(); return 0; } void cleanup_module(void) { printk(KERN_INFO "== CLEANUP ]\n"); } MODULE_LICENSE("GPL");
Makefile:
obj-m += thread.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
实际效果:
............................ [10585.922885] == telepathy-indic [2210] [10585.922885] == mission-control [2218] [10585.922886] == zeitgeist-daemo [2246] [10585.922886] == zeitgeist-fts [2252] [10585.922887] == zeitgeist-datah [2254] [10585.922888] == cat [2265] [10585.922888] == cupsd [2279] [10585.922889] == update-notifier [2311] [10585.922890] == deja-dup-monito [2333] [10585.922891] == gnome-terminal [2341] [10585.922891] == gnome-pty-helpe [2351] [10585.922892] == bash [2352] [10585.922893] == kworker/u256:1 [3710] [10585.922893] == kworker/u256:2 [3908] [10585.922894] == sudo [4776] [10585.922894] == insmod [4777] [10585.922895] == Number of process: 226
那怎么根据输入的进程名得到task_struct结构体呢;
//thread.c #include <linux/module.h> // Needed by all modules #include <linux/kernel.h> // KERN_INFO #include <linux/sched.h> // for_each_process, pr_info #include <linux/pid.h> //find_get_pid #include <linux/string.h> struct task_struct *find_task(char *find_name) { struct task_struct* task_list; size_t process_counter = 0; for_each_process(task_list) { // pr_info("== %s [%d]\n", task_list->comm, task_list->pid); if(!strcmp(task_list->comm,find_name)){ printk("%s (pid=%d, comm=%s)\n", __func__, task_list->pid, task_list->comm); return task_list; } else{ ++process_counter; } } printk(KERN_INFO "== Number of process: %zu\n", process_counter); return 0; } static int __init thread_init(void) { char *find_name = "kthreadd"; struct task_struct* task; printk(KERN_INFO "[ INIT ==\n"); printk("%s (pid=%d, comm=%s)\n", __func__, current->pid, current->comm); task = find_task(find_name); // printk("%s (pid=%d, comm=%s)\n", __func__, task->pid, task->comm); printk("the thread state is: %lu %d\n",task->state,task->flags); return 0; } static void __exit thread_exit(void) { printk(KERN_INFO "== CLEANUP ]\n"); } module_init(thread_init); module_exit(thread_exit); // 模块信息 MODULE_LICENSE("GPL"); MODULE_AUTHOR("curtis li");
效果如下,成功将task_struckt指针返回到thread_init:
[16924.131582] [ INIT ==
[16924.131584] thread_init (pid=14615, comm=insmod)
[16924.131586] find_task (pid=2, comm=kthreadd)
[16924.131586] the thread state is: 1 2129984
[17549.520333] == CLEANUP ]
我们之前的提的问题,如何知晓某一特定进程的状态;
对dmesg信息进行分析,此进程的状态为(1 --> #define TASK_INTERRUPTIBLE 1 )也就是说当前出于stop的状态,可以被唤醒;flags的值为 2129984 --> 0x208040,对号入座查找flags的宏;
#define PF_FORKNOEXEC 0x00000040 /* Forked but didn't exec */
#define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
到这里怎么获取一个进程的状态就告一段落了;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。