进程间通信顾名思义就是两个或多个进程间进行通信,在UNIX系统中IPC(InterProcess Commu)是各种进程通信方式的总称。以下对几种进程间通信方式进行说明。
匿名管道(pipe)
这是一种半双工的工作方式,只适用于有亲缘关系的进程间使用,通常由一个进程创建,该进程调用fork,此后父子进程就可以使用该管道。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int pfd[2];
pid_t pid;
if(pipe(pfd) == -1){
perror("pipe");
exit(0);
}
pid = fork();
if(pid < 0){
perror("fork()");
exit(0);
}
if(pid == 0){
char buf;
close(pfd[1]); //关闭写端
while(read(pfd[0],&buf,6) > 0)
printf("buf = %s\n",&buf);
close(pfd[0]);
}
if(pid > 0){
close(pfd[0]); //关闭读端
write(pfd[1],"hello",6);
wait(NULL);
}
close(pfd[1]);
return 0;
}
当读一个写断已经关闭的管道时,在所有数据被读取完后,read返回0。
当写一个读端被关闭的管道时,产生SIGPIPE(管道断裂)信号。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int pfd[2];
pid_t pid;
if(pipe(pfd) == -1){
perror("pipe");
exit(0);
}
pid = fork();
if(pid < 0){
perror("fork()");
exit(0);
}
if(pid == 0){
close(pfd[1]);
while(1);
}
if(pid > 0){
int cnt = 0;
close(pfd[0]);
while(1){
write(pfd[1],"1",1);
cnt ++;
printf("size = %d\n",cnt);
}
wait(NULL);
}
close(pfd[1]);
return 0;
}
通过循环向管道中写入数据,但读端不进行读取,获取到管道的大小为65536.
简单来说,当一个管道创建时,他会向用户返回两个文件描述符,一个是读端,一个是写端,用户只需要对其文件描述符操作即可。通常规定为fd[0]为读端,fd[1]为写端。
命名管道(FIFO)
FIFO是一种文件类型,创建FIFO类似于创建文件,使用mkfifo函数。
#include <sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
返回值:若成功返回0,若出错返回-1
具体代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define _GNU_SOURCE
struct aaa
{
char name[5];
int age;
};
int main(int argc, char *argv[])
{
int ret;
int fd;
char buf ;
struct aaa msg;
ret = mkfifo("./fifo",0664); //创建管道
if(ret < 0)
{
if(errno != EEXIST)
{
perror("mkfifo error!\n");
return -1;
}
}
else
printf("mkfifo success!\n");
fd = open("./fifo",O_RDONLY); //以只读方式打开管道
if(fd < 0)
{
perror("open failed!\n");
return -1;
}
printf("fifo read fd = %d \n",fd);
while(1)
{
read(fd,&buf,10); //读取管道中的数据
printf("%s\n",&buf);
}
close(fd);
unlink("./fifo");
return 0;