Chinaunix首页 | 论坛 | 博客
  • 博客访问: 663280
  • 博文数量: 121
  • 博客积分: 4034
  • 博客等级: 上校
  • 技术积分: 1439
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-28 12:42
文章分类

全部博文(121)

文章存档

2017年(8)

2016年(10)

2013年(2)

2012年(3)

2011年(18)

2010年(80)

分类: LINUX

2010-07-22 15:41:13

函数kernel_thread

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
flags参数是什莫?
kernel_thread()这样调用do_fork():
do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
这也是kernel_thread()唯一使用flags的地方,能够看出,无论怎样CLONE_VM|CLONE_UNTRACED两个flag都是要用到的。
察看CLONE_VM的定义能够发现:

/*
* cloning flags:
*/
#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
#define CLONE_VM 0x00000100 /* set if VM shared between processes */
#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
#define CLONE_FILES 0x00000400
/* set if open files shared between processes */
#define CLONE_SIGHAND 0x00000800
/* set if signal handlers and blocked signals shared */
#define CLONE_IDLETASK 0x00001000
/* set if new pid should be 0 (kernel only)*/
#define CLONE_PTRACE 0x00002000
/* set if we want to let tracing continue on the child too */
#define CLONE_VFORK 0x00004000
/* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000
/* set if we want to have the same parent as the cloner */
#define CLONE_THREAD 0x00010000 /* Same thread group? */
#define CLONE_NEWNS 0x00020000 /* New namespace group? */
#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
#define CLONE_UNTRACED 0x00800000
/* set if the tracing process can’t force CLONE_PTRACE on this clone */
#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
#define CLONE_STOPPED 0x02000000 /* Start in stopped state */
/*
* List of flags we want to share for kernel threads,
* if only because they are not used by them anyway.
*/
#define CLONE_KERNEL (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)

内核线程常用的flags就是CLONE_KERNEL,为什莫这样?肯定更有很多具体的细节。

用kernel_thread创建的线程复制了父进程的资源(像fork), 而有些资源(如mm)对于内核线程是不需要的, daemonize用来释放这些资源。


schedule_timeout()

schedule_timeout() -- 将当前进程推后执行

fastcall signed long __sched schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
schedule();
goto out;
default:
if (timeout < 0) {
printk(KERN_ERR "schedule_timeout: wrong timeout "
"value %lx\n", timeout);
dump_stack();
current->state = TASK_RUNNING;
goto out;
}
}
expire = timeout + jiffies;
setup_timer(&timer, process_timeout, (unsigned long)current);
__mod_timer(&timer, expire);
schedule();
del_singleshot_timer_sync(&timer);
timeout = expire - jiffies;
out:
return timeout < 0 ? 0 : timeout;
}

source code 1

 1 #include 
2 #include
3 #include
4 #include "rc2032dx.h"
5
6 int check_button(void)
7 {
8 if((GPIO_DATA_INPUT_HIGH & GPIO_BUTTON_POW) == 0)
9 {
10 return 0;
11 }
12 else
13 {
14 return 1;
15 }
16 }
17
18 static int noop(void *dummy)
19 {
20 int i = 0;
21 int putton_flash = 0;
22 printk("[dancy log:%d]insmod pushbutton.\n",__LINE__);
23 daemonize("pushbutton");
24 GPIO_DATA_ENABLE_HIGH &= ~GPIO_BUTTON_POW;
25 GPIO_DATA_ENABLE_LOW |= GPIO_FOR_REBOOT;
26 GPIO_DATA_OUTPUT_LOW &= ~GPIO_FOR_REBOOT;
27 while(1)
28 {
29 if(check_button()==0)
30 {
31 putton_flash = 1;
32 i++;
33 if(i >= 20)
34 {
35 printk("reset board.\n");
36 GPIO_DATA_OUTPUT_LOW |= GPIO_FOR_REBOOT;
37 }
38 }
39 else
40 {
41 if(putton_flash == 1)
42 {
43 if(i < 20)
44 {
45 printk("turn off led.\n");
46 }
47 else
48 {
49 printk("reset board.\n");
50 GPIO_DATA_OUTPUT_LOW |= GPIO_FOR_REBOOT;
51 }
52 }
53 i = 0;
54 putton_flash = 0;
55 }
56 set_current_state(TASK_INTERRUPTIBLE);
57 schedule_timeout(100);
58 }
59 return 0;
60 }
61
62 static int pushbutton_init(void)
63 {
64 printk("[dancy log:%d]insmod pushbutton.\n",__LINE__);
65 kernel_thread(noop, NULL, CLONE_KERNEL | SIGCHLD);
66 return 0;
67 }
68
69 static void pushbutton_exit(void) {}
70 module_init(pushbutton_init);
71 module_exit(pushbutton_exit);


source code 2

#include 
#include

static int noop(void *dummy)
{
int i = 0;
daemonize("mythread");
while(i++ < 5)
{
printk("current->mm = %p\n", current->mm);
printk("current->active_mm = %p\n", current->active_mm);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(10 * HZ);
}
return 0;
}

static int test_init(void)
{
kernel_thread(noop, NULL, CLONE_KERNEL | SIGCHLD);
return 0;
}

static void test_exit(void) {}
module_init(test_init);
module_exit(test_exit);


Makefile

 1 CROSS_COMPILE=/opt/toolchains/uclibc-crosstools-gcc-4.2.3-3/usr/bin
/mips-linux-uclibc-
2 KER=../../../../kernel/linux/
3 obj-m := pushbutton.o
4 pushbutton.ko:pushbutton.c
5 $(MAKE) -C $(KER) CROSS_COMPILE=$(CROSS_COMPILE) SUBDIRS=$(shell pwd)
modules
6 clean:
7 rm *.ko *.o Module.symvers pushbutton.mod.c .*.cmd .tmp_versions -fr
阅读(1914) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~