本人最近学习了进程间通信,并看了一些博文,然后结合书籍根据自己的理解写了这篇文章。
1. 管道
函数原型:经由参数fd返回两个文件描述符:fd[0]为读,fd[1]为写。fd[1]的输出是fd[0]的输入。
#include <unistd.h>
int pipe(int fd[2]);
局限性:
(1)历史上,它是半双工的,某些系统提供全双工管道,即其可移植性并不好。
(2)它只能在具有公共祖先的两个进程间使用。
示例代码:
#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <string.h>
int main(){
int pipe_fd[2];
int ret = pipe(pipe_fd);//类似两个文件指针,针对管道中的读(0)和写(1)
if(ret == -1)
{
printf("创建管道失败,错误码是:%d,%d\n",error,strerror(error));
return 0;
}
pid_t pid = fork();//创建子进程
if(pid < 0)
{
printf("创建子进程错误\n");
return 0;
}else if(pid == 0)
{ //子进程的操作
close(_pipe[0]); // 关闭读通道
int i = 0;
char sendbuf[BUFSIZ];
while( i < 20){
scanf("%s", sendbuf);
write(pipe_fd[1], sendbuf, strlen(sendbuf));
sleep(2);
i++;
}
}else
{ //进入父进程,从子进程读取数据
close(pipe_fd[1]); //关闭写通道
char recv[BUFSIZ];
while(1){
memset(recv, 0, sizeof(recv));
int length= read(pipe_fd[0], recv, sizeof(recv));
if(strstr(recv, "quit") != 0)
{
printf("退出程序\n");
exit(0);
}
printf("message:%s. length:%d.\n", recv, length);
}
if(waitpid(pid, NULL, 0) < 0)
{ //避免父进程与子进程冲突,让子进程先执行
return 0;
}
}
return 0;
}
运行结果:
2. 命名管道(FIFO)
函数原型:
#include<sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
参数信息:
(1)参数fd为文件描述符。
(2)参数path为路径名。
(3)mode参数指定文件的访问权限位。
FIFO的用途:
(1)shell命令使用FIFO将数据从一条管道传送到另一条时,无需创建中间临时文件。
(2)C/S应用程序中,FIFO用作汇聚点,在二者之间传递数据。
示例代码:fifo-read.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define _PATH_ "/tmp/file.fifo"
int main(){
int fd = open(_PATH_, O_RDONLY);//以只读的权限打开文件
if(fd < 0){
printf("打开失败\n");
return 0;
}
char recv[BUFSIZ];
while(1){
memset(recv, 0, sizeof(recv));//字符串清零
int ret = read(fd, recv, sizeof(recv));
if(strstr(recv, "quit") != 0){ //判断接收到的字符是否是quit
printf("退出程序\n");
exit(0);
}
printf("message:%-20s. length:%d\n", recv, ret);
}
close(fd);//关闭文件
return 0;
}
运行结果:
fifo-write,c
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define _PATH_ "/tmp/file.fifo"
int main(){
int ret = mkfifo(_PATH_, 0666);//创建管道文件
if(ret == -1){
printf("创建管道失败\n");
exit(0);
}
int fd = open(_PATH_, O_WRONLY);//以只写的权限打开文件
if(fd < 0){
printf("打开失败\n");
exit(0);
}
char buf[BUFSIZ];
while(1){
memset(buf, 0, strlen(buf));//字符串清零
printf("please input the string:");
scanf("%s", buf);
int ret = write(fd, buf, strlen(buf));//写数据
if(ret < 0){
printf("写出错\n");
break;
}
if(strstr(buf, "quit") != 0){
break;
}
}
close(fd);//关闭文件
unlink(_PATH_);//删除管道文件
return 0;
}