进程间通信(管道通信)
1.管道通信:
(1)匿名管道:
匿名管道的特点是没有名称,所以用户无法使用open来创建和打开,但是匿名管道进行数据读写的方式和普通文件一样,都是支持read()/write()操作的。
思考:匿名管道在Linux系统下属于文件,但是匿名管道没有名称,请问应该如何创建匿名管道以及对匿名管道进行访问?
回答:Linux系统提供了系统调用接口pipe()来创建匿名管道,用户可以通过man 2 pipe来查阅函数的使用规则。

可以看到pipe函数由一个名字叫做pipefd的参数,该参数是一个数组类型,用于存储对管道进行读写的文件描述符,pipefd[0]记录管道读取端的文件描述符,pipefd[1]记录管道写入端的文件描述符。另外,用户把对数据写入到管道之后,数据是会在内核的缓冲区中进行暂存的,直到从管道中读取该数据为止。
思考:可以看到pipe函数调用成功可以得到创建成功的匿名管道关于读取端和写入端的文件描述符,这样两个进程之间就可以通过文件描述符对匿名管道进行访问,但由于匿名管道没有名称,请问匿名管道适合什么样的进程使用?以及进程中什么时候适合创建匿名管道?
回答:由于匿名管道没有名称,所以只适合在有亲缘关系的进程中使用,一般经常用于父子进程之间。
设计一个程序,实现在程序中创建一个子进程,然后父子进程通过匿名管道进行通信,要求子进程发送字符串“Hello Father,I am Child!”,要求父进程把子进程发送的数据输出到终端,然后父子进程退出。
点击查看代码
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc,char const *argv[]){
//1.创建匿名管道
int piped_fd[2] = {0};
int ret = pipe(piped_fd);
if(-1 == ret){
fprintf(stderr,"pipe error,errno:%d,%s",errno,strerror(errno));
return -1;
}
//2.创建子进程,调用fork函数的时候就已经创建子进程
pid_t child_pid = fork();
if (child_pid > 0)
{
//说明是父进程的进程空间
char recvbuf[30] = {0};
read(piped_fd[0],recvbuf,sizeof(recvbuf));
printf("the massage from child is %s\n",recvbuf);
wait(NULL);
}
else if( child_pid == 0)
{
//说明是子进程的进程空间
char sendbuf[30] = "Hello child,I am father";
write(piped_fd[1],sendbuf,strlen(sendbuf));
}
else
{
printf("child process fork error\n");
return -1;
}
return 0;
}
点击查看代码
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#define FIFO_PATH "/tmp/fifo"
int main(int argc,char const *argv[]){
//1.进程A创建有名管道
int ret = mkfifo(FIFO_PATH,0777);
if(-1 == ret){
fprintf(stderr,"mkfifo error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.进程A打开有名管道
int fifo_fd = open(FIFO_PATH,O_RDWR);
if(-1 == fifo_fd){
fprintf(stderr,"open error,errno:%d,%s\n",errno,strerror(errno));
exit(2);
}
//3.进程A获取时间并格式化为字符串,写入管道文件中
time_t tim = time(NULL);
char *ptime;
while(1){
ptime = ctime(&tim);
write(fifo_fd,ptime,strlen(ptime));
sleep(1);
}
//4.关闭有名管道
close(fifo_fd);
return 0;
}
点击查看代码
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <strings.h>
#define FIFO_PATH "/tmp/fifo"
#define LOG_PATH "./log.txt"
int main(int argc,char const *argv[]){
//1.创建log.txt
int log_fd = open(LOG_PATH,O_RDWR|O_CREAT);
if(-1 == log_fd){
fprintf(stderr,"oprn log error,errorno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.进程B打开有名管道
int fifo_fd = open(FIFO_PATH,O_RDWR|O_CREAT);
if(-1 == fifo_fd){
fprintf(stderr,"open fifo error,errno:%d,%s\n",errno,strerror(errno));
exit(2);
}
//3.进程B读取有名管道
char timebuf[126] = {0};
while(1){
read(fifo_fd,timebuf,sizeof(timebuf));
write(log_fd,timebuf,sizeof(timebuf));
bzero(timebuf,sizeof(timebuf));
sleep(1);
}
//4.关闭有名管道
close(fifo_fd);
close(log_fd);
return 0;
}
浙公网安备 33010602011771号