进程间通信

[Linux:]信号

送分小仙女□ 提交于 2020-02-17 05:15:31
1.如何理解信号 例如在生活中,快递员告诉我们快递到了,那么我们会终止手上的事,去取快递,这就是一种信号。 站在操作系统的角度,再来理解信号: 1.用户输入命令,在Shell下启动一个前台进程。 2. 用户按下 Ctrl-C ,这个键盘输入产生一个硬件中断,被OS获取,解释成信号,发送给目标前台进程 3. 前台进程因为收到信号,进而退出。 所以,显而易见,信号是操作系统与用户通信的一种方式,也可以是进程间通信的方式。 2. Linux下信号机制 信号是进程间时间异步通知的一种方式,属于软中断。 在Linux下我们可以使用 kill -l 命令查看系统定义的信号列表。 2.1 信号常见的处理方式 忽略此信号。 执行该信号的默认处理动作。 提供一个信号处理函数,要求内核在处理信号时切换到用户态执行这个处理函数,这种处理方式称之为捕捉一个信号。 2.2 产生信号的方式 通终端按键产生信号(如常用的Ctrl+z) 调用系统函数向进程发信号 由软件条件产生信号 硬件异常产生信号 3. Linux下信号阻塞 先来了解一些信号相关常见的概念: 信号递达(Delivery):实际执行信号的处理动作 未决信号(Pending):信号从产生到传递之间的状态。 阻塞信号(Blocking):被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作. 在内核中

day 31-1 守护进程、互斥锁、队列、生产消费模型

二次信任 提交于 2020-02-17 01:14:58
守护进程 关于守护进程需要强调两点 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children from multiprocessing import Process import time def foo(): pass def run(): print('this is 子进程') time.sleep(3) p1 = Process(target=foo,) # AssertionError: daemonic processes are not allowed to have children p1.start() if __name__ == '__main__': p = Process(target=run,) p.daemon = True # 守护进程要主进程执行完毕前开启 p.start() p.join() print('主进程') 互斥锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱, 主要参数: from multiprocessing import Process, Lock  

线程相关概念

不问归期 提交于 2020-02-16 18:34:14
文章目录 什么是线程/进程(Thread/Process) 线程和进程的区别、优劣 线程的五个状态 阻塞 状态之间的转移 什么是线程/进程(Thread/Process) 进程:进程是资源分配(CPU、内存)的基本单位,它是程序执行时的一个实例。 程序运行时,系统就会创建一个进程,并为他分配资源,然后把该进程放入进程就绪队列。进程调度器选中该进程的时候为它分配CPU时间片,程序开始真正运行。 线程:线程是程序执行时的最小单位,是进程的一个执行流,CPU调度和分派的基本单位。 一个进程至少有一个线程,可以包含多个线程,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。 线程由CPU调度执行,在多CPU环境下就可以多线程同时运行,同样多线程也可以实现并发操作,为每个请求分配一个线程来处理。 线程和进程的区别、优劣 进程是资源分配的最小单位,线程是程序执行的最小单位。 创建、销毁和切换:进程有独立的地址空间,新建一个进程之后,系统为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这些操作花销较大。线程间共享进程中的数据,使用相同的地址空间,因此CPU在线程间切换要比进程间切换花销小很多,同理创建、销毁一个线程的花销更小 数据共享和通信:线程间通信更加方便,因为同一进程下的线程共享全局变量和静态变量等数据;进程间通信需要以通信的方式(IPC)进行

线程与进程

戏子无情 提交于 2020-02-15 10:39:50
程序设计的目标 性能:高性能的程序应该可以等同于CPU的利用率,CPU的利用率越高(一直在工作,没有闲下来的时候),程序的性能越高。 体验:这里的体验不只是界面多么漂亮,功能多么顺手,这里的体验指程序的响应速度,响应速度越快,用户体验越好。 Socket网络编程 在同一个JVM运行环境中,类与类之间可以直接相互调用,但是处于不同的JVM中的类,它们之间是无法直接调用的,这时通过Socket网络编程可以让处于不同JVM、甚至不同计算机的类之间进行通讯。 Socket:相当于电话座机 IP:相当于电话号码 Socket的API常用方法: accept()--阻塞; getInputStream()--获取网络连接输入流 getOutputStream()-- 获取网络连接输出流 单线程多任务IO阻塞(例如:磁盘操作)时CPU空闲---解决方案:[单线程多任务异步IO --让准备好的任务优先执行] 单线程多任务,有耗时计算 即CPU计算耗时阻塞----解决方案:[多线程程序(可进行任务执行切换)] 多CPU执行效果更好,但决定如何分配难,也就是多核下的线程同步与互斥 进程 :在操作系统中运行着的一个独立的程序(桌子) 线程 :一个进程中一条独立的执行分支。(一个人) 多线程与多进程: 一群人(多个线程)在一个桌子(进程)上吃饭,他们会涉及到一些问题,比如多个人可能会夹一个菜(竞争)

[APUE]进程控制(中)

我与影子孤独终老i 提交于 2020-02-15 10:14:47
一、wait和waitpid函数 当一个进程正常或异常终止时会向父进程发送SIGCHLD信号。对于这种信号系统默认会忽略。调用wait/waidpid的进程可能会: 阻塞(如果其子进程都还在运行); 立即返回子进程的终止状态(如果一个子进程已经终止正等待父进程存取其终止状态); 出错立即返回(如果它没有任何子进程); 如果进程由于收到SIGCHLD信号而调用wait,则可期望wait会立即返回。但是在任一时刻调用则进程可能阻塞。 #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc, int options); 返回值: 成功返回进程ID, 出错-1. 这两个函数区别: wait如果在子进程终止前调用则会阻塞,而waitpid有一选项可以使调用者不阻塞。 waitpid并不等待第一个终止的子进程--它有多个选项,可以控制它所等待的进程。 如果调用者阻塞而且它有多个子进程,则在其一个子进程终止时,wait就立即返回。因为wait返回子进程ID,所以调用者知道是哪个子进程终止了。 参数statloc是一个整型指针。如果statloc不是一个空指针,则终止状态就存放到它所指向的单元内

Linux下Fork与Exec使用

感情迁移 提交于 2020-02-15 10:04:29
一、引言   对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。fork函数是Unix系统最杰出的成就之一,它是七十年代UNIX早期的开发者经过长期在理论和实践上的艰苦探索后取得的成果,一方面,它使操作系统在进程管理上付出了最小的代价,另一方面,又为程序员提供了一个简洁明了的多进程方法。与DOS和早期的Windows不同,Unix/Linux系统是真正实现多任务操作的系统,可以说,不使用多进程编程,就不能算是真正的Linux环境下编程。   多线程程序设计的概念早在六十年代就被提出,但直到八十年代中期,Unix系统中才引入多线程机制,如今,由于自身的许多优点,多线程编程已经得到了广泛的应用。 下面,我们将介绍在Linux下编写多进程和多线程程序的一些初步知识。 二、多进程编程 什么是一个进程?进程这个概念是针对系统而不是针对用户的,对用户来说,他面对的概念是程序。当用户敲入命令执行一个程序的时候,对系统而言,它将启动一个进程。但和程序不同的是,在这个进程中,系统可能需要再启动一个或多个进程来完成独立的多个任务。多进程编程的主要内容包括进程控制和进程间通信,在了解这些之前,我们先要简单知道进程的结构。    2.1 Linux下进程的结构   Linux下一个进程在内存里有三部分的数据,就是"代码段"、"堆栈段"和"数据段"

操作系统线程和进程的同步机制和通信机制

♀尐吖头ヾ 提交于 2020-02-15 00:52:52
现在流行的进程线程同步互斥的控制机制,其实是由最原始最基本的4种方法实现的。由这4种方法组合优化就有了.Net和Java下灵活多变的,编程简便的线程进程控制手段: 临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event) 1. 线程间的同步通信机制 1.1 临界区 通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问 。在 任意时刻只允许一个线程对共享资源进行访问 ,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。 1.2 互斥量 采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问 。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 .互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。 1.3 信号量 它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 .信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV

进程间的通信方式及线程间的通信方式

随声附和 提交于 2020-02-15 00:38:48
进程间的通信方式及线程间的通信方式 0X00 进程间的通信方式 0X01 总述 每个进程都有自己的地址空间,因此从资源占用上来看,不同进程是相互独立的,也就是存在着明显边界的。因此相比于线程,通信比较困难一点。现在比较常用的方式有: 管道 、 消息队列 、 信号量 、 信号 、 共享内存 、 套接字 0X02 管道 管道主要包括 无名管道 和 命名管道 管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信 普通管道PIPE 1、它是 半双工 的(即数据只能在一个方向上流动),具有固定的读端和写端 2、它只能用于 具有亲缘关系 的进程之间的通信(也是父子进程或者兄弟进程之间) 3、它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只 存在于内存 中。 命名管道FIFO 1)FIFO可以在无关的进程之间交换数据 2)FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。 0X03 消息队列 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列 克服了信号传递信息少 、 管道只能承载无格式字节流 以及 缓冲区大小受限 等缺点。 特点: 1)消息队列是 面向记录 的,其中的消息具有特定的格式以及特定的优先级。 2

Python中使用多进程来实现并行处理的方法小结

依然范特西╮ 提交于 2020-02-14 00:02:35
Python中使用多进程来实现并行处理的方法小结 进程和线程是计算机软件领域里很重要的概念,进程和线程有区别,也有着密切的联系,先来辨析一下这两个概念: 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 2.关系 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行. 相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。 3.区别 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。 简而言之,一个程序至少有一个进程

python 学习笔记 多进程

こ雲淡風輕ζ 提交于 2020-02-13 21:15:57
要让python程序实现多进程,我们先了解操作系统的相关知识 Unix/Linux操作系统提供了一个fork()系统调用,他非常特殊,普通的函数调用,调用一次,返回一次,但是fork调用一次, 返回两次,因为操作系统自动把当前进程称为父进程复制了一份,然后,分别在父进程和子进程返回。 子进程永远返回0,而父进程返回子进程的ID.这样做的理由是,一个父进程可以fork出很多子进程,所以父进程要记下来 子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的id Python的OS模块封装了常见的系统调用,其中就包括fork,可以在python程序中轻松创建子进程 import os print('Process (%s) start...' % os.getpid()) # Only works on Unix/Linux/Mac: pid = os.fork() if pid == 0: print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())) else: print('I (%s) just created a child process (%s).' % (os.getpid(), pid)) 有了 fork 调用