一、实验目的
1.了解操作系统中的无名管道和有名管道
2.掌握进程通信中的管道编程模型
二、实验内容
管道是一种进程间通信的方式,在linux中分为有名管道和无名管道。有名管道就是把一个进程的输出写到一个文件中,再把此文件作为另一个进程的输入,普通管道只能用于父子进程,而有名管道能用于不相关的进程间。本次实验的内容需要编写一个普通管道程序和命名管道程序,并测试。
三、实验要求
实验需要提前准备一台PC机,并在PC机上搭建Linux Ubuntu环境。
四、实验步骤及操作
1.打开Linux系统,新建一个终端
2.新建文件
3.编写代码
4.编译运行
五、程序源码
1. 普通管道 piperw.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#define BUFSZ PIPE_BUF
void err_quit(char *msg);
int main(int argc, char *argv[])
{
int fd[2]; //文件描述符fd[0]表示读取管道,fd[1]表示写入管道
int fdin; /* 输入文件描述符 */
char buf[BUFSZ];//buf为缓冲区
int pid, len;
/* Create the pipe */
if((pipe(fd)) < 0)
err_quit("pipe");
/* 分叉并关闭适当的描述符 */
if((pid = fork()) < 0)
err_quit("fork");
if (pid == 0) {
close(fd[1]);//关闭子进程的写数据
//read()函数调用成功会返回读取到的字节数
while((len = read(fd[0], buf, BUFSZ)) > 0)
//STDOUT_FILENO表示将buf中的内容写到标准输出
write(STDOUT_FILENO, buf, len);//STDIN_FILENO表示标准输出
close(fd[0]);
} else {
/* Parent是writer,关闭读描述符 */
close(fd[0]);
//open函数打开文件成功
if((fdin = open(argv[1], O_RDONLY)) < 0) {
perror("open");
/* 发送一些东西,因为我们无法打开输入 */
write(fd[1], "123\n", 4);
} else {
//管道里的数据必须被读走
while((len = read(fdin, buf, BUFSZ)) > 0)
write(fd[1], buf, len);
close(fdin);
}
/* 关闭写描述符 */
close(fd[1]);
}
//waitpid会使目前进程暂停,直到有信号来或者子进程结束
waitpid(pid, NULL, 0);
exit(EXIT_SUCCESS);
}
void err_quit(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
2. 无名管道 wrfifo.c
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <time.h>
int main(int argc, char *argv[])
{
int fd; /* FIFO文件描述符 */
int len; /* 写入FIFO的字节 */
char buf[PIPE_BUF]; /* 确保原子写入 */
time_t tp; /* For time call */
/* Identify myself */
printf("I am %d\n", getpid());
/* Open the FIFO write-only */
if((fd = open(argv[1], O_WRONLY)) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
/* Generate some data to write */
while(1) {
/* 获取当地时间 */
time(&tp);
/* 创建要写入的字符串 */
len = sprintf(buf, "wrfifo %d sends %s", getpid(), ctime(&tp));
/* 使用(len + 1),因为sprintf不计算结束的null */
if((write(fd, buf, len + 1)) < 0) {
perror("write");
close(fd);
exit(EXIT_FAILURE);
}
printf("%s",buf);
sleep(3);
}
close(fd);
exit(EXIT_SUCCESS);
}
3. 有名管道 rdfifo.c
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
void myfunc1(int sign_no)
{
if(sign_no==SIGINT){
printf("\nExit pipe!\n");
}
else if(sign_no==SIGQUIT)
printf("I have get SIGQUIT\n");
}
int main(int argc, char *argv[])
{
printf("I am %d\n", getpid());
int fd; /* Descriptor for FIFO */
int len; /* Bytes read from FIFO */
char buf[PIPE_BUF];
char buf1[50]="Hello,Bit-Dong!";
//在当前目录下创建一个有名管道
unlink("test_rdfifo");
if((mkfifo("test_rdfifo",0777)) < 0) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
/* Open the FIFO read-write */
if((fd = open("test_rdfifo", O_RDWR)) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if((write(fd,buf1,50))<0){
perror("write");
}
/* 读取并显示FIFO的输出直到EOF */
len = read(fd, buf, PIPE_BUF - 1);
printf("rdfifo read: %s\n", buf);
signal(SIGINT, myfunc1);
sleep(10);
close(fd);
exit(EXIT_SUCCESS);
}
版权声明:本文为Dustinthewine原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。