进程(2)
来源:互联网 发布:清华大学网络教学本科 编辑:程序博客网 时间:2024/05/17 01:09
LINUX系统中的进程控制块
进程的信息在LINUX中通过内核中的一个结构体来描述-task_struct.这样的数据结构被叫做PCB进程控制块。对进程信息的描述包括进程当前的状态,进程的优先级,他正在占用CPU还是阻塞,给他分配了什么地址空间,他可以访问那个文件等等。
PCB是一个相当大的结构,他的域主要分为以下几类
【1】状态信息-描述进程动态的变化,比如就绪态、等待态、僵死态等。
【2】连接信息-描述进程的亲属关系,比如父进程,祖父进程,子进程,兄弟进程等。
【3】各种标识符-用简单数字对进程进行标识-PID,UID等
【4】进程间通信信息-描述多个进程在同一任务上协作工作-管道,消息队列,共享内存,套接字等
【5】时间和定时信息-描述进程在生存周期内使用CPU时间的统计、计费等信息
【6】调度信息-描述进程优先级调度策略等
【7】文件系统信息-对进程使用文件情况进行记录,如文件描述符,系统打开文件表。用户打开文件表
【8】虚拟内存信息-描述每个进程拥有的地址空间,也就是进程编译连接后形成的空间
【9】处理器环境信息-描述进程的执行环境(处理器的各种寄存器及堆栈等等),这是体现进程动态变化的主要场景。
下面通过一些简单的例子说明PCB中这些域的使用,,,,,,,
当内核调度某进程执行时要从该进程的PCB中查出其运行状态和优先级。在某进程被投入运行时要从其PCB中取出其处理器的环境信息,恢复其运行现场。在进程运行过程中需要与其合作的进程实现同步、通信或者访问文件时,也要访问其PCB。当进程因某种情况而暂停执行时,又需将其断点的处理机环境保存在PCB中。PCB是进程存在和运行的唯一标识。
PCB的创建和回收
当系统创建一个进程时,就为他建立一个PCB进程结束时又收回其PCB,进程也随之消亡。PCB是内核中被频繁读写的数据结构故应常驻内存。
LINUX下进程的状态:
LINUX下因为运行态只有一个进程,故将运行态和就绪态合并为就绪态
(1)就绪态:正在运行或者准备运行,处于这个状态的所有进程组成就绪队列
(2)等待态:深度睡眠和浅度睡眠
浅度睡眠:进程被阻塞,等待资源有效时被唤醒也可以有其他进程通过时钟或者信号唤醒。
深度睡眠:被阻塞,其他进程发的时钟中断和信号不能打断她的睡眠
(3)暂停状态:暂停执行,比如进程收到一些信号时(SIGSTOP停止进程执行、SIGTSTP从终端发来的信号停止进程、SIGTTIN键盘的中断、SIGTTOU后台进程请求输出)
(4)僵死状态:进程执行结束但尚未消亡-此时进程的大部分资源已经释放但尚未释放其PCB。
struct task_struct
{
volatile long state;//确保状态变化可以及时反映出来
.......
}
进程标识符
每个进程都有进程标识符、用户标识符、组标识符
进程标识符(PID):内核通过PID来识别不同的进程,同时他也是OS提供给用户的一个接口,用户程序通过PID对进程发号施令。新建进程的PID通常是上一个进程PID加1.LINUX上允许最大PID号由pid_max来指定。当内核在系统中创建的PID大于这个值时就要重新使用已闲置的PID号。如果是大型服务器可以让管理员更改pid_max的值
每个进程都属于某个用户组,task_struct中有UID和GID。系统通过这两种标识符控制进程对系统中文件和设备的访问。
进程的亲缘关系
struct task_struct
{
volaile long state;
int pid,gid,uid;
struct task_struct * realparent;
struct task_struct * parent;
struct list_head children;//子进程链表
struct list_head sibling;//兄弟进程链表
struct task_struct *group_leader;//线程组头进程
。。。
}
进程控制块的存放
每当进程从用户态进入内核态后都要使用栈,这个栈叫做进程的内核栈。当进程一进入内核态,cpu就自动设置该进程的内核栈,这个栈位于内核的数据段上。LINUX把内核栈和一个紧接PCB的小数据结构thread_info放在一起占用8KB.
union thread_union{
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
}
struct thread_info
{
struct task_struct * task;
struct exec_domain *exec_domain;
}
从用户态切换到内核态只要把数据写入栈中,则堆栈寄存器的指针就向箭头方向递减。p表示thread_info的其实地址而task又是thread_info的第一个数据项,故只要找到thread_info就能很容易的找到当前运行的task_struct了。
内核根本不给PCB分配内存而只是给内核栈分配8KB的内存PCB占用了其中的一部分。
当前进程
thread_info和内核栈放在一起的最大好处是内核很容易通过ESP寄存器获得当前CPU上运行的thread_info结构的地址。
current_thread_info()函数获得thread_info的基地址,因为thread_union结构的长度是8kb,则内核屏蔽ESP的低13为有效位就可以获得thread_info结构的基地址。
struct task_struct *currentpcb = current_thread_info()->task;
struct task_struct *myparent = current->parent;
- 进程---------进程描述符(2)
- linux进程(2)--进程概念
- 进程(2)- 进程队列及管理
- 进程(2)
- 进程(2)
- 进程学习(2)
- 操作系统(进程2)
- 进程通信(2)
- 父进程获取子进程退出状态(2)
- 进程篇上之初识进程(2)
- 第2章 进程管理和调度 (进程表示)
- VC进程通信(2)
- Linux进程管理(2)
- LINUX进程调度(2)
- Nginx二次开发(2)进程
- 进程、线程小结(2)
- 进程管理(3-2)
- linux进程调度(2)
- 音乐播放
- oracle 按自定义的序列排序结果集
- iOS中在View 中获取控制器
- ThreadLocal详解
- locate 错误
- 进程(2)
- 数据结构复习之图(1)
- maven
- leetcode再出发
- (转)URI和URL的区别
- 【VC小项目】-13.0项目导引(1)
- WPF控件开源资源
- xml解析-dom范例
- js call() apply()