多进程、多线程、多任务(windows vs linux)

来源:互联网 发布:linux 调用.so 参数 编辑:程序博客网 时间:2024/05/01 14:19

        一个进程最基本的内容:PCB、程序段、数据段

        一个线程包含的内容:线程ID,当前指令指针(PC),寄存器集合、堆栈。

        线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享

进程所拥有的全部资源。


1、Windows下多进程与多线程

       Windows中进程只是作为资源的拥有者,并不是实际任务的执行者,实际的执行靠线程实现。一个进程可以拥有多个线程,多个线程共享进程拥有的资源,在具体执行任务

时由线程来使用处理机。    

       Windows中,进程实现靠createProcess实现。而createProcess有一大堆的参数,不过很多时候都默认为null。其作用相当于创建一个进程的同时创建一个线程(一般一个),

其作用相当于fork+execv(详见下文)。

2、Linux下多进程、多线程

       Linux的进程创建靠fork实现。在Linux中,进程本身是可以执行的(区别windows)。

       fork()的含义是把进程本身clone一个新的出来。也就是说,fork之后子进程和父进程都执行同样的一段代码。想要区分,必须通过fork的返回值来区分。

       int pid = fork();

       if (pid < 0) {// printf("error");//小于0,发生错误

       else if( pid == 0 ) {// printf("子进程!");//==0,为子进程

            else{ // printf("父进程! ");}           // >0,父进程

       为什么这个样子呢?大家知道,Linux起源于unixunix中只有进程的概念,直到后来也不明确区分进程、线程的概念。并且早期unix也是大型机器上使用,大家根据长期总结

经验,得到linux快速复制父进程的方法。fork快速复制父进程,子进程直接使用父进程的地址,开销小,效率高。那么子进程需要执行其他的资源呢?用exevc族,这个时候才为

子进程开辟自己的地址空间,传入需要执行的文件,就可以执行具体的内容了。

   

       既然linux进程、线程并不做明显区分,那么linux怎么还有线程概念、甚至多线程呢?

       在Linux上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程。一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构,却共享了同

一个代码上下文。在Linux上,这样的进程称为轻量级进程Light weight process。 

        Linux2.4 vs linux2.6内核多线程实现:

        首先要明确,2.4内核的多线程无法使用多个cpu,一个进程的线程都被限制在同一个cpu上运行。因此多线程库pthread的实现并不是一件简单的事情,它建立在特有的线程

模型之上。

        2.4内核使用了一个内核线程来处理用户态进程中的多个线程的上下文切换(线程切换)。内核中也并没有线程组(一个进程的多个线程)的概念,因此必须依在pthread

中实现一个额外的线程来管理其他用户线程(即用户程序生成的线程)的建立、退出、资源分配和回首以及线程的切换。早起硬件并没有线程寄存器之类的东西支持多线程,因

此多线程切换效率低下,并且需要引入复杂的机制在进程的栈中为哥哥线程划分出各自的栈数据所在位置,并且在切换时进行栈数据拷贝。而最大的问题是内核中缺乏对线程间

的同步机制的支持,因此pthread库不得不在底层依靠信号量的方式来实现同步,因此线程互斥中的互斥操作和条件量操作都转换为进程的信号操作。信号量是比较低俗的通信方

式,势必降低线程的实际性能。最后的问题是信号处理,内核对线程并不清楚,必须由管理线程接收信号投递给相应线程,造成了效率低下以及不必要的问题。

        在后来的2.5内核之后,硬件结构中已经大为发展,出现了对线程寄存器的支持,因此pthread的切换速度已经大大提高,不过受硬件限制,线程数量小于8192个。

        2.6内核中已经使用了NPTLNative POSIX Thread Library),linux线程的一种新实现,在性能和稳定性方面都提供了重大的改进。

  • NPTL不在使用管理线程。现在内核本身就可以实现这些功能,内核还可以处理线程堆栈所使用内存的回首工作。
  • NPTL没有了管理线程,使得其在NUMASMP系统上有了更好的伸缩性和同步机制。
  • NPTL线程库可以避免使用信号量来实现线程同步,它引入了一种名为futex的机制,在共享内存区域上尽心工工作,可以实现进程之间共享,就可以提供进程间posix同步机制。它使得线程间、进程间共享成为可能。
  • Posix兼容,对信号处理等机制相应处理更为健全
  • 向后兼容

        于此,linux已经可以支持多处理机下的多线程操作。

3java多线程、c++11多线程

        Java编写的程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。
        每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线

程来运行的。JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后,主线程运行完成。JVM进程

随即退出

        语言自带的多线程机制?其实并不是完全自身的多线程机制,只不过是通过在编译器级别使用多线程内存模型,利用其一般的顺序一致性原则来编写高效率的多线程程

序。底层往往任然调用系统的api,中间过程做了优化。

       C++新标准使用了名为sequential consistency for data race free programs的多线程模型机制;而java的缓存一致性模型(包含顺序一致性模型、释放一致性模型)来实现

其多线程。

4、多任务vs 多进程、多线程

       计算机的早期,多任务被称作多道程序。多任务处理是指计算机同时运行多个程序的能力。多任务的一般方法是运行第一个程序的一段代码,保存工作环境;再运行第二个

程序的一段代码,保存环境;……恢复第一个程序的工作环境,执行第一个程序的下一段代码……现代的多任务,每个程序的时间分配相对平均。

        对于实时操作系统,任务调度直接影响性能。 

       任务切换、调度方式等也都类似于进程、线程调度方式,其实这里的任务在windows下可能就是一堆等待执行的线程,也可能像linux下的多个进程等方式。

       实际上,任务调度就是在对进程或线程调度。

       Windows多任务处理机制:
       Windows多任务处理机制采用的是协商式多任务:有几个内核,就维护多少个队列,多个进程内的线程按先后次序排队,有几个内核,就会排成几队。

        缺点:当cpu访问进程队列信息失败时,即当前线程阻塞,则该队列后面所有的线程都会等待。这就是当我们使用windows系统时,某个线程假死之后,所有的队列都会停

滞。这时候,我们要么选择等待,要么选择终止阻塞线程所在的进程。
      

        Linux/unix多任务处理机制:
        Linux/unix多任务处理机制是抢占式多任务:有几个内核,就维护多少个队列,每个进程维护自己的队列,各个进程之间是独立的。各个进程(线程)抢占cpu资源。当cpu访

问进程队列失败时,即某个线程假死之后,其他线程会迅速抢占cpu资源,这样不会因为某个线程假死,影响其他任务的执行。这就是在linux/unix下,当我们的某个进程处于假

死状态,我们其他进程照样可以运行,其他程序依然可以操作,就是这