进程间通信-IPC讲解

上传人:我** 文档编号:115015180 上传时间:2019-11-12 格式:PPT 页数:115 大小:996.50KB
返回 下载 相关 举报
进程间通信-IPC讲解_第1页
第1页 / 共115页
进程间通信-IPC讲解_第2页
第2页 / 共115页
进程间通信-IPC讲解_第3页
第3页 / 共115页
进程间通信-IPC讲解_第4页
第4页 / 共115页
进程间通信-IPC讲解_第5页
第5页 / 共115页
点击查看更多>>
资源描述

《进程间通信-IPC讲解》由会员分享,可在线阅读,更多相关《进程间通信-IPC讲解(115页珍藏版)》请在金锄头文库上搜索。

1、linux进程间通信,linux进程间通信,进程间通信IPC(interprocess Communication)提供了一种不同进程间可以互相访问数据的方式。相互访问的数据不仅包括程序运行时的适时数据,也包括对对方代码段的访问。 进程间通信的目的: 1、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。 2、共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。 3、通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。 4、资源共享:多个进程之间共享同样的资源。为了作到

2、这一点,需要内核提供锁和同步机制。 5、进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有异常,并能够及时知道它的状态改变。,linux进程间通信发展历史,linux进程间通信(IPC)由以下几部分发展而来:,linux进程间通信方式,目前Linux 中使用较多的进程间通信方式: (1)管道(Pipe)及有名管道(named pipe) :管道可用于具有亲缘关系进程间的通信;有名管道,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。 (2)信号(Signal) :信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,

3、用于通知接受进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的。 (3)消息(message)队列:消息队列是消息的链接表,包括 Posix 消息队列 systemV 消息队列。它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息。,linux进程间通信,(4)共享内存(shared memory) :可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥

4、锁和信号量等。 (5)信号量(semaphore) :主要作为进程间以及同一进程不同线程之间的同步手段。 (6)套接字(Socket) :这是一种更为一般的进程间通信机制,它可用于不同机器之间的进程间通信,应用常广泛。,管道通信,管道通信是linux 中比较常见,也比较原始的通信方式之一,它实现了数据以一种数据流的方式,在多进程间流动。 管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件。 管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。 写进程在管道的尾端写入数据,读进程在管道的首端读出数据。

5、 数据读出后将从管道中移走,其它读进程都不能再读到这些数据。 管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。 管道分类: 无名管道: (匿名管道)在系统中没有实名,不能在文件系统中以任何方式看到该管道,它只是进程的一种资源,会随着进程的结束而被系统清除。 有名管道:也称为FIFO管道,是一种文件类型,在文件系统中可以查看到。,7,匿名管道(pipe),对匿名管道两端进程而言,是一个只存在于内存的特殊文件 匿名管道是半双工的,数据只能向一个方向流动 一个进程将数据写入管道

6、,另一进程从管道中读取数据 写入的内容添加在管道缓冲区的末尾,每次都是从缓冲区头部读出数据 双向通信的建立 需要建立起两个管道 使用限制 只能用于具有亲缘关系的进程之间 如父子进程或兄弟进程之间,管道通信,8,匿名管道的建立,基本函数 int pipe(int fd2); 参数说明 fd2描述管道两端 fd0只能用于读,称为管道读端 fd1只能用于写,称为管道写端 若试图从写端读,或者向读端写都将导致错误发生 返回值 成功时返回0,失败时返回-1 说明 基本文件I/O函数都可用于管道 如close()、read()、write()等 低层系统调用 sys_pipe( )do_pipe(),管道

7、通信,9,匿名管道的读操作,进程调用read()系统调用 内核最终调用与该文件描述符相关的文件操作表中所找到的read()方法 在管道情形下,read方法将指向pipe_read()函数 该系统调用可能以两种方式阻塞当前进程 系统调用开始时管道缓冲区为空 管道缓冲区没有包含所请求的字节(n个字节),写进程在等待缓冲区的空间时曾经被置为睡眠,10,匿名管道的写操作,进程调用write()系统调用 内核最终调用pipe_write()函数 如果管道没有读进程,写进程发送SIGPIPE信号 管道缓冲区一有空闲区域,写进程将试图写入数据 如果读进程不读出管道缓冲区中的数据,那么写操作将一直阻塞,匿名管

8、道示例一,#include #include #include int main(void) int fd2; char str256; if( pipe(fd)0 ) perror(“pipe“); exit(1); write(fd1, “Create the pipe successfully!n“, 31); read(fd0, str, sizeof(str); printf(“%sn“,str); close(fd0); close(fd1); return 0; ,单个进程中的管道几乎没有任何用处。通常,调用 p i p e的进程接着调用 f o r k,这样就创建了从父进程到子

9、进程或反之的 I P C通道。 f o r k之后做什么取决于我们想要有的数据流的方向。对于从父进程到子进程的管道,父进程关闭管道的读端(f d 0 ) ,子进程则关闭写端(f d 1 ) 。对于从子进程到父进程的管道,父进程关闭 f d 1 ,子进程关闭f d 0 。,12,#include #include #include #define BUFSZ 256 int main(void) int fd2; char bufBUFSZ; pid_t pid; int len; if( pipe(fd)0 ) perror(“failed to pipe“); exit(1); if( (p

10、id = fork()0 ) perror(“failed to fork“); exit(1); ,13,else if(pid 0) printf(“This is farther, write to fd1n“,fd0,fd1); close(fd0); write(fd1, “farther write,child readn“, 25); exit(0); else printf(“This is child ,read from fd0n“); close(fd1); read(fd0, buf, BUFSZ); printf(“%sn“, buf); return 0; ,匿名管

11、道-父子进程间通信,匿名管道操作基本流程,管道操作的基本流程: 1)使用pipe函数创建管道; 2)用fork函数创建一个子进程; 3)关闭父子进程中不需要的文件描述符,使用管道进行通信; 由于以上对管道的操作是比较规范,也比较常用。所以在ANSI C中将以上操作定义在两个标准库函数中,分别是popen和pclose函数。 FILE * popen(const char * command, const char * type) ; int pclose(FILE * f p) ; 参数command是一个在shell中可以运行的命令字符串的指针; 参数type是一个字符指针,这个参数只有两种

12、值,分别是r和w,分别对 应popen函数的返回值是一个读打开文件指针,还是写打开文件指针。 函数失败返回NULL,并设置出错变量errno。 pclose函数的参数fp是一个popen打开的文件描述符,函数失败时返回-1。,#include #include #include #include #include #define BUFES PIPE_BUF int main(void) FILE *fp; char *cmd = “ls -l“; char bufBUFES; if(fp = popen(cmd, “r“) = NULL) perror(“failed to openn“);

13、 exit(1); ,while(fgets(buf, BUFES, fp) != NULL) printf(“%sn“, buf); pclose(fp); exit(0); ,Popen示例,16,有名管道,匿名管道缺点 没有名字,只能用于具有亲缘关系的进程间通信 FIFO(有名管道) 严格遵循先进先出的读写规则 有名字,FIFO的名字包含在系统的目录树结构中,支持无亲缘关系的进程按名字访问 类似管道,在文件系统中不存在数据块,而是与一块内核缓冲区相关联 read和write操作也由pipe_read()和pipe_write() 实现 与匿名管道主要区别 FIFO索引节点出现在系统目录树

14、上而不是pipefs特殊文件系统中 FIFO是一种双向通信管道,可以以读/写模式打开一个FIFO,17,有名管道的建立,基本函数 int mkfifo(const char * pathname, mode_t mode); 参数说明 pathname:创建的FIFO名字 mode:规定FIFO的读写权限 返回值 成功时返回0 失败时返回-1 若路径名存在,则返回EEXIST错误 说明 一般文件的I/O函数都可用于管道,如open(), close(), read(), write()等。,18,有名管道的open(),打开规则 为读操作而打开FIFO文件 若已有进程为写而打开该FIFO,则当

15、前打开操作将成功返回 否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置未设置O_NONBLOCK标志) 或立即返回(当前打开操作设置O_NONBLOCK标志) 为写操作而打开FIFO文件 如果已经有进程为读而打开该FIFO,则当前打开操作将成功返回 否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作未设置O_NONBLOCK标志) 或者,返回ENXIO错误(当前打开操作设置O_NONBLOCK标志) 实例: 1,mkfifo testfifo 建立有名管道文件testfifo; 2,ls testfifo 向有名管道文件写入”ls”命令显示的内容; 3,cat t

16、estfifo 用”cat”命令读取”testfifo”文件中的内容;,19,有名管道示例创建有名管道,#include #include #include #include #include #include #include #include int main(int argc, char* argv) /mode_t mode = 0666; mode_t mode = O_NONBLOCK; if( argc!=2 ) printf(“USEMSG: create_fifo fifonamen“); exit(1); ,if(mkfifo(argv1,mode)0) perror(“failed to mkfifo“); exit(1); else printf(“you successfully

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号