当前位置:   article > 正文

Linux 中的进程与线程(一)_linux mission-control

linux mission-control

首先来区分一下进程和线程,新手上路,各位大神多多指教;
在这里插入图片描述

在中断服务程序、内核软中断服务程序以及其他设备驱动程序的设计中,注意不能让这些函数嵌套太深,不宜使用太多、太大的局部变量,入以下例子;

int function()
{
	char buf [1024];  //buf为局部变量,在堆栈中消耗了1KB
	...............
}
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
进程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);
  • 1
  • 2
  • 3
  • 4
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

除了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");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

实际效果:

............................
[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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

那怎么根据输入的进程名得到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");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

效果如下,成功将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 ]
  • 1
  • 2
  • 3
  • 4
  • 5

我们之前的提的问题,如何知晓某一特定进程的状态;
对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 */
  • 1
  • 2
  • 3

到这里怎么获取一个进程的状态就告一段落了;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/185432
推荐阅读
相关标签
  

闽ICP备14008679号