引言
进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。另外,系统空间是“公共场所”,各进程均可以访问,所以内核也可以提供这样的条件
进程间通信(IPC,Interprocess communication)是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息。这使得一个程序能够在同一时间里处理许多用户的要求。因为即使只有一个用户发出要求,也可能导致一个操作系统中多个进程的运行,进程之间必须互相通话。IPC接口就提供了这种可能性。每个IPC方法均有它自己的优点和局限性,一般,对于单个程序而言使用所有的IPC方法是不常见的。
IPC方法包括管道(PIPE)、消息队列、共享内存、信号量(旗语)、以及套接字(Socket)。
1、无名管道pipe
1.1 简述
管道有无名管道和命名管道,以管道的进程间通信的构建较为简单,但不适合进程间频繁的数据交互。
1.2 特点
(1)无名管道pipe为半双工通信方式,具有固定的读端fd[0],写端fd[1]。即数据在同一时刻只能在一个方向传输。
(2)无名管道只能用于具有亲缘关系的进程之间通信(例如父子进程)
(3)管道是一种特殊的文件类型,只存在内存中,而不存在于文件系统。
1.3 函数原型
#include <unistd.h>
int pipe(fd[2]);//返回值:成功返回0,失败返回-1
1.4 例程
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int fd[2]; //无名管道参数,fd[0]为管道固定的读端,fd[1]为管道固定的写端
char buff[128];
if(pipe(fd) == -1) //创建无名管道
{
perror("create pipe failed.\n");
exit(0);
}else{
if((pid = fork()) == -1) //创建子进程
{
perror("fork failed.why:");
exit(0);
}
else if(pid > 0)
{
printf("Ready to send message......\n");
sleep(3);
close(fd[0]); //关闭读端fd[0],向写端fd[1]写入数据
write(fd[1], "hello my son.\n", strlen("hello my son.\n"));
wait(NULL);
}
else if(pid == 0)
{
close(fd[1]); //关闭写端fd[1],从读端fd[0]读取数据
read(fd[0], buff, 128);
printf("read from farther:%s\n", buff);
exit(0);
}
}
return 0;
}
1.5 例程说明
父进程休眠3秒后,打开写端,关闭读端。向创建的无名管道写入数据。
子进程等待父进程写入管道中的数据。
Ready to send message......
read from farther:hello my son.
2、命名管道FIFO
2.1 简述
命名管道可以令无关进程之间进行通信,故可以利用命名管道可以形成多个客户端(多个写端)——>一个服务器(一个读端)的多个进程间的通信。
2.2 特点
(1)FIFO可以在无关的进程之间交换数据,与无名管道不同。
(2)FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
2.3 函数原型
#include <sys/stat.h>
// 返回值:成功返回0,出错返回-1
int mkfifo(const char *pathname, mode_t mode);
2.4 例程
read_fifo.c
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int ret;
char *read_message = NULL;
if((ret = mkfifo("FIFO", 0600)) == -1) //创建命名管道
{
perror("create fifo fialed.why:");
if(errno == EEXIST)
{
printf("fifo exists\n");
}
}else{
printf("create fifo successfully.\n");
}
int fd = open("./FIFO", O_RDWR); //打开管道
if(fd == -1)
{
perror("open failed.why:");
exit(0);
}
read_message = (char*)malloc(sizeof(char) *128);
read(fd, read_message, 128);//等待读取管道中的数据
printf("Receive:%s\n", read_message);
close(fd);
exit(0);
}
write_fifo.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main()
{
int fd;
char *write_message = NULL;
if((fd = open("./FIFO", O_RDWR)) == -1)
{
perror("open failed.why:");
exit(0);
}
printf("open success.\n");
write_message =(char *)malloc(sizeof(char) *128);
gets(write_message);
write(fd, write_message, 128);
printf("Mr.anrang:%s\n", write_message);
close(fd);
exit(0);
}
2.5 例程说明
首先执行read_fifo.c中的程序,创建管道->打开管道->等待读取管道数据->读取管道数据->关闭管道->退出程序
再执行write_fifo.c中的程序,打开管道->gets键入内容->向管道写入数据->关闭管道->退出程序