进程间通信-IPC.ppt
《进程间通信-IPC.ppt》由会员分享,可在线阅读,更多相关《进程间通信-IPC.ppt(115页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、linux进程间通信linux进程间通信进程间通信IPC(interprocessCommunication)提供了一种不同进程间可以互相访问数据的方式。相互访问的数据不仅包括程序运行时的适时数据,也包括对对方代码段的访问。进程间通信的目的:1、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。2、共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。3、通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。4、资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核
2、提供锁和同步机制。5、进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有异常,并能够及时知道它的状态改变。linux进程间通信发展历史linux进程间通信(IPC)由以下几部分发展而来:linux进程间通信方式目前Linux中使用较多的进程间通信方式:(1)管道(Pipe)及有名管道(namedpipe):管道可用于具有亲缘关系进程间的通信;有名管道,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。(2)信号(Signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知接受进程有某事件发生,一个进程
3、收到一个信号与处理器收到一个中断请求效果上可以说是一样的。(3)消息(message)队列:消息队列是消息的链接表,包括 Posix消息队列 systemV消息队列。它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息。linux进程间通信(4)共享内存(sharedmemory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。(5)信号量(semaphore):主
4、要作为进程间以及同一进程不同线程之间的同步手段。(6)套接字(Socket):这是一种更为一般的进程间通信机制,它可用于不同机器之间的进程间通信,应用常广泛。管道通信管道通信是linux中比较常见,也比较原始的通信方式之一,它实现了数据以一种数据流的方式,在多进程间流动。管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件。管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单
5、的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。管道分类:无名管道:(匿名管道)在系统中没有实名,不能在文件系统中以任何方式看到该管道,它只是进程的一种资源,会随着进程的结束而被系统清除。有名管道:也称为FIFO管道,是一种文件类型,在文件系统中可以查看到。7匿名管道(pipe)对匿名管道两端进程而言,是一个只存在于内存的特殊文件 匿名管道是半双工的,数据只能向一个方向流动一个进程将数据写入管道,另一进程从管道中读取数据写入的内容添加在管道缓冲区的末尾,每次都是从缓冲区头部读出数据 双
6、向通信的建立需要建立起两个管道使用限制只能用于具有亲缘关系的进程之间如父子进程或兄弟进程之间管管道道通通信信8匿名管道的建立基本函数intpipe(intfd2);参数说明fd2描述管道两端fd0只能用于读,称为管道读端fd1只能用于写,称为管道写端若试图从写端读,或者向读端写都将导致错误发生返回值成功时返回0,失败时返回-1说明基本文件I/O函数都可用于管道如close()、read()、write()等低层系统调用sys_pipe()-do_pipe()管管道道通通信信9匿名管道的读操作进程调用read()系统调用内核最终调用与该文件描述符相关的文件操作表中所找到的read()方法在管道情
7、形下,read方法将指向pipe_read()函数该系统调用可能以两种方式阻塞当前进程系统调用开始时管道缓冲区为空管道缓冲区没有包含所请求的字节(n个字节),写进程在等待缓冲区的空间时曾经被置为睡眠10匿名管道的写操作进程调用write()系统调用内核最终调用pipe_write()函数如果管道没有读进程,写进程发送SIGPIPE信号管道缓冲区一有空闲区域,写进程将试图写入数据如果读进程不读出管道缓冲区中的数据,那么写操作将一直阻塞匿名管道示例一#include#include#includeintmain(void)intfd2;charstr256;if(pipe(fd)0)perror(
8、pipe);exit(1);write(fd1,Createthepipesuccessfully!n,31);read(fd0,str,sizeof(str);printf(%sn,str);close(fd0);close(fd1);return0;单个进程中的管道几乎没有任何用处。通常,调用 pipe的进程接着调用 fork,这样就创建了从父进程到子进程或反之的 IPC通道。fork之后做什么取决于我们想要有的数据流的方向。对于从父进程到子进程的管道,父进程关闭管道的读端(fd0),子进程则关闭写端(fd1)。对于从子进程到父进程的管道,父进程关闭 fd1,子进程关闭fd0。12#inc
9、lude#include#include#defineBUFSZ256intmain(void)intfd2;charbufBUFSZ;pid_tpid;intlen;if(pipe(fd)0)perror(failedtopipe);exit(1);if(pid=fork()0)printf(Thisisfarther,writetofd1n,fd0,fd1);close(fd0);write(fd1,fartherwrite,childreadn,25);exit(0);elseprintf(Thisischild,readfromfd0n);close(fd1);read(fd0,buf
10、,BUFSZ);printf(%sn,buf);return0;匿名管道-父子进程间通信匿名管道操作基本流程管道操作的基本流程:1)使用pipe函数创建管道;2)用fork函数创建一个子进程;3)关闭父子进程中不需要的文件描述符,使用管道进行通信;由于以上对管道的操作是比较规范,也比较常用。所以在ANSIC中将以上操作定义在两个标准库函数中,分别是popen和pclose函数。FILE*popen(constchar*command,constchar*type);intpclose(FILE*fp);参数command是一个在shell中可以运行的命令字符串的指针;参数type是一个字符指针
11、,这个参数只有两种值,分别是r和w,分别对应popen函数的返回值是一个读打开文件指针,还是写打开文件指针。函数失败返回NULL,并设置出错变量errno。pclose函数的参数fp是一个popen打开的文件描述符,函数失败时返回-1。#include#include#include#include#include#defineBUFESPIPE_BUFintmain(void)FILE*fp;char*cmd=ls-l;charbufBUFES;if(fp=popen(cmd,r)=NULL)perror(failedtoopenn);exit(1);while(fgets(buf,BUFE
12、S,fp)!=NULL)printf(%sn,buf);pclose(fp);exit(0);Popen示例16有名管道匿名管道缺点没有名字,只能用于具有亲缘关系的进程间通信FIFO(有名管道)严格遵循先进先出的读写规则有名字,FIFO的名字包含在系统的目录树结构中,支持无亲缘关系的进程按名字访问类似管道,在文件系统中不存在数据块,而是与一块内核缓冲区相关联read和write操作也由pipe_read()和pipe_write()实现与匿名管道主要区别FIFO索引节点出现在系统目录树上而不是pipefs特殊文件系统中FIFO是一种双向通信管道,可以以读/写模式打开一个FIFO17有名管道的建
13、立基本函数intmkfifo(constchar*pathname,mode_tmode);参数说明pathname:创建的FIFO名字 mode:规定FIFO的读写权限 返回值成功时返回0失败时返回-1若路径名存在,则返回EEXIST错误 说明一般文件的I/O函数都可用于管道,如open(),close(),read(),write()等。18有名管道的open()打开规则为读操作而打开FIFO文件若已有进程为写而打开该FIFO,则当前打开操作将成功返回否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置未设置O_NONBLOCK标志)或立即返回(当前打开操作设置O_NONBL
14、OCK标志)为写操作而打开FIFO文件如果已经有进程为读而打开该FIFO,则当前打开操作将成功返回否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作未设置O_NONBLOCK标志)或者,返回ENXIO错误(当前打开操作设置O_NONBLOCK标志)实例:1,mkfifotestfifo建立有名管道文件testfifo;2,lstestfifo向有名管道文件写入”ls”命令显示的内容;3,cattestfifo用”cat”命令读取”testfifo”文件中的内容;19有名管道示例创建有名管道#include#include#include#include#include#includ
15、e#include#includeintmain(intargc,char*argv)/mode_tmode=0666;mode_tmode=O_NONBLOCK;if(argc!=2)printf(USEMSG:create_fifofifonamen);exit(1);if(mkfifo(argv1,mode)0)perror(failedtomkfifo);exit(1);elseprintf(yousuccessfullycreateaFIFOnameis:%sn,argv1);exit(0);20有名管道举例读有名管道#include#include#include#include#
16、include#include#include#include#defineBUFESPIPE_BUFintmain(void)intfd;intlen;charbufBUFES;if(fd=open(testfifo,O_RDONLY)0)printf(read:%s,buf);close(fd);return0;21有名管道示例写有名管道#include#include#include#include#include#include#include#include#defineBUFESPIPE_BUFintmain(void)intfd;intn,i;if(fd=open(testfif
17、o,O_WRONLY)0)perror(open);exit(1);for(i=0;i10;i+)if(write(fd,messagen,9)0)perror(write);exit(1);close(fd);return0;22信号的本质信号是一种进程间异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。在实现上是一种软中断。是对中断的模拟,也称软中断信号或软中断。信号可以导致一个正在运行的进程被异步打断,让进程知道已经发生了一个特定事件;强迫进程执行自身代码中的信号处理程序;发给非运行进程的信号必须由内核保存,直到进程恢复执行;阻塞一个信号要求信号的传递被延迟,直到随后
18、解除阻塞;每个信号都有名字,这些名字都是以SIG开头;不存在编号为0的信号。信号来源硬件来源硬件操作,如按Ctrl+C硬件故障软件来源常用信号发送函数,如kill(),raise(),alarm()非法运算(浮点运算溢出或内存访问错误等也可产生信号24信号分类不可靠信号信号值小于SIGRTMIN;进程每次处理信号后,将信号响应函数设置为默认动作,需调用signal()重新安装信号;非实时信号都是不可靠信号,不支持排队,信号可能丢失;可靠信号信号值介于SIGRTMIN和SIGRTMAX之间;新信号安装函数sigaction()和信号发送函数sigqueue();实时信号都是可靠信号,支持排队;信
19、信号号通通信信25进程对信号的响应方式忽略信号进程忽略接收到的信号,不做任何处理;SIGKILL和SIGSTOP不能忽略;不能为SIGKILL和SIGSTOP设置新的信号处理函数。捕获信号类似中断处理程序,一旦捕获到相应信号,执行对应的信号处理函数;进程可通过signal()/sigaction()指定进程对某个信号的处理行为;缺省操作Linux内核为信号提供默认处理程序处理;26常见信号值值值值C C 语语语语言宏言宏言宏言宏用途用途用途用途1SIGHUP从终端上发出的结束信号从终端上发出的结束信号2SIGINT来自键盘的中断信号(来自键盘的中断信号(Ctrl-c)3SIGQUIT来自键盘的
20、退出信号(来自键盘的退出信号(Ctrl-)8SIGSTOP进程收到该信号后会暂停执行,进入暂停态进程收到该信号后会暂停执行,进入暂停态9SIGKILL立即结束程序,立即结束程序,不能被阻塞不能被阻塞,处理和忽略,处理和忽略14 SIGALRM 进程的定时器到期时,发送该信号进程的定时器到期时,发送该信号18 SIGCONT处于阻塞状态的进程收到该信号后会继续执处于阻塞状态的进程收到该信号后会继续执行行17 SIGCHLD子进程退出时给父进程发送该信号子进程退出时给父进程发送该信号vKill lKill l可列出所有信号可列出所有信号可列出所有信号可列出所有信号27信号生命周期信号诞生触发信号的
21、事件发生(如检测到硬件异常、定时器超时以及调用信号发送函数kill()或sigqueue()等)。信号在进程中注册内核更新目标进程的数据结构,将信号加入进程的未决信号集,并将信号所携信息保存到某个sigqueue结构中对实时信号,不管其是否已在进程中注册,都被再次注册对非实时信号,若该信号已在进程中注册,则将其丢弃信号在进程中注销进程从核心空间返回用户空间时都检测是否有信号等待处理若存在等待处理且未被阻塞的未决信号,则将其在未决信号链中占有的结构卸掉(对实时进程只删除sigqueue结构)信号处理函数执行完毕执行相应信号处理函数或改变目标进程的执行状态28信号在进程中注册进程的task_str
22、uct结构中有关于本进程中未决信号的数据成员:structsigpending中第三个成员signal是进程中所有未决信号集,第一、第二个成员分别指向一个sigqueue类型的链表的(称之为“未决信号信息链”)的首尾,该链中的每个sigqueue结构包含一个特定信号所携带的信息,并指向下一个sigqueue结构:structsigpendingpending;structsigpendingstructsigqueue*head,*tail;sigset_tsignal;structsigqueuestructsigqueue*next;siginfo_tinfo;信号在进程中注销在目标进程执
23、行过程中,会检测是否有信号等待处理(每次从系统空间返回到用户空间时都做这样的检查)。如果存在未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。是否将信号从进程未决信号集中删除对于实时与非实时信号是不同的。对于非实时信号来说,由于在未决信号信息链中最多只占用一个sigqueue结构,因此该结构被释放后,应该把信号在进程未决信号集中删除(信号注销完毕);而对于实时信号来说,可能在未决信号信息链中占用多个sigqueue结构,因此应该针对占用sigqueue结构的数目区别对待:如果只占用一个sigqueue结构(进程只收到该信号一次),则
24、应该把信号在进程的未决信号集中删除(信号注销完毕)。否则,不应该在进程的未决信号集中删除该信号(信号注销完毕)。进程在执行信号相应处理函数之前,首先要把信号在进程中注销。30信号处理函数信号发送函数kill(),sigqueue(),raise(),alarm(),setitimer(),pause(),abort()信号安装函数signal(),sigaction()信号集操作函数sigemptyset(),sigfillset(),sigaddset(),sigdelset(),sigismember()31信号发送函数kill()#include#includeintkill(pid_t
25、pid,intsigno)功能向进程或进程组发送一个信号(成功返回0;否则,返回-1)参数说明pid:接收信号的进程(组)的进程号pid0:发送给进程号为pid的进程pid=0:发送给当前进程所属进程组里的所有进程pid=-1:发送给除1号进程和自身以外的所有进程pid-1:发送给属于进程组-pid的所有进程signo:发送的信号Signo=0:不发送信号,可用于检查目标进程是否存在,以及当前进程是否具有向目标进程发送信号的权限(root权限的进程可以向任何进程发送信号,非root权限的进程只能向属于同一个session或者同一个用户的进程发送信号)。#include#include#incl
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 进程 通信 IPC
限制150内