一、Linux 下进程间通讯方式
1)管道(Pipe)及有名管道(named pipe):
管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
2)无名信号量(semaphore)级有名信号量(named semaphore):
主要作为进程间以及同一进程不同线程之间的同步手段。
3)信号(Signal)
信号是比较复杂的通信方式,用于通知接受进程有某种事件生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期 信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上, 该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,sigaction函数重新实现了signal函数);
4)报文(Message)队列(消息队列):
消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5)共享内存:
使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针其他通信机制运行效率较低设计的。往往与其它通信机制,如信号量结合使用, 来达到进程间的同步及互斥。
6)套接字(Socket):
更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix 系统上:Linux和System V的变种都支持套接字。
二、进程间通讯特点说明
1. socket
1、使用socket通信的方式实现起来简单,可以使用因特网域和UNIX域来实现,使用因特网域可以实现不同主机之间的进出通信。
2、该方式自身携带同步机制,不需要额外的方式来辅助实现同步。
3、随进程持续。
2. 共享内存
1、最快的一种通信方式,多个进程可同时访问同一片内存空间,相对其他方式来说具有更少的数据拷贝,效率较高。
2、需要结合信号灯或其他方式来实现多个进程间同步,自身不具备同步机制。
3、随内核持续,相比于随进程持续生命力更强。
3. 管道
1、较早的一种通信方式,缺点明显:只能用于有亲缘关系进程之间的通信;只支持单向数据流,如果要双向通信需要多创建一个管道来实现。
2、自身具备同步机制。
3、随进程持续。
4. FIFO
1、是有名管道,所以支持没有亲缘关系的进程通信。和共享内存类似,提供一个路径名字将各个无亲缘关系的进程关联起来。但是也需要创建两个描述符来实现双向通信。
2、自身具备同步机制。
3、随进程持续。
5. 信号
1、这种通信可携带的信息极少。不适合需要经常携带数据的通信。
2、不具备同步机制,类似于中断,什么时候产生信号,进程是不知道的。
6. 消息队列
1、与共享内存和FIFO类似,使用一个路径名来实现各个无亲缘关系进程之间的通信。消息队列相比于其他方式有很多优点:它提供有格式的字节流,减少了开发人员的工作量;消息具有类型(system V)或优先级(posix)。其他方式都没有这些优点。
1、具备同步机制。
2、随内核持续。
三、进程间通讯实现方式
1、有名管道(不相关的没有血缘关系的进程也可以相互通信)
1、管道创建 #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *filename, mode_t mode); int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t)0); filname是指文件名,而mode是指定文件的读写权限。mknod是比较老的函数,而使用mkfifo函数更加简单和规范,所以建议用mkfifo。 open(const char *path, O_RDONLY);//1 open(const char *path, O_RDONLY | O_NONBLOCK);//2 open(const char *path, O_WRONLY);//3 open(const char *path, O_WRONLY | O_NONBLOCK);//4
1、写入端代码 #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <string.h> int main() { const char *fifo_name = "/tmp/my_fifo"; int pipe_fd = -1; int data_fd = -1; int res = 0; const int open_mode = O_WRONLY; int bytes_sent = 0; char buffer[PIPE_BUF + 1]; int bytes_read = 0; if(access(fifo_name, F_OK) == -1) { printf ("Create the fifo pipe. "); res = mkfifo(fifo_name, 0777); if(res != 0) { fprintf(stderr, "Could not create fifo %s ", fifo_name); exit(EXIT_FAILURE); } } printf("Process %d opening FIFO O_WRONLY ", getpid()); pipe_fd = open(fifo_name, open_mode); printf("Process %d result %d ", getpid(), pipe_fd); if(pipe_fd != -1) { bytes_read = 0; data_fd = open("Data.txt", O_RDONLY); if (data_fd == -1) { close(pipe_fd); fprintf (stderr, "Open file[Data.txt] failed "); return -1; } bytes_read = read(data_fd, buffer, PIPE_BUF); buffer[bytes_read] = '