一、进程间通信概述

基本目的:

1.数据传输     一个进程需要将它的数据发送给另一个进程

2.资源共享     多个进程之间共享同样的资源

3.通知事件     一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件

4.进程控制 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变

Linux进程间通信(IPC)由以下几部分发展而来:

1.UNIX进程间通信 (单机)

2.基于System V进程间通信(单机) 

System V,也被称为 AT&T System V,是Unix操作系统众多版本中的一支

3.POSIX进程间通信(单机)

POSIX(Portable Operating System Interface)表示可移植操作系统接口。电气和电子工程师协会(IEEE)最初开发 POSIX 标准,是为了提高 UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于 UNIX,许多其它的操作系统,例如 DEC OpenVMS 和 Microsoft Windows,都支持 POSIX 标准

4.BSD进程间通信(多机)

现在Linux使用的进程间通信方式包括:

1、管道(pipe)和有名管道(FIFO) (无格式字节流)

2、信号(signal) (唯一异步的)

3、消息队列 (解决无格式、信号量少的问题)

4、共享内存(效率最高)

5、信号量

6、套接字(socket)(按TCP\UDP区分,一般不用于单机)

管道通信

管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据,随内核持续。

数据被一个进程读出后,将被从管道中删除,其它读进程将不能再读到这些数据。管道提供了简单的流控制机制,进程试图读空管道时,进程将阻塞。同样,管道已经满时,进程再试图向管道写入数据,进程将阻塞

管道包括无名管道有名管道两种,前者用于父进程和子进程间,兄弟进程之间的通信,后者可用于运行于同一系统中的任意两个进程间的通信。

先创建管道,再创建子进程。

无名管道由pipe()函数创建:

int pipe(int filedis[2]);

当一个管道建立时,它会创建两个文件描述符:filedis[0] 用于读管道, filedis[1] 用于写管道

(成功返回0,失败返回-1)

管道读写

管道用于不同进程间通信。通常先创建一个管道,再通过fork函数创建一个子进程,该子进程会继承父进程所创建的管道

注意: 必须在系统调用fork( )前调用pipe( ),否则子进程将不会继承文件描述符

命名管道

命名管道无名管道基本相同,但也有不同点:无名管道只能由父子进程使用;但是通过命名管道,不相关的进程也能交换数据。

创建命名管道

#include <sys/types.h>#include <sys/stat.h> int mkfifo(const char * pathname, mode_t mode)

pathname:FIFO文件名

mode:属性

一旦创建了一个FIFO,就可用open打开它,一般的文件访问函数(close、read、write等)都可用于FIFO

信号通信

信号(signal)机制是Unix系统中最为古老的进程间通信机制,很多条件可以产生一个信号:

1、当用户按某些按键时,产生信号

2、硬件异常产生信号:除数为0、无效的存储 访问等等。这些情况通常由硬件检测到,将其通 知内核,然后内核产生适当的信号通知进程,例 如,内核对正访问一个无效存储区的进程产生一 个SIGSEGV信号

3、进程用kill函数将信号发送给另一个进程

4、用户可用kill命令将信号发送给其他进程

信号类型

下面是几种常见的信号:

§ SIGHUP: 从终端上发出的结束信号

§ SIGINT: 来自键盘的中断信号(Ctrl-C)

§ SIGKILL:该信号结束接收信号的进程

§ SIGTERM:kill 命令发出的信号

§ SIGCHLD:标识子进程停止或结束的信号

§ SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号

信号处理

当某信号出现时,将按照下列三种方式中 的一种进行处理:

1、忽略此信号      

大多数信号都按照这种方式进行处理,但有两种     信号却决不能被忽略,它们是:SIGKILL\SIGSTOP。这两种信号不能被忽略的原因是:它们向超级用户提供了一种终止或停止进程的方法

2、执行用户希望的动作

通知内核在某种信号发生时,调用一个用户 函数。在用户函数中,执行用户希望的处理

3、执行系统默认动作

对大多数信号的系统默认动作是终止该进程

信号发送

发送信号的主要函数有 kill和raise。

区别:Kill既可以向自身发送信号,也可以向其他进程发送信号。与kill函数不同的是,raise函数是向进程自身发送信号

#include <sys/types.h>    #include <signal.h>    int kill(pid_t pid, int signo)    int raise(int signo)

ps:signo为0时意味着不发送信号,用于检测是否有权限向指定的进程发送信号

成功返回0,失败返回-1

kill的pid参数有四种不同的情况:

1、pid>0    将信号发送给进程ID为pid的进程。

2、pid == 0    将信号发送给同组的进程。

3、pid < 0    将信号发送给其进程组ID等于pid绝对值的进程。

4、pid ==-1     将信号发送给所有进程。

alarm函数

使用alarm函数可以设置一个时间值(闹钟时 间),当所设置的时间到了时,产生SIGALRM信 号.如果不捕捉此信号,则默认动作是终止该进程。

#include <unistd.h>

unsigned int alarm(unsigned int seconds)

Seconds:经过了指定的seconds秒后会产生信号 SIGALRM。

每个进程只能有一个闹钟时间.如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,以前登记的闹钟时间则被新值代换 ,此时返回剩余时间的值

如果有以前登记的尚未超过的闹钟时间,而这次seconds值是0,则表示取消以前的闹钟

pause函数

pause函数使调用进程挂起直至捕捉到一个信号。   

#include <unistd.h>

int pause(void)

只有执行了一个信号处理函数后,挂起才结束

pause之后的程序不执行!

信号处理

当系统捕捉到某个信号时,可以忽略该信号或是使用指定的处理函数来处理该信号,或者使用系统默认的方式

信号处理的主要方法有两种,一种是使用简单的signal函数,另一种是使用信号集函数组

signal--信号

#include <signal.h>

void (*signal (int signo, void (*func)(int)))(int)

如何理解?

typedef void (*sighandler_t)(int) sighandler_t

signal(int signum, sighandler_t handler))

(*signal (int signo, void (*func)(int)))是指向函数的指针

func可能的值是:

1、SIG_IGN:忽略此信号

2、SIG_DFL: 按系统默认方式处理

3、信号处理函数名:使用该函数处理

共享内存

被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.

此处共享内存在内核。

共享内存实现分为两个步骤:

一、创建共享内存

使用shmget函数    

int shmget ( key_t key, int size, int shmflg )

key标识共享内存的键值: 0/IPC_PRIVATE。 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中又设置IPC_PRIVATE这个标志,则同样会创建一块新的共享内存。

shmflg也可以设置IPC_CREAT|IPC_EXCL

返回值:如果成功,返回共享内存标识符;如果失败,返回-1。

键值:给对应的共享内存一个编号,便于打开;正整数。

二、映射共享内存

将这段创建的共享内存映射到具体的进程空间去,使用shmat函数

char * shmat ( int shmid, char *shmaddr, int flag)

参数:

shmid:shmget函数返回的共享存储标识符

char *:表示字节地址

char * shmaddr 处值为NULL时,系统自动分配地址,此时函数返回值返回地址。

flag:决定以什么方式来确定映射的地址(通常为0)

返回值:如果成功,则返回共享内存映射到进程中的地址;如果失败,则返回- 1

当一个进程不再需要共享内存时,需要把它从进程地址空间中脱离,即解除映射。

int shmdt ( char *shmaddr )

成功返回0,失败返回-1

删除共享内存:int shmctl(int shmid,int cmd,struct shmid_ds * buf)

struct shmid_ds * buf一般取NULL值

消息队列

unix早期通信机制之一的信号能够传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列(也叫做报文队列)则克服了这些缺点

消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式.进程可以向中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息

目前主要有两种类型的消息队列:

POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用

系统V消息队列是随内核持续的,只有在内核重起或者人工删除时,该消息队列才会被删除

键值

消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值

#include <sys/types.h>    #include <sys/ipc.h>    key_t ftok (char*pathname, char proj) 

功能:

返回文件名对应的键值。

pathname:文件名

proj:项目名(不为0即可)

打开/创建

#include <sys/types.h>    #include <sys/ipc.h>    #include <sys/msg.h>   int msgget(key_t key, int msgflg) 

key:键值,由ftok获得。

msgflg:标志位。

返回值:与健值key相对应的消息队列描述字

IPC_CREAT    创建新的消息队列

IPC_EXCL    与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误

IPC_NOWAIT     读写消息队列要求无法得到满足时,不阻塞

创建

在以下两种情况下,将创建一个新的消息队列:

1、如果没有与健值key相对应的消息队列,并且 msgflg中包含了IPC_CREAT标志位。

2、key参数为IPC_PRIVATE

int open_queue(key_t keyval){int qid;if((qid=msgget(keyval,IPC_CREAT))==-1){return(-1);}return (qid);}

发送消息

include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg) 

功能:向消息队列中发送一条消息

msqid    已打开的消息队列id

msgp   存放消息的结构

msgsz    消息数据长度

msgflg    发送标志,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待

消息格式

struct msgbuf{long mtype;/*消息类型*/char mtext[1]; /*消息数据的首地址*/}

接收消息

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msqid, struct msgbuf *msgp, int   msgsz, long msgtyp, int msgflg)

功能:从msqid代表的消息队列中读取一个 msgtyp类型的消息,并把消息存储在msgp指向 的msgbuf结构中。在成功地读取了一条消息以 后,队列中的这条消息将被删除

int read_message(int qid,long type,struct mymsgbuf*qbuf){int result,length;length=sizeof(struct mymsgbuf)-sizeof(long);if((result=msgrcv(qid,qbuf,length,type,0))==-1)return(-1);return(result);}

信号量

信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源.进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步

分类

二值信号灯:信号灯的值只能取0或1,类似于互斥锁。 但两者有不同:信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。    

计数信号灯:信号灯的值可以取任意非负值

Linux进程间通信编程相关推荐

  1. Linux 进程间通信编程

    Linux 进程间通信编程(单机) 一.进程间通信概述 二.管道通信(默认无名管道) 1.创建无名管道函数pipe() 2.使用无名管道读取的代码练习 三.命名管道 1.创建有名管道函数mkfifo( ...

  2. Linux网络编程--进程间通信(一)

    进程间通信简介(摘自<Linux网络编程>p85) AT&T 在 UNIX System V 中引入了几种新的进程通讯方式,即消息队列( MessageQueues),信号量( s ...

  3. linux进程间通信:system V 信号量 生产者和消费者模型编程案例

    生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...

  4. 实验六 Linux进程编程,Linux系统编程实验六:进程间通信

    <Linux系统编程实验六:进程间通信>由会员分享,可在线阅读,更多相关<Linux系统编程实验六:进程间通信(10页珍藏版)>请在人人文库网上搜索. 1.实验六:进程间通信l ...

  5. 【Linux系统编程】进程间通信之无名管道

    00. 目录 文章目录 00. 目录 01. 管道概述 02. 管道创建函数 03. 管道的特性 04. 管道设置非阻塞 05. 附录 01. 管道概述 管道也叫无名管道,它是是 UNIX 系统 IP ...

  6. 【Linux系统编程】进程间通信概述

    00. 目录 文章目录 00. 目录 01. 进程间通信概述 02. 进程间通信目的 03. 进程间通信机制 04. 附录 01. 进程间通信概述 进程是一个独立的资源分配单元,不同进程(这里所说的进 ...

  7. 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)

    文章目录 Linux系统编程 文件IO open/close函数 read/write函数 文件描述符 阻塞.非阻塞 fcntl函数 lseek函数 传入传出参数 文件系统 文件存储 文件操作 sta ...

  8. Linux系统编程【文件IO、进程、进程间通信、信号、线程、互斥】

    linux系统编程 个人通过学习,手打了一份48000字的Linux系统编程的笔记,包含了[文件IO.进程.进程间通信.信号.多线程.互斥]等知识点,并给出了大量的代码案例对每个重要的知识点进行了代码 ...

  9. c语言系统编程八:Linux进程间通信之消息队列

    Linux进程间通信之消息队列 一 消息队列概述 二 消息队列的特点 三 消息队列的创建和使用 3.1 获取系统唯一的key值 3.2 创建消息队列 3.3 查看消息队列和删除消息队列的shell命令 ...

最新文章

  1. pypy解释器提高python的效率之安装pypy
  2. python 描述器_python 描述器
  3. iis php win安装kangle_Win2008 R2 IIS7.5+PHP5(FastCGI)+MySQL5环境搭建教程
  4. c#垂直投影法_投影学
  5. OA中SSH+JBPM项目整合
  6. USB CDC 可变形参
  7. 8.10模拟:贪心、最优化思路
  8. PagerAdapter学习
  9. Delta3d框架学习--程序启动过程详解
  10. git 如何忽略掉文件夹_#PY小贴士# 我的git仓库为什么每次提交都有很多改动?
  11. translclude
  12. springside4例子
  13. 11.文件与文件系统的压缩与打包
  14. 英特尔第四代酷睿处理器数字和字母代表什么意思
  15. *min_element 神器第二弹 牛逼的找最大值 最小值
  16. 【防爬虫01】通过headers中的user-agent字段来反爬
  17. PopWindow使用方法详解
  18. 【Prometheus】Prometheus联邦的一次优化记录[续]
  19. oracle 三表连接 join,三个表innerjoin 如何用inner join关联三张表
  20. 如何通过网页超链接控制电脑应用程序

热门文章

  1. 关于Provision.apk
  2. dnf史诗计算机手机版,dnf计算器装备模拟100手机版
  3. 朋友圈集赞神器!再也不怕谁让集赞了
  4. python外星人实验报告_Python 项目实践一(外星人入侵)第一篇
  5. 离职前一定要删除这几个文件,不然你的微信聊天记录全被别人看了
  6. 【笨木头Unity】入门之旅007:Demo之四处找死(二)_主角移动和旋转
  7. 缓冲区溢出漏洞_缓冲区溢出漏洞简介
  8. 03:成绩排序 个人博客:doubleq.win
  9. 记一次AWK程序耗时日志分析
  10. 电商平台数据查询工具(京东数据分析软件)