文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>内核线程

内核线程

时间:2006-03-06  来源:ChinaE_OS

内核线程

内核线程只运行在内核态,普通进程既可以运行在内核态也可以运行在用户态。因为内核线程运行在内核态,所以只访问大于PAGE_OFFSET以上的线性地址空间,而普通进程使用所有的4G空间。

 

1:内核线程的创建时间:

kernel_thread创建内核线程。

int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)

{

    struct pt_regs regs;

 

    memset(&regs, 0, sizeof(regs));

 

    regs.ebx = (unsigned long) fn;

    regs.edx = (unsigned long) arg;

 

    regs.xds = __USER_DS;

    regs.xes = __USER_DS;

    regs.orig_eax = -1;

    regs.eip = (unsigned long) kernel_thread_helper;

    regs.xcs = __KERNEL_CS;

    regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;

 

    /* Ok, create the new process.. */

    return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);

}

CLONE_VM:避免复制正在运行进程的页表。

CLONE_UNTRACED:保证即使父进程正在被调试,内核线程也不会被调试。

Regs:内核栈中的一个地址,通过这个地址,可以找到内核栈CPU寄存器的初始化值。

(1)   通过fn和arg分别设置ebx和edx寄存器。

(2)   kernel_thread_helper是一个汇编函数,代码如下:

extern void kernel_thread_helper(void);

__asm__(".section .text\n"

    ".align 4\n"

    "kernel_thread_helper:\n\t"

    "movl %edx,%eax\n\t"

    "pushl %edx\n\t"

    "call *%ebx\n\t"

    "pushl %eax\n\t"

    "call do_exit\n"

    ".previous");

所以内核线程是通过fn函数开始的。当结束时,执行系统调用do_exit.
添加评论
14:54  |  固定链接 | 引用通告 (0) | 记录它 | 计算机与 Internet
固定链接 关闭
http://spaces.msn.com/chinaos040930/blog/cns!887077BC2C579359!154.entry
Linux创建进程(3)copy_process的下半部分

(14)        调用sched_fork,完成新进程调度其数据结构的初始化工作。该函数设置进程的状态为TASK_RUNNING,并且设置thread_info的preempt_count为1,关系内核可抢占。同时,为了调度公平,子进程和父进程共享父进程的时间片。

     Sched_fork的代码如下(kernel/sched.c):

void fastcall sched_fork(task_t *p, int clone_flags)

{

    int cpu = get_cpu();

 

#ifdef CONFIG_SMP

    cpu = sched_balance_self(cpu, SD_BALANCE_FORK);

#endif

    set_task_cpu(p, cpu);

 

    /*

     * We mark the process as running here, but have not actually

     * inserted it onto the runqueue yet. This guarantees that

     * nobody will actually run it, and a signal or other external

     * event cannot wake it up and insert it on the runqueue either.

     */

    p->state = TASK_RUNNING;

    INIT_LIST_HEAD(&p->run_list);

    p->array = NULL;

#ifdef CONFIG_SCHEDSTATS

    memset(&p->sched_info, 0, sizeof(p->sched_info));

#endif

#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)

    p->oncpu = 0;

#endif

#ifdef CONFIG_PREEMPT

    /* Want to start with kernel preemption disabled. */

    p->thread_info->preempt_count = 1;

#endif

    /*

     * Share the timeslice between parent and child, thus the

     * total amount of pending timeslices in the system doesn't change,

     * resulting in more scheduling fairness.

     */

    local_irq_disable();

    p->time_slice = (current->time_slice + 1) >> 1;

    /*

     * The remainder of the first timeslice might be recovered by

     * the parent if the child exits early enough.

     */

    p->first_time_slice = 1;

    current->time_slice >>= 1;

    p->timestamp = sched_clock();

    if (unlikely(!current->time_slice)) {

       /*

        * This case is rare, it happens when the parent has only

        * a single jiffy left from its timeslice. Taking the

        * runqueue lock is not a problem.

        */

       current->time_slice = 1;

       scheduler_tick();

    }

    local_irq_enable();

    put_cpu();

}

(15)        设置新进程thread_info的CPU域为smp_processor_id()返回的当前CPU.

p->cpus_allowed = current->cpus_allowed;

    if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed)))

        set_task_cpu(p, smp_processor_id());

(16)        设置父子关系。

/* CLONE_PARENT re-uses the old parent */

    if (clone_flags & (CLONE_PARENT|CLONE_THREAD))

        p->real_parent = current->real_parent;

    else

        p->real_parent = current;

    p->parent = p->real_parent;

(17)        如果设置CLONE_THREAD,子进程属于父进程所在组。

if (clone_flags & CLONE_THREAD) {

         spin_lock(&current->sighand->siglock);

         /*

          * Important: if an exit-all has been started then

          * do not create this new thread - the whole thread

          * group is supposed to exit anyway.

          */

         if (current->signal->flags & SIGNAL_GROUP_EXIT) {

              spin_unlock(&current->sighand->siglock);

              write_unlock_irq(&tasklist_lock);

              retval = -EAGAIN;

              goto bad_fork_cleanup_namespace;

         }

         p->group_leader = current->group_leader;

 

         if (current->signal->group_stop_count > 0) {

              /*

               * There is an all-stop in progress for the group.

               * We ourselves will stop as soon as we check signals.

               * Make the new thread part of that group stop too.

               */

              current->signal->group_stop_count++;

              set_tsk_thread_flag(p, TIF_SIGPENDING);

         }

 

         if (!cputime_eq(current->signal->it_virt_expires,

                   cputime_zero) ||

             !cputime_eq(current->signal->it_prof_expires,

                   cputime_zero) ||

             current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY ||

             !list_empty(&current->signal->cpu_timers[0]) ||

             !list_empty(&current->signal->cpu_timers[1]) ||

             !list_empty(&current->signal->cpu_timers[2])) {

              /*

               * Have child wake up on its first tick to check

               * for process CPU timers.

               */

              p->it_prof_expires = jiffies_to_cputime(1);

         }

 

         spin_unlock(&current->sighand->siglock);

     }

(18)        使用SET_LINKS宏将新进程描述符插入进程队列。如果子进程需要被跟踪,设置p->parent为current->parent,并且将子进程插入调试器跟踪队列。

     SET_LINKS(p);

if (unlikely(p->ptrace & PT_PTRACED))

        __ptrace_link(p, current->parent);

     SET_LINKS宏定义如下

#define SET_LINKS(p) do {                   \

    if (thread_group_leader(p))             \

        list_add_tail(&(p)->tasks,&init_task.tasks);    \

    add_parent(p, (p)->parent);             \

    } while (0)

   

(19)        调用attach_pid将新进程的进程描述符的PID插入到pidhash[PIDTYPE_PID]哈西表。

attach_pid(p, PIDTYPE_PID, p->pid);

    attach_pid(p, PIDTYPE_TGID, p->tgid);

    if (thread_group_leader(p)) {

        attach_pid(p, PIDTYPE_PGID, process_group(p));

        attach_pid(p, PIDTYPE_SID, p->signal->session);

        if (p->pid)

            __get_cpu_var(process_counts)++;

    }

(20)        新进程加入到进程组后,nr_threads++

(21)        为了跟踪创建的进程,total_forks++

返回子进程的task_struct.
相关阅读 更多 +
排行榜 更多 +
滑梯女王最新版

滑梯女王最新版

休闲益智 下载
逻辑方块手机版

逻辑方块手机版

休闲益智 下载
精灵风暴太阳神手机版

精灵风暴太阳神手机版

休闲益智 下载