linux内核设计与实现(一)

进程管理

定义

  • 进程就是处于执行期间的程序(还包括打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间,及一个或多个执行的线程,存放全局变量的数据段等)。进程是处于执行期的程序以及相关资源的总称。

特性

  • 线程是进程中活动的对象。每个线程都拥有独立的程序计数器、进程栈、进程寄存器。
  • 内核的调度对象是线程
  • 进程提供两种虚拟机之:虚拟处理器,虚拟内存。
  • 同一个进程里的线程共享虚拟内存,但各自拥有独立的虚拟处理器

进程描述符及任务结构

内核把进程的列表存放在任务队列(双向循环列表)中。
链表中的每一项都是类型为 task_struct (进程描述符)。
进程描述符包含一个具体进程的所有信息。
  • 分配进程描述符
    linux通过slab分配器分配task_struct机构。这样可以达到对象复用和缓存着色的目的

进程状态

系统中的每个进程必然处于五种进程状态中的一种:

  • TASK_RUNNING —— 进程是可执行的:正在执行或者在运行队列中等待执行。
  • TASK_INTERRUPTIBLE —— 进程正在睡眠,等待某些条件的达成。
  • TASK_UNINTERRUPTIBLE —— 等待时进程不可中断,对信号不作响应。
  • _TASK_TRACKED —— 被其他进程跟踪的进程。
  • _TASK_STOPED —— 进程停止执行,进程没有投入运行,也不能运行。

设置当前进程状态

set_task_state(task,state);    /*将任务task的状态 设置为 state*/
set_current_state(state);   /* 与上面函数等价 */

在SMP系统中使用这个函数;
否则等价于

task->state = state;

进程上下文

当一个程序调执行了系统调用或者触发了某个异常,它就陷入了内核空间。此时,我们称内核“代表进程执行”并处于进程上下文中

进程家族树

每个进程必有一个父进程,每个进程可以有0个或者多个子进程。进程间的关系存在进程描述符中。每个task_struct 都包含有一个指向其父进程task_struct的指针parent。还有一个称为chaildren的子进程链表。
对于当前进程,可以通过如下代码获取其父进程的进程描述符:

struct task_struct  *my_parent = current->parent;

访问子进程:

struct  task_struct  *task;
struct list_head  *list;
list_for_each(list, &current->children)
{
	task = list_entry(list,struct task_struct,sibling);//task指向当前的某一个进程
}

init进程的进程符是init_task(静态分配)。获取所有进程之间的关系可用如下代码:

struct task_struct *task;
for(task = current;task != init_task;task = task->parent)
	;
	/*task最终指向init进程*/

通过进程链表获指定进程,如下:

list_entry(task->tasks.next,struct task_struct,tasks) //获取下一个进程
list_entry(task->tasks.prev,struct task_struct,task)//获取上一个进程

其中:task.next task.prev 都是宏定义。
而for_each_process(task)宏可以访问整个队列。每次访问任务指针都会指向链表中的下一个元素。

struct  task_struct *task;
for_each_process(task)
{
	/*打印出每一个任务的名字和PID*/
	printk("%s [%d ]\n",task->com,task->pid);
}

进程创建

调用了两个函数:fork(),exec();

  • 过程:fork()通过拷贝当前进程创建一个子进程。exec()函数负责读取可执行文件并将其在如地址空间运行。
  • 特点:fork()之后的子进程与父进程的PID(每个进程都是唯一的)、PPID(父进程的进程号)和某些资源和统计量(例如:挂起的信号)。

写时拷贝

  • 定义:写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址进程空间,而是让父进程,子进程烘箱一个拷贝。只有在写入的时候,数据才会被复制。

fork()

P27

vfork()

p28

线程

在linux内核中线程都被当做进程实现。线程仅仅是与其他进程共享某些资源的进程。每个线程都拥有唯一隶属于自己的task_struct.

创建线程

与进程的区别在于clone()的参数不一样。指定了需要共享的资源。

进程终结

当一个进程终结时,内核释放它所占有的资源,并告知其父进程。
当父进程死于子进程之前,会自动找父进程。如果找不到就会让init进程做父进程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值