进程间的通信简介一、进程间的通信 1、linux下进程间通信概述 进程间通信就是在不同进程之间传播或交换信息。 进程间通信(IPC interprocess communication)主要包括以下几种: 1、管道及有名管道 管道:具有亲缘关系进程间的通信 有名管道:可以在许多不相关的进程之间进行通信 2、信号(signal):用于通知接收进程有某种事件发生 3、报文(message)队列(消息队列):消息队列是消息的链接表 4、共享内存:使多个进程可以访问同一块内存空间 5、信号量:作为进程间以及同一进程不同线程之间的同步手段 6、套接字(socket):可用于不同机器之间的进程间通信。 2、管道通信(连接一个进程的标准输入到另一个进程的标准输出的方法) 1、管道 当进程创建一个管道时,系统内核设置了两个管道可以使用的文件描述符。(write,read) 特点: 管道是半双工的 只能用于具有亲缘关系的进程 单独构成一种独立的文件系统 数据的读出和写入:(FIFO)写入的内容每次都添加在管道缓冲区的末尾, 并且每次都是从缓冲区的头部读出数据 (1)管道的创建 pipe()函数用于创建无名管道,当管道创建时会创建fd[0]和fd[1]两个文件描述符 函数原型: int pipe(int fd[2]) fd[2]: fd[0]固定用于读管道,fd[1]固定用于写管道 返回值:成功——返回0; 失败——返回-1 (2)管道的关闭 close(): 关闭了fd[0]和fd[1]就关闭了管道 (3)管道的读/写操作 写操作:
close(fd[0]);//关闭读取端 sleep(3);//确保已关闭相应的读描述符 write(fd[1],string,strlen(string));//通过写端将字符串写入管道 close(fd[1]);//关闭写描述符
读操作:
close(fd[1]);//关闭写入端 read(fd[0],readbuffer,sizeof(readbuffer));//从管道中读取字符串 printf("%s",readbuffer); close(fd[0]);//关闭读描述符
2、标准流管道 创建管道:FILE * popen(char * command, char * type) command: 启动shell后执行的命令 type: 管道中数据流的方向w/r,不能同时为读和写(type只以第一个字符代表的方式打开)。 关闭管道:int pclose(FIFE * stream); 读写:fputs函数和fputc函数 3、有名管道(FIFO管道) 有名管道指创建的管道文件是有文件名的,任何程序都可以通过文件名或路径名与这个文件挂上钩 FIFO管道不是一个临时对象,而是在文件系统中作为一个特殊的设备文件而存在的实体。 (1)FIFO的创建 FIFO文件即”先进先出“文件, 创建方法: mknod MYFIFO p mkfifo a = rw MYFIFO 以上的两个命令执行同样的操作,但其中有一点不同。mkfifo提供一个在创建之后改变FIFO文 件存取权限的途径,而mknod需要调用命令chmod。 mkfifo函数原型: int mkfifo(const char * pathname, mode_t mode) pathname: 将在文件系统中创建的一个专用文件 mode:规定FIFO的读/写权限 返回值:成功——返回0;失败——返回-1 (2)使用 有名管道可以用于任意两个进程间通信。由于管道都是单向的,因此双方通信需要两个管道。 示例: 写入数据:
mkfifo(namedpipe, 0777);//创建管道 pipe_fd = open(namedpipe, O_WRONLY);//以只写方式打开 sour_fd = open(sourtxt, O_RDONLY);//以只读方式打开源文件 bytes_read = read(sour_fd, buffer, sizeof(buffer)); buffer[bytes_read] = '\0'; while(bytes_read > 0) {//向管道写入数据 write(pipe_fd, buffer, sizeof(buffer)); bytes_read = read(sour_fd, buffer, sizeof(buffer)); buffer[bytes_read] = '\0'; }
读取数据:
pipe_fd = open(namedpipe, O_RDONLY);//以只读方式打开管道 dest_fd = open(desttxt, O_WRONLY|O_CREAT, 0664); bytes_read = read(pipe_fd, buffer, sizeof(buffer)); do {//从管道读出数据到目标文件 count = read(pipe_fd, buffer, sizeof(buffer)); write(dest_fd, buffer,sizeof(buffer)); } while (count > 0)
三、共享内存通信 共享内存:最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是 —— 同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的 更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制(互斥锁、信号量) 对于系统V共享内存,主要有以下几个API:shmget(),shmat(),shmdt(),shmctl() shmget(): 获取共享内存区域的ID,不存在指定共享区域则创建相应的区域 shmat():把共享内存区域映射到调用进程的地址空间中去 shmdt():接触进程对共享内存区域的映射 shmctl():实现对共享内存区域的控制操作 函数原型: int shmget(key_t key, int size, int shmflg) key:IPC结构的键值,通常取常量IPC_PRIVATE size: 共享内存区的大小(新建时必须制定size大小,引用已有的区域,则size设为0) shmflg:权限位,可以用八进制表示 返回值:成功——返回共享内存区域标识符ID,即shmid;出错——返回-1 char * shmat(int shmid, const void * shmaddr, int shflg) shmid: 通过shmget得到的共享内存区标识符ID shmaddr:将共享内存映射到指定位置。0 —— 表示映射到调用进程的地址空间 shmflg: 选项位,设置权限,常用选项是SHM_RDONLY(只读),默认为0(读写)。 返回值:成功——返回被映射的段地址,失败——返回-1 (使用以上两个函数即可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读/写命令对 其进行操作) int shmdt(const void * shmaddr) shmaddr: 表示被映射的共享内存段地址 返回值:成功——返回0;失败——返回-1