操作系统(7)--进程、线程基本概念

线程与进程的区别:

Linux的线程实现非常特别, 它对线程和进程并不区分,从内核的角度来看,它并没有线程这个概念。内核把进程的列表存放在叫做任务列表的双向循环链表中,链表每一项都是类型为task_struct,称为进程描述符的结构,定义在<linux/sched.h>中。Linux通过slab分配器分配task_struct结构,用来达到对象服用和缓存着色的目的。

创建进程时,由于采用写时拷贝策略(copy-on-write),fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符。fork()实际上是clone()系统调用实现的,内核倾向于首先执行子进程。

线程在Linux内部仅仅被视为一个与其他进程共享资源的进程,每个线程都拥有唯一隶属于自己的task_struct,所以在内核中看起来它就像一个普通的进程,只是线程和其他的一些进程共享例如地址空间之类的资源。

创建线程时调用clone,与创建进程不同的是它会传递一些参数来指明需要共享的资源。

进程的调度

进程调度的基本原则很简单,既最大限度地利用处理器的时间。Linux是抢占式多任务系统,由调度器决定什时候停止一个进程的运行,进程被抢占之前的时间都是预先设定好的 ,叫进程的时间片。除了Mac OS9及其前身还有windows3.1及其前身这些非抢占式多任务系统以外,绝大部分操作系统都是抢占式多任务的。

如何增加计算型进程的时间?

对于这类进程,调度策略往往是尽量降低它们的调度频率,而延长运行时间。延长进程时间的方法可以有1:调整进程nice值(操作方法参考http://blog.csdn.net/codestinity/article/details/7496962,或系统调用);2:可以用一个只有该进程使用的自旋锁,保证进程不会被切换;3: 也可以通过preempt_disable/preempt_enable函数来禁止/重新开启内核抢占,自旋锁上锁前会调用preempt_disable, 解锁前会调用preempt_enable重新开启内核抢占(

内核中每个进程数据结构里有一个计数器preempt_count
抢占的开启与禁止,操作当前进程的preempt_count
内核在进行进程调度的时候,只要prempt_count为0,内核就可以进行抢占。
    struct thread_info {
        struct task_struct *task; /* main task structure */
        ............//省略
        int     cpu;              /* cpu we're on */
        int     preempt_count;    /* 0 => preemptable,  <0 => BUG */
    };
);

进程的状态

  • 运行态:进程在内存中并可以执行;
  • 就绪态:进程做好了准备,只要有机会就开始执行;
  • 就绪/挂起态:进程在外存中,但是只要被载入内存就可以执行;
  • 阻塞态:进程在内存中并等待一个事件;
  • 阻塞/挂起态:进程在外存中并等待一个事件;
  • 新建态:刚刚穿件的进程,操作系统还没有把 它加入到可执行进程组中;
  • 退出态:操作系统从可执行进程组中释放出的进程,或者因为它自身停止了,或者是某种原因被取消



猜你喜欢

转载自blog.csdn.net/woshizuxi/article/details/52729734