Linux内核之进程管理
进程是可并发执行的程序在一个数据集合上的运行过程,在Linux系统中,当一个程序开始执后,在开始执行到执行完毕退出这段时间里,它在内存中的部分就被称为一个进程,有三种不同类型——交互进程,批处理进程,监控进程。
线程可以看成是进程中指令的不同执行线路。与进程相关的基本要素有:代码、数据、堆栈、文件I/O和虚拟内存信息等,也叫“轻量级进程”。有用户线程和内核线程,linux将线程定义为执行上下文。
一、进程创建和进程调度
系统启动时创建初始化进程,机器状态存在初始化进程的task_struct数据结构中,初始化结束后初始进程启动一个内核线程init,自己处于空循环状态,当系统中没有可运行的进程时调度程序会运行这个空闲的进程。
Fork和clone系统调用可用来建立新的进程。
进程终止的条件有:主动终止——进程运行结束,正常退出和发生可预料的错误,报错退出;被动终止——发生严重错误,进程异常终止和被其他进程终止。
进程之间的切换由调度程序完成。Intel在i386体系中设计考虑到进程的管理和调度所以在体系结构中增设了一种新段“任务状态段”TSS(Task Status Segment),是一个104字节的数据结构。
每个进程用一个task_struct的数据结构表示,仅仅是进程控制表(process table)中的一项,每个在task_struct结构中登记的进程都有相应的进程状态(state)和进程标志(flags),是进行进程调度的两个重要数据。进程控制表既是一个数组又是一个双向链表还是一个树。进程中访问共享数据的程序片段称为临界区,避免竞争条件就必须避免多个进程处于临界区。
进程切换时需作三个层次的工作:一、用户数据的保存——正文段(TEXT)、数据段(DATA,BSS)、栈段(STACK)、共享内存段(SHARED MEMORY);二、寄存器数据的保存——PC(program counter,指向下一条要执行的指令的地址)、PSW(processor status word,处理机状态字)、SP(stack pointer,栈指针)、PCBP(pointer of process control block,进程控制块指针)、FP(frame pointer,指向栈中一个函数的local 变量的首地址)、 AP(augument pointer,指向栈中函数调用的实参位置)、ISP(interrupt stack pointer,中断栈指针) 以及其他的通用寄存器等;三、系统层次的保存——proc、虚拟存储空间管理表格和中段处理栈,以便该进程再一次得到CPU时间片时正常运行下去。
Linux中的程序和命令通常由命令解释器——shell执行,用户输入命令之后,shell会在搜索路径(shell变量PATH)指定的目录中搜索和输入命令匹配的映像名称,若发现匹配的映像,shell负责装载并执行该命令。shell首先利fork系统调用建立子进程,然后用找到的可执行映像文件覆盖子进程正在执行的shell二进制映像。Linux使用的最常见的可执行文件格式是可执行可连接格式(Executable and linking format,ELF)和a.out。
Linux利用需求分页技术装入程序映像,系统调用建立子进程后调用exec系统调用利用ELF二进制格式装载器装载ELF映像,将当前进程的可执行映象从虚拟内存中清除,同时清除任何信号处理程序并关闭所有打开的文件,然后重置进程页表。根据ELF文件中的信息将映像代码和数据的起始和终止地址分配并设置相应的虚拟地址区域,修改进程页表,这是当前进程就可以开始执行对应的ELF影响中的指令了。
Linux下进程之间通信的主要手段有一、管道(pipe)及有名管道(named pipe)【具有亲缘关系进程的通道和无】,二、信号(signal)【进程间和进程本身】,三、报文(message)队列(消息队列)【进程向队列添加消息】,四、共享内存【多进程访问同一内存空间】,五、信号量(semaphore)【进程间及同一进程不同线程】,六、套接字(socket)【不同机器之间的进程】。这里对共享内存进行简单的介绍,由于进程的虚拟地址可以映射到任意一处物理地址,如果两个进程的虚拟地址映射到同意物理地址,这两个进程就可以利用这一物理地址进行通讯,但是一旦内存被共享之后对共享内存的访问同步需要有其他IPC机制(如信号量)。通过访问键来访问并进行权限检查,共享内存对象的创建者负责控制访问权限以及访问键的共有或私有特性,如果有足够的权限,可以将共享内存锁定到物理内存中。在利用共享内存时,参与通讯的进程通过系统调用将自己要共享的虚拟地址区域加到attached指向的链表中。某进程第一次访问共享虚拟内存时将产生页故障。这时Linux找出描述该内存的vm_area_struct结构,该结构中包含用来处理这种共享虚拟内存的处理函数地址。
Linux查看当前系统中运行的进程命令有ps-报告进程状态,pstree-可打印进程之间的父子关系,top-监视系统CPU利用率最高的进程。
内核同步是为了达到多线程协同的目的而设计的一种机制,通常包含异步信号机制和互斥机制作为其实现的底层,在2.4内核中用信号量、自旋锁、原子操作和等待队列实现,其中原子操作和等待队列又是实现信号量的底层。