多线程概念:线程的独有和共享

线程概念:

理解:
在Linux内核中,实质上是没有线程这个概念的,也没有提供创建线程的系统调用接口;(线程创建等接口是在库函数中完成的,因为早期Linux根本不认为有线程这个东西)
当我们需要完成多个功能时,如果单单按照进程的概念,一个进程就执行一个功能,就需要多进程来完成。而由于这些功能有可能在内存中的位置是相同的,我们能不能通过一些方式来节省资源呢?
Linux通过多个pcb共享一个虚拟地址空间来实现完成不同的功能,而这些pcb相对于进程pcb而言是是相对轻松的,因此被称为轻量级进程。
在广泛意义上讲(各种操作系统),又有一个概念是:线程是进程的一条执行流,完成进程的各种功能。而Linux对这点,已经用轻量级进程来实现了,为了统一概念,干脆就说Linux下轻量级进程就是线程。
总结:
一个pcb映射一个虚拟地址空间,这就叫有一个轻量级进程的进程。
多个pcb映射一个虚拟地址空间,这就叫有多个轻量级进程的进程。
多线程概念:线程的独有和共享_第1张图片
总结:
进程和线程:
进程是一个pcb,Linux下是一个task_struct结构体实现的,对一个运行的程序进行动态的描述,通过这个描述实现对程序运行的管理。
线程是进程中的一条执行流,但是Linux下执行流通过pcb实现,一个进程中可以有多个pcb,这些pcb共享进程中的大部分资源,相较于传统的pcb较为轻量化,因此也称轻量级进程。
进程是操作系统资源分配的基本单位;
线程是CPU调度的基本单元

线程之间的独有和共享

独有:标识符,寄存器,栈,信号屏蔽字,errno,优先级
共享:虚拟地址空间(代码段和数据段),文件描述符表,信号的处理回调函数,用户ID/组ID/工作路径;

虚拟地址空间共享:
创建线程是创建一个pcb,然后通过指针指向同一块虚拟地址空间,同一个页表,因此映射的也是同一块物理内存,数据段代码段堆栈都是同一块。这意味着线程之间的通信是非常灵活的,只需要知道变量的地址就可以进行通信。
tips:线程间的通信可以通过进程通信的方式,除此之外全局变量、函数传参也可以进行通信。
信号屏蔽字为什么独有:
为什么信号是先注销在处理?
信号是针对整个通知事件进行处理的,但一个信号只应被处理一次就好了。然而一个进程有多个执行流,到底谁来处理这个信号呢?
答案是:谁拿到时间片,谁能就处理谁就处理。
若不先注销信号,当第一个线程将信号处理完毕,切换时间片到另一个线程,这个线程还能检测到有信号未处理,就要去处理。这样就造成一个信号被处理多次。
有的线程不希望操作被信号打断,就可以独立屏蔽这个信号。所以信号屏蔽字是独有的。
寄存器独有:
线程在处理数据时,会将cpu上寄存器的数据(上下文数据,程序计数器等)拷贝过来,每个线程在切换完时间片后再次运行时就会知道上次运行的位置。方便继续运行。
栈独有:
在使用vfork()创建子进程时,父子进程共用同一个虚拟地址空间,但是需要阻塞父进程,直到子进程exit退出或者程序替换才可以。
否则就会造成共用一块栈区,在函数压栈是,如果父进程和子进程单独调用函数,就不知道哪一个函数先出栈了,这样就是栈混乱。
多线程调用也是一样,因为线程之间是共用同一快虚拟地址空间的,也会遇到栈混乱的情况,唯一能解决这个问题的方法就是调用栈独有。
但是这种栈独有也是相对的(因为虚拟地址空间是共享的),当遇到一些特殊情况时,传入栈的地址也可以让线程之间使用用一个栈。

errno独有:
errno是一个全局变量,保存系统调用使用完成后的错误编号,多个线程同时执行,都会使用系统调用;都会修改errno,若error共用,就会存在二义问题。不知道哪个errno是哪个进程的。

多线程/多进程进行多任务处理的优缺点分析:
多线程的优点:
1.线程间通信灵活方便,(除了进程间通信方式之外还有全局变量以及函数传参,共用一块虚拟地址空间,只要知道地址就可以访问同一块物理空间)
2.线程的创建和销毁成本更低(创建线程创建pcb只要使用一个指针就可以指向同一处就好了)
3.同一个进程中的线程间调度成本更低(因为使用的同一个页表,只需要切换页表信息,而进程调度需要切换整个页表)
多进程的优点:
多进程的鲁棒性、稳定性更高(异常(比如内存访问错误、逻辑错误)以及一些系统调用exit直接针对整个进程生效,多进程有一个进程退出,不会影响其他进程。而如果是在多线程中,进程退出,线程都得退出。出现问题就很容易造成整个程序崩溃)
应用场景:对于主程序安全性要求比较高的场景,比如shell场景服务器。
应用场景:
1.IO密集型程序:多任务并行处理,(单磁盘可以并行压缩IO等待事件/多磁盘可以实现同时处理)
IO密集型:程序中大量进程IO操作,对CPU要求不高因此执行流个数没有太大要求,使用多线程很好。

2.CPU密集型程序:程序中进行大量的数据运算处理,cpu资源足够,就可以同时处理,提高效率,(通常执行流的个数是cpu核心数+1),创建线程很多的话,而cpu资源不够,就会造成大量的线程切换,调度成本提高。使用多进程比较好。

你可能感兴趣的:(操作系统和网络,linux)