linux高编之进程间通讯篇(1)

时间:2021-12-19 17:00:05

进程间通讯,分为:信号,管道,命名管道,共享内存,信号量,套接字,消息队列。

此篇中,套接字和信号暂时不说。

 

一、管道:(亲缘进程间通讯)(单向,先发先到)

 

函数: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;
}

两个例子合起来使用,一个收一个发,而且你会发现,创建的那个文件里面什么都没有,说明他只是个管道,负责运输,但不会保存数据