4.7.1 匿名管道通信

任务:把一个CMD控制台程序改成窗口程序

“算命大师”程序的改进版

改进目标:标准的Windows窗口程序

(匿名)管道通信机制

管道定义 pipe

定义:管道是进程间的一种通信机制,一个进程(A)可以通过管道把数据传输到另外一个进程(B)。前者(A)向管道输入数据,后者(B)从管道读取数据

管道的工作原理

  1. 管道象文件一样,可读和可写,有读/写2个句柄。 CreatePipe(Handle W, Handle R)
  2. 通过写写句柄(W)向管道中写数据: WriteFile(W, Buffer) 或通过输出重定向向写句柄(W)写入。
  3. 通过读读句柄(R)从管道中读数据: ReadFile{R, Buffer) 或通过输入重定向从读句柄(R)读出。

注意事项:仅能用于父子或兄弟进程中通信

  1. 由父进程 (A)创建管道: CreatePipe(W, R)。
  2. 由父进程 (A)创建子进程 (B) : CreateProccess()
  3. 父进程写或读管道,子进程输入或输出重定向到管道。

两个示例

应用管道的注意事项

双向通信必须建立2个管道

要支持程序见双向通信,父进程(A)必须创建2个管道

“算命大师”程序的改进版实现

设计思路

  1. 由父进程 (A)创建管道: CreatePipe(W, R)。
  2. 由父进程 (A)创建子进程 (B) : CreateProccess()
  3. 父进程写或读管道,子进程输入或输出审定向到管道。

关键函数和代码

  1. 父进程(即算命大师改进版程序)创建2个管道

    CreatePipe(&hPipe_1_ReadHandle, &hPipe1_WriteHandle, &sa, 0);
    CreatePipe(&hPipe_2_ReadHandle, &hPipe2_WriteHandle, &sa, 0);
  2. 父进程创建子进程(算命大师的原始版程序),隐藏它并输入/输出重定向到管道

    StartInfo.wShowWindow = SW_HIDE;
    StartInfo.hStdInput = hPipe_ReadHandle;
    StartInfo.hStdOutput = hPipe2_WriteHandle;
    ::CreateProcess(NULL, "算命大师.exe", NULL, NULL, true, 0, NULL, NULL, &StartInfo, &PiInfo);
  3. 父进程把用户输入的日期写道管道1的写句柄上,传给算命大师原始版程序

    GetDlgItem(IDC_EDIT_DATE)->GetWindowsText(csDate);
    ::WriteFile(hPipe1_WriteHandle, csDate, nLen, &writeBytes, NULL);
  4. 父进程读取管道2的读句柄,以获取算命大师原始版程序的结果,并显示出

    ReadFile(hPipe2_ReadHandle, bufferResult, 1023, &IBytesRead, 0);
    GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(bufferReuslt);

4.7.2 Linux信号通信

信号的概念(Signal)

  • 信号是Linux进程间一种重要的通信机制。
  • 信号是向进程发送的一个通知通知某个事件已发生
  • 收到信号的进程可以立即执行指定的操作。
  • 信号的发出可以是进程,也可以是系统(含硬件)。

终端上使用信号机制的例子

例子1:键盘上按下Ctrl+C杀死一个进程

说明:

  1. Ctrl+C产生信号SIGINT
  2. 进程收到SIGINT信号,执行默认操作(结束进程)

例子2:键盘上按下Ctrl+Z暂停(挂起)一个进程

说明:

  1. Ctrl+Z产生信号SIGTSTP
  2. 进程收到SIGTSTP信号,执行默认操作(挂起进程)

例子2:终端命令kill -9杀死一个进程

说明:

  1. kill -9产生信号SIGKILL
  2. 进程收到SIGKILL信号,执行默认操作(强制结束进程)

信号的产生

  1. 来源1 : 键盘输入特殊组合键产生信号,例: " Ctrl + C"
  2. 来源2 : 执行终端命令产生信号,例: kill系列命令
  3. 来源3 : 程序中调用函数产生信号,例: kill()、 abort()
  4. 来源4:硬件异常或内核产生相应信号。例:内存访问错

信号的定义

Linux定义了64种信号,信号用整数1-64表示

信号编号 信号名称 说明
2 SIGINT 进程结束(按键 CTRL+ C能产生)
6 SIGABRT 进程结束 ( 调用 abort函数产生)
9 SIGKILL 进程强制结束(用户不能捕获该信号)
11 SIGUSR1 用户自定义信号 1
14 SIGALRM 定时器时间到的信号
19 SIGTSTP 进程暂停执行(用户不能捕获该信号)

信号机制编程:例子1

任务:编写一个死循环程序,当其收到键盘按下的 CTRL+ C信号后,输出“BYE BYE”,然后退出。

#include <iostream>
#include <unistd.h> int main() {
printf("int_handler set for SIGNIT\n"); while (1) {
printf("go to sleep\n");
sleep(6);
} return 0;
}

思路:让进程对Ctrl+c的SIGNIT信号用自定义的信号处理函数相应,在自定义信号处理函数输出“BYE BYE”后结束

signal():注册信号处理函数的函数

原型
void signal(
int SigNo, //信号编号
void (* Handle) int //信号自定义处理函数
)
功能:

为指定信号注册信号处理函数。当进程收到SigNo信号时,立即自动调用 Handle函数执行。一般在进程初始化时使用该函数注册信号处理函数。

#include <iostream>
#include <unistd.h> void int_handler(int signum) {
printf("\nBYE BYE \n");
exit(-1);
} int main() {
signal(SIGINT, int_handler);
printf("int_handler set for SIGNIT\n"); while (1) {
printf("go to sleep\n");
sleep(6);
} return 0;
}

信号机制编程:例子2

任务:一个进程(父进程)等待另一个死循环的进程(子进程)先结束并向自己BYE BYE后,自己再结束。

思路:父进程主动发送一个信号给子进程,子进程收到之后 立即准备结束。子进程中设置信号处理函数,提前结束自己,并向父进程“BYE- BYE!“。

kill():发送信号的函数

原型:
void kill(
int PID, //接受信号的目标进程的ID
int SigNo //待发送的信号
)
功能:

向着目标进程PID发送SigNo信号

【av68676164(p33-p34)】进程通信的更多相关文章

  1. Linux学习笔记(13)-进程通信|命名管道

    匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...

  2. Android随笔之——跨进程通信(一) Activity篇

    在Android应用开发中,我们会碰到跨进程通信的情况,例如:你用QQ通讯录打电话的时候会调用系统的拨号应用.某些新闻客户端可以将新闻分享到QQ.微信等应用,这些都是跨进程通信的情况.简而言之,就是一 ...

  3. Android 进程通信机制之 AIDL

    什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在 ...

  4. Windows进程通信 -- 共享内存(1)

    共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 W ...

  5. MINIX3 进程通信分析

    MINIX3 进程通信分析 6.1MINIX3 进程通信概要 MINIX3 的进程通信是 MINIX3 内核部分最重要的一个部件,我个人认为其实这 是内核中的“内核”,怎么来理解这个概念呢?其实 MI ...

  6. Linux系统编程@进程通信(一)

    进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...

  7. Linux下进程通信的八种方法

    Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...

  8. WinForm实现跨进程通信的方法

    public class WinMessageHelper { private struct COPYDATASTRUCT { public IntPtr dwData; public int cbD ...

  9. 进程通信之一 使用WM_COPYDATA C++及C#实现(转)

    进程间通信最简单的方式就是发送WM_COPYDATA消息.本文提供C++及C#程序相互通信的二种实现方式.这样消息的接收端可以用C++实现,发送端可以用C++或C#实现.     发送WM_COPYD ...

  10. [转]WINDOW进程通信的几种方式

    windows进程通信的几种方式 1 文件映射 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/O操作,只需简单的指针 ...

随机推荐

  1. java 面向对象(二十):类的结构:代码块

    类的成员之四:代码块(初始化块)(重要性较属性.方法.构造器差一些)1.代码块的作用:用来初始化类.对象的信息2.分类:代码块要是使用修饰符,只能使用static分类:静态代码块 vs 非静态代码块3 ...

  2. java 基本语法(八) 数组(一) 数组的概述

    * 1.数组的理解:数组(Array),是多个相同类型数据一定顺序排列的集合,并使用一个名字命名, * 并通过编号的方式对这些数据进行统一管理. * * 2.数组相关的概念: * >数组名 * ...

  3. Go的100天之旅-常量

    常量 简介 道可道,非常道.这里常道指的永恒不变的道理,常有不变的意思.顾名思义和变量相比,常量在声明之后就不可改变,它的值是在编译期间就确定的. 下面简单的声明一个常量: const p int = ...

  4. .net core 自带分布式事务的微服务开源框架JMS

    事务的统一性是微服务的一个重点问题,简洁有效的控制事务,更是程序员所需要的.JMS的诞生,就是为了更简单.更有效的控制事务. 先看一段调用微服务的代码: using (var ms = new JMS ...

  5. Linux中profile和bashrc的区别

    profile主要设置系统环境参数(可类比为Windows的系统环境变量),如$PATH /etc/profile ~/.bash_profile bashrc主要用来设置bash命令,如命令别名,a ...

  6. css的一些小技巧。修改input样式

    在第一次正式写项目的时候,遇到了几个布局的小技巧.记录一下. 我们常常会遇到图片和文字对齐的一种样式.比如 这样的样式,我们写的时候有时候会出现不对齐的情况.我们有俩种方法 一种就是flex的布局,还 ...

  7. 数据库事务与MySQL事务总结

    事务特点:ACID 从业务角度出发,对数据库的一组操作要求保持4个特征: Atomicity(原子性):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败 ...

  8. ELasticSearch(五)ES集群原理与搭建

    一.ES集群原理 查看集群健康状况:URL+ /GET _cat/health (1).ES基本概念名词 Cluster 代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产 ...

  9. 面试题二十二:链表中倒数第k个节点

    方法一:双指针法定义两个指针A.B,A先走k-1步后再一起走,直到A.next==null注意: 1.链表为空 2.链表长度小于k 3.k<=0 当题目是求链表的中间节点时,可以两个指针从开头开 ...

  10. Centos 7下编译安装PHP7.2(与Nginx搭配的安装方式)

    一.下载源码包 百度云网盘下载地址:https://pan.baidu.com/s/1li4oD3qjvFyIaEZQt2NVRg 提取码:4yde 二.安装php依赖组件 yum -y instal ...