进程与进程间通信

进程

进程是资源分配的基本单位,也是调度运行的基本单位。比如我们想运行一个程序,操作系统就要创建一个进程,并为它分配资源,各种表结构,内存空间,磁盘空间,I/O设备等。然后将它放入就绪队列,当调度运行程序拿到它以后,为它分配CPU和其他资源它才能真正的运行。所有它也是操作系统并发的基本单位。但是在MAC或者Windows NT等微内核结构的操作系统下,它的功能就只有资源分配了,在微内核结构的操作系统下真正调度运行的单位是线程,这样的话,执行并发的自然也是线程。

线程

线程是进程中执行的运算的最小单位。如果把进程理解为逻辑上操作系统所完成的任务,那么线程就是为了完成这任务中许多任务之一。假设用户启动了一个窗口中数据库应用程序,操作系统就将对数据库的调用表示为一个进程,假设用户要从数据库中产生一个工资单报表,并传到一个文件里去,我们把它称为一个子任务;在产生工资单报表的过程中,用户又可以输入查询请求,这又是一个子任务。这样操作系统则把每一个子任务表示为 数据库进程中的一个个线程。线程可以在处理器上独立调度执行,这样,在多处理器环境下,就允许几个线程在各自单独的处理器上进行。操心系统提供线程就是为了方便而有效地实现并发。

进程和线程的区别

  • 1.进程是资源分配和调度的基本单元,而线程则是CPU调度的基本单元。

  • 2.同一个进程可以包含多个线程,并且这些线程共享这个进程的资源包括(寄存器,堆栈,上下文),一个进程至少包含一个线程。

  • 3.进程的创建使用fork()或者vfork(),而创建线程使用pthread_create(),进程结束后它所拥有的所有线程都会被销毁,而线程退出,则不会影响同一个进程下的其他线程。

  • 4.线程是轻量级的进程,所以它的创建和销毁都比进程销毁小。操作系统中所以执行功能都是由线程来完成的。

  • 5.线程执行时一般要注意同步或者互斥,因为它共享同一进程的资源。

  • 6.线程有自己的TCB,线程ID,寄存器硬件上下文,而进程也有自己的PCB,这些私有属性不能被共享,它们用来标识一个线程或者进程。

  • 7.线程退出使用pthread_exit而进程退出使用exit()。

  • 引入线程的好处:

    • 1.易于调度
    • 2.提高并发性。通过线程可以方便有效的提高并发。
    • 3.开销低。创建线程比创建进程容易。
    • 4.利于充分发挥多处理器的功能。通过创建多线程进程,同一进程下的不同线程在不同的处理器上运行,使每个处理器都充分发挥作用。并发性更好。
  • 总结一下,进程有独立的地址空间,一个进程崩溃以后,在保护模式下不会对其他进程造成影响,而线程只是进程的一个执行路径。线程有自己的堆栈,和局部变量,但是线程间没有独立的地址空间,所有当一个线程坏掉,就会影响其他线程导致这个进程崩溃。所以多进程比多线程健壮,但是进程切换的时候消耗比线程切换大。但是对于要求进行并且需要共享某些变量的并发时,我们就得选择线程。

fork和vfork()的区别

  • fork出来的子进程,父子进程交替运行,而vfork出来的子进程,使父进程阻塞,知道子进程结束。
  • fork实现了写时拷贝,而vfork()就算写时,也不拷贝。
  • vfork()必须使用exit和exec后父进程才能运行。
  • vfork在各个系统都存在问题,尽量不使用vfork

进程创建的过程

  • 为新进程在进程表中分配一个表项
  • 为它分配一个唯一的进程ID
  • 准备一个父进程上下文的逻辑副本,不包括共享内存区
  • 增加父进程所拥有所有的计数器,表示有另一个进程也拥有这些文件。
  • 把子进程设置为就绪态。
  • 向父进程返回子进程的进程ID,子进程返回0。

一个32位机器上Linux进程最大能分配多大空间?

一共4G,其中3G用户空间,1G内核空间。

32位系统中,一个进程最大能申请多少堆空间

没有限制,可以申请到堆的上限为止。

多线程和多进程的区别?

进程与进程间通信_第1张图片

多进程多线程适用场景

  • 需要频繁创建销毁,选择多线程。
  • 需要进行大量计算时,选择多线程。
  • 强相关的使用多线程,弱相关的使用多进程。
  • 多机分布使用多进程,多核分布使用多线程
  • 如果多进程多线程都可以,看实际情况,可以选择自己擅长的方式编程。

进程间通信

  • 管道:半双工通信方式,数据单向流动,只能父子进程间使用。
  • 命名管道:半双工通信方式,允许无亲缘关系间的进程通信。
  • 信号:进程间用于通知进程某一时间发生,也可通知进程本身。但是要注意的是除了内核和root,只有具备相同id的进程才可以进行通信。
  • 信号量:信号量的数据结构是一个计数值和一个指针,指针指向等待信号量的下一个进程,简单来说就是一种计数器,它用于对资源进行计数,每当一个进程要拿去资源时,信号量就会进行P操作来对信号量-1,当减到0的时候,就说明没有临界资源了。其他进程想要访问就要等待了,当进程执行完坤姐区的代码之后,再进行V操作对信号加1。PV操作是原子性的,不可中断。
  • 共享内存:共享内存是开辟一块内存空间,使多个进程都可以同时访问这一块内存,是最快的进程间通信方式,而且效率高。往往需要和信号量一起搭配使用,以实现进程间的同步和互斥。
  • 消息队列:消息队列是消息的链表,有权限的进程可以向消息队列里添加消息。有写权限的进程可以在消息队列里写,有读权限的进程可以在消息队里读。消息队列克服了信号承载信息量少的缺陷,同时也解决了管道传递消息是以无格式的字符流传递以及缓冲区大小限制的缺陷。
  • 套接字:实现了不同主机间的进程间通信方式。

进程间通信,各通信方式的优缺点

匿名管道:通信慢,容量有限,必须是有亲缘关系间的通信。
管道:通信慢,容量有限,但是所有进程都能通信。
消息队列:容量有限。
信号量:无法传递复杂信息,只能用来同步。
共享内存:通信快,效率高。但是需要配合信号量使用。

线程间通信

  • 同一进程下的线程,只要做好同步与互斥,保护好全局变量即可。
  • 锁机制(互斥锁,条件变量,读写锁)
  • 信号量机制(计数器)
  • 信号机制:通过通知操作来达到线程同步的目的。

线程同步的方式

  • 临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问共享资源,那么有一个线程进入后,其他使他访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以枪占。
  • 互斥量:采用互斥对象机制。只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
  • 信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一适合访问此资源的最大线程数目。
  • 事件:通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较慢的操作。

什么是死锁?

举个例子吧,存在进程A、B;资源C、D,每种资源只能被一个进程访问。进程A享有C资源,进程B享有D资源,进程A为了完成某一项任务,需要使用D资源,但是它此时任需要使用C资源。而此时呢,进程B真正使用D资源,它为了完成它的任务,它也需要C资源。它俩就陷入一种互相等待的状态,一个等一个,各种又无法释放自己的资源,这就造成了死锁。

死锁的4个必要条件

  • 资源具有互斥性,资源被某一个进程使用时,其他进程不可以访问,除非当前进程访问完毕。
  • 请求和保持:某一进程正再访问某一资源时,此时需要访问其他进程的资源,自己又不释放自己的,并且需要别的进程的,别的进程也不肯释放,这样的一个关系。
  • 不可剥夺:意思是资源被进程使用时,只有当进程访问完毕以后才可以被其他进程访问。
  • 环路等待: 意思是进程发送死锁情况以后必然存在进程-资源环形等待现象。

如何避免死锁

打破任意一个死锁产生的必要条件就行。
比如我们给进程分配资源的时候,一次性给该进程分配完。让它不需要借助其他进程资源,从而打破它请求与等待的条件。

你可能感兴趣的:(进程与进程间通信)