Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186643
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 418
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-26 22:37
文章存档

2015年(4)

2014年(27)

2013年(9)

我的朋友

分类: LINUX

2013-11-22 22:27:35

      今天定位一个问题,本来是用ftrace查看调度轨迹,希望能看出有什么一场调度,结果偶然看到系统中存在两个swapper进程,一个进程号为0,一个进程号为3。进程号为0是正常情况下都应该有的,但是对于一个单核cpu来说,竟然还有一个3号swapper进程,就显得太奇怪了,于是看看代码,最后发现竟然是kernel_thread的问题。
      为了定位问题,在初始化start_kernel中调用了一个函数,函数中使用了kernel_thread,创建一个新的内核线程,怀疑这个swapper就是创建的这个线程。于是查看kthread_create怎么给线程命名,代码如下:(所有代码内核版本均为3.12)

点击(此处)折叠或打开

  1. #define kthread_create(threadfn, data, namefmt, arg...) \
  2.     kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)
继续查看kthread_create_on_node函数,如下:

点击(此处)折叠或打开

  1. /**
  2.  * kthread_create_on_node - create a kthread.
  3.  * @threadfn: the function to run until signal_pending(current).
  4.  * @data: data ptr for @threadfn.
  5.  * @node: memory node number.
  6.  * @namefmt: printf-style name for the thread.
  7.  */

  8. struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
  9.                      void *data, int node,
  10.                      const char namefmt[],
  11.                      ...)
  12. {
  13.     struct kthread_create_info create;

  14.     create.threadfn = threadfn;
  15.     create.data = data;
  16.     create.node = node;
  17.     init_completion(&create.done);

  18.     spin_lock(&kthread_create_lock);
  19.     list_add_tail(&create.list, &kthread_create_list);
  20.     spin_unlock(&kthread_create_lock);

  21.     wake_up_process(kthreadd_task);
  22.     wait_for_completion(&create.done);

  23.     if (!IS_ERR(create.result)) {
  24.         static const struct sched_param param = { .sched_priority = 0 };
  25.         va_list args;

  26.         va_start(args, namefmt);
  27.         vsnprintf(create.result->comm, sizeof(create.result->comm),
  28.              namefmt, args);
  29.         va_end(args);
  30.         /*
  31.          * root may have changed our (kthreadd
        将name复制给了create.result->comm字段,那么create.result->comm又是什么呢?继续看代码,

点击(此处)折叠或打开

  1. struct kthread_create_info
  2. {
  3.     /* Information passed to kthread() from kthreadd. */
  4.     int (*threadfn)(void *data);
  5.     void *data;
  6.     int node;

  7.     /* Result passed back to kthread_create() from kthreadd. */
  8.     struct task_struct *result;
  9.     struct completion done;

  10.     struct list_head list;
  11. };
        result字段是task_struct结构指针,看到这里,kthread_create怎样给新创建的函数取名流程也就一清二楚了。
        那么kernel_thread又是怎么取名字的呢?为什么我们用kernel_thread创建的线程名字会是swapper呢?继续看代码:
   

点击(此处)折叠或打开

  1. pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
  2. {
  3.     return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
  4.         (unsigned long)arg, NULL, NULL);
  5. }
        可以看到kernel_thread直接调用do_fork函数,而do_fork函数我们知道,就是将父进程的地址空间直接复制给子进程,所以名字也是一样的,而我们当时调用kernel_thread的时间比较早,是在初始化时由swapper创建的,所以继承了swapper的名字,也就不足为奇了。
        那么接下来的问题就是怎么给kernel_thread创建的线程取名呢?内核还有一个daemonize的接口,专门用来取名,在kernel_thread的函数指针所指向的函数中调用daemonize函数,然后重新编译内核,启动,发现3号线程的名字果然就是自己用daemonize所取得线程名字了。

        

阅读(3943) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~