1. 创建一个进程
fork()系统调用通过复制一个现有的进程来创建一个新进程。 fork()系统调用从内核返回了2次,一次回到父进程,一次回到子进程。fork() 实际上是由clone()系统调用来实现的。 vfork()除了不拷贝父进程的页表项外,和fork功能相同
2. Linux把进程的列表放在叫做任务队列(task list)的双向循环链表中。
链表中的每一项都是类型为task_struct,称为进程描述符的结构(定义在linux/sched.h中)。进程描述符包含一个具体进程的所有信息。
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
void *stack;
atomic_t usage;
unsigned int flags; /* per process flags, defined below */
unsigned int ptrace;
#ifdef CONFIG_SMP
struct task_struct *wake_entry;
int on_cpu;
#endif
int on_rq;
int prio, static_prio, normal_prio;
unsigned int rt_priority;
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
pid_t pid; //进程的pid
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->real_parent->pid)
*/
struct task_struct *real_parent; /* real parent process */
struct task_struct *parent; /* recipient of SIGCHLD, wait4() reports */
/*
* children/sibling forms the list of my natural children
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
struct task_struct *group_leader; /* threadgroup leader */
...............
}
Linux 通过slab分配器分配task_struct结构。在(进程的内核栈)栈顶或栈底创建一个新的结构struct thread_info.
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
__u32 flags; /* low level flags */
__u32 status; /* thread synchronous flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable,
<0 => BUG */
此结构中task指向该任务实际的task_struct的指针。
3. 进程的优先级
Linux采用2中不同的优先级范围:
a) nice值,-20到+19.nice 值越大优先级越低,默认是0.
b) 实时优先级,从0到99.任何实时优先级都比不同进程高。值越大优先级越高。
4. Linux的调度算法
Linux的调度器是以模块方式提供的,这样做的目的是允许不同类型进程可以有针对性的选择调度算法。这种某块化的结构成为 调度器类。
完全公平调度(CFS)是一个针对普通进程的调度类。