Linux内核设计与实现-进程管理

学习《Linux内核设计与实现》, 简单记录一些重要的概念,理清逻辑,如有偏差欢迎批评指正。

1 进程描述符及任务结构

    内核将进程的列表存放在任务队列(task list)中维护。任务队列是一个双向循环链表,链表的每一项都是类型为 task_struct (进程描述符 process descriptor)的结构体。

1.1 分配 task_struct

    Linux通过slab分配器分配  task_struct 结构, 在栈底(向下生长的栈)或栈顶(向上生长的栈)创建一个 thread_info 结构

struct thread_info {
	struct task_struct	*task;		/* main task structure */
	unsigned long		flags;		/* low level flags */
	__u32			status;		/* thread synchronous flags */
	__u32			cpu;
	int			preempt_count; /* 0 => preemptable, <0 => BUG */
	unsigned long		previous_sp;	/* sp of previous stack in case
						   of nested IRQ stacks */
	__u8			supervisor_stack[];
};

1.2 进程的状态

    系统中的进程必然处于以下五种状态之一, 进程的进程描述符中的status成员必然为下面五种状态之一:

- TASK_RUNNIG : 进程 1.正在执行 2.在运行队列中等待执行

- TASK_INTERRUPTABLE : 进程正在睡眠(被阻塞)

- TASK_UNITERRUPTABLE : 进程正在睡眠, 就算是收到信号也不会被唤醒

- __TASK_TRACED : 进程正在被其他进程跟踪

- __TASK_STOPPED : 进程停止执行,没有投入运行也不能投入运行

    

1.3 进程上下文

    当一个进程执行了系统调用或触发了某个异常, 进程会陷入内核空间。 (事实上进程只用通过这些对内核明确定义的接口才能陷入内核态) 此时我们称内核代表进程执行,(内核)处于进程上下文。

    在进程通过系统调用陷入到内核态时, 内核代码执行所使用的栈并非原进程用户空间的栈,而是执行在该进程的内核栈上

1.4 进程家族树

    Linux的所有进程都是 PID 为 1 的 init 进程的后代。 Linux内核在系统启动的最后阶段启动 init

进程。 init 进程读取系统的初始化脚本, 执行相应的程序。

    系统中的进程必有一个父进程和零活多个子进程, 拥有同一个父进程的子进程之间被称为(sibling), 所有进程的 task_struct 之间通过成员 parent 指针和 children 链表建立起继承关系。

2 进程创建

    UNIX 进程创建分为 fork() exec() 两个步骤: fork() 函数拷贝当前进程创建子进程, 子进程与父进程的区别在于PID PPID和一些资源统计量; exec() 函数读取可执行文件载入新的地址空间(在进程的内存空间中介绍)运行。

2.1  写时拷贝

     在复制进程时使子进程和父进程共享同一个拷贝, 只有在需要写入时数据才会被复制, 在此之前资源被进程之间只读共享。 采用这种技术后 fork() 的实际开销主要有复制父进程的页表以及创建子进程的 task_struct 。   

3 进程与线程

    在Linux内核的角度来说没有线程的概念, 它与进程本质的区别就是它与其他线程共享某些资源, 例如地址空间。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值