进程间通讯,分为:信号,管道,命名管道,共享内存,信号量,套接字,消息队列。
此篇中,套接字和信号暂时不说。
一、管道:(亲缘进程间通讯)(单向,先发先到)
函数:int pipe (int filefd [2]);
函数中数组里面存放着两个文件描述符(返回值),filefd[0]为读而打开,filefd[1]为写而打开。
运用:比如在一个程序中,用pipe()函数后,在用fork()函数打开一个子进程,父进程中用close()函数关闭filefd[1],而子进程中用close()函数关闭filefd[0],这样,父子进程之间通讯就可以用剩下的两个文件描述符来收发信息了。这里要说明的是,管道是单向的,因此上面这样操作的话,只能够通过子进程来发,父进程来收。具体情况可以根据需求来定消息收发的方向。或者可以再开一个子进程,父进程把两个文件描述符全部关闭,而子进程用相同办法来进行两个子进程之间的通讯,所以pipe()这个函数,是不仅可以用在父子进程间的通讯,也可以用在子进程之间的通讯,所以说,这个函数是亲缘进程间通讯的函数。
如果父进程进行发送,而同时开好多个子进程进行接收,那么信息的接收会具有随机性,当时间片到一个子进程而父进程刚之前发送消息的话,那么消息就会被次子进程接收。
最后,接收端如果先关闭,也会导致管道的破裂。
注意点:在linux下管道文件属于比较特殊的文件,此文件windows应该没有,因此在虚拟机运行时,管道文件不能创建在和windows共享的目录下。
相关函数:
Int fp = popen(const char *command,”w/r”);//此函数用于与linux指令进程间通讯,将显示在屏幕上的东西,转到fp中;
inrt pclose(fp);//关闭这个文件描述符
收发分别采用read()、write()两个函数。
二、命名管道:
Int mkfifo(const char *pathname ,mode_t mode);//成功返回0.失败返回-1
pathname 为创建的管道文件
例1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
if(-1 == mkfifo("hello.fifo",0666)){// 创建管道文件,并判断管道文件是否存在
perror("mkfifo");
return -1;
}
printf("create successful.\n");
int fd = open("hello.fifo",O_WRONLY,0);// 以只写权限打开管道文件
if(fd <= 0){
perror("open");
return -1;
}
while(1){
write(fd,"hello",5);//每一秒向管道发送信息
sleep(1);
}
close(fd);
return 0;
}
例2:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
char buf[1024];
int fd = open("hello.fifo",O_RDONLY,0)// 以只读权限打开管道文件
if(fd <= 0){
perror("open");
return -1;
}
while(1){
memset(buf,0,1024);
read(fd,buf,1024);//从管道中读取信息
printf("buf = %s\n",buf);
}
close(fd);
return 0;
}
两个例子合起来使用,一个收一个发,而且你会发现,创建的那个文件里面什么都没有,说明他只是个管道,负责运输,但不会保存数据