定义

关于process,一个经典的定义是:

A process is a program in the midest of execution.

进程是对IO设备、处理器和主存的抽象,操作系统给每个进程提供它们独占CPU和主存的幻觉。

进程在内核中的表示

内核为每个进程维护一个进程描述符(struct task_struct)结构,它的定义在./include/linux/sched.h中。在这个结构中记录了描述进程状态的信息,如:打开文件表,进程地址空间,待决信号,进程的状态。。。

struct task_struct {
    struct files_struct *files;
    struct mm_struct *mm;
    struct signal_struct *signal;
    volatile long state;
    ...
};

进程状态

state描述了当前进程的状态,进程可能处于五种情况之一:

  • TASK_RUNNING
  • TASK_INTERRUPTIBLE
  • TASK_UNINTERRUPTIBLE
  • __TASK_TRACED
  • __TASK_STOPPED

注意进程处于TASK_UNINTERRUPTIBLE状态时它不能被信号唤醒。

进程的创建

Linux使用clone()系统调用来实现进程的创建,它会调用do_fork()(./kernel/fork.c),do_fork()又会调用copy_process(),这里包含了真正有趣的工作:

// This creates a new process as a copy of the old one,
// it copies the registers, and all the appropriate
// parts of the process environment.

static struct task_struct *copy_process(unsigned long clone_flags,
    unsigned long stack_start, struct pt_regs *regs, 
    unsigned long stack_size, int __user *child_tidptr,
    struct pid *pid, int _trace)
{
    struct task_struct *p;

    // 检查flags是否合法
    p = dup_task_struct(current); // 分配thread info/kernel stack和process descriptor,内容与父进程一致
    // 检查进程资源的限制
    // 子进程设置不同于父进程的一些字段
    sched_fork(p, clone_flags); // 设置调度相关的字段

    // 根据传递的flags标志确定哪些资源是共享,哪些资源需要复制 
    copt_semundo(clone_flags, p);
    copy_files(clone_flags, p);
    copy_fs(clone_flags, p);
    copy_signal(clong_flags, p);
    copy_mm(clone_flags, p);
    copy_namespaces(clone_flags, p);
    copy_io(clone_flags, p);

    // 初始化内核栈 
    copy_thread(clone_flags, stack_start, stack_size, p, regs);

    pid = alloc_pid(p->nsproxy->pid_ns);
    ...
}

由于使用了COW(Copy on Write)技术,fork()带来的开销其实只有父进程页表的复制和新进程描述符的建立。

Linux中的线程

linux并没有实现一个独立的线程概念,线程是通过进程来实现的,多个线程可以共享一些资源。

在unix系统中

线程的终止

A sad story,到了要结束的时候。结束的处理工作由do_exit()(./kernel/exit.c)来执行:

void do_exit(long code)
{
    exit_signals(tsk);  //设置PF_EXITING标志
    exit_mm(tsk);   //释放进程地址空间
    exit_sem(tsk);
    exit_files(tsk);
    exit_fs(tsk);
    exit_thread();
    ...

    exit_notify(tsk, group_dead);
    schedule(); 
}

参考

《Understanding the Linux Kernel》

《Linux Kernel Development》

Comments

Powered by Pelican. Booler's Adventure © 不贰 2014-2016