使用多线程的方式使用fifo管道实现通信
A程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
char buf[128];
//fifo管道写端线程
void* fifo_w(void* arg)
{
int res = 0;
int fd_w = open("fifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return NULL;
}
//printf("open fifo success\n");
while(1)
{
//终端输入
bzero(buf,sizeof(buf));
printf("A进程说>>>\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
res = write(fd_w,buf,sizeof(buf));
if(res < 0)
{
perror("write");
return NULL;
}
if(0 == strcmp(buf,"quit"))
{
printf("A写端退出\n");
break;
}
}
//关闭文件描述符并退出
pthread_exit(NULL);
close(fd_w);
}
//fifo1管道读端线程
void* fifo1_r(void* arg)
{
int res = 0;
//以只读的方式打开fifo1管道
int fd_r = open("fifo1", O_RDONLY);
if(fd_r < 0)
{
perror("open");
return NULL;
}
//printf("open fifo1 success\n");
while(1)
{
//从管道fifo1中读
bzero(buf,sizeof(buf));
res = read(fd_r,buf,sizeof(buf));
if(res < 0)
{
perror("read");
return NULL;
}
//写端关闭后read不阻塞,当数据读取完毕,直接返回0
else if(0 == res)
{
printf("B写端退出\n");
break;
}
printf("A进程接收到:%s\n",buf);
if(0 == strcmp(buf,"quit"))
{
printf("B写端退出\n");
break;
}
}
pthread_exit(NULL);
close(fd_r);
}
int main(int argc, const char *argv[])
{
//重设文件权限掩码
umask(0);
//创建两个fifo管道,并排除文件已经存在的错误
if(mkfifo("./fifo",0777) < 0 )
{
// printf("errno = %d\n",errno);
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo create success\n");
if(mkfifo("./fifo1", 0777) < 0)
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo1 create success\n");
//创建两个线程
pthread_t tid1,tid2;
if(pthread_create(&tid1,NULL,fifo_w,NULL) < 0)
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid2,NULL,fifo1_r,NULL) <0)
{
perror("pthread_create");
return -1;
}
//阻塞等待线程退出
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
B程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
char buf[128];
//fifo1管道写端线程
void* fifo1_w(void* arg)
{
int res = 0;
int fd_w = open("fifo1",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return NULL;
}
//printf("open fifo1 success\n");
while(1)
{
//终端输入
bzero(buf,sizeof(buf));
printf("B进程说>>>\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
res = write(fd_w,buf,sizeof(buf));
if(res < 0)
{
perror("write");
return NULL;
}
if(0 == strcmp(buf,"quit"))
{
printf("B写端退出\n");
break;
}
}
//关闭文件描述符并退出
pthread_exit(NULL);
close(fd_w);
}
//fifo管道读端线程
void* fifo_r(void* arg)
{
int res = 0;
//以只读的方式打开fifo1管道
int fd_r = open("fifo", O_RDONLY);
if(fd_r < 0)
{
perror("open");
return NULL;
}
//printf("open fifo success\n");
while(1)
{
//从管道fifo中读
bzero(buf,sizeof(buf));
res = read(fd_r,buf,sizeof(buf));
if(res < 0)
{
perror("read");
return NULL;
}
//写端关闭后read不阻塞,当数据读取完毕,直接返回0
else if(0 == res)
{
printf("A进程退出\n");
break;
}
printf("B进程接收到:%s\n",buf);
if(0 == strcmp(buf,"quit"))
{
printf("A写端退出\n");
break;
}
}
pthread_exit(NULL);
close(fd_r);
}
int main(int argc, const char *argv[])
{
//重设文件权限掩码
umask(0);
//创建两个fifo管道,并排除文件已经存在的错误
if(mkfifo("./fifo",0777) < 0 )
{
// printf("errno = %d\n",errno);
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo create success\n");
if(mkfifo("./fifo1", 0777) < 0)
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo1 create success\n");
//创建两个线程
pthread_t tid1,tid2;
if(pthread_create(&tid1,NULL,fifo1_w,NULL) < 0)
{
perror("pthread_create");
return -1;
}
if(pthread_create(&tid2,NULL,fifo_r,NULL) <0)
{
perror("pthread_create");
return -1;
}
//阻塞等待线程退出
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
使用多进程的方式使用fifo管道实现通信,并加入使用信号回收僵尸进程的方法
A程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
char buf[128];
//重定义用sighandler_t代表返回值为void有一个int类型的参数的函数指针
typedef void (*sighandler_t)(int);
//回收僵尸进程的任务
void recycle(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
//重设文件权限掩码
umask(0);
//创建两个fifo管道,并排除文件已经存在的错误
if(mkfifo("./fifo",0777) < 0 )
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo create success\n");
if(mkfifo("./fifo1", 0777) < 0)
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo1 create success\n");
//创建子进程
pid_t pid = fork();
if(pid > 0)
{
//捕获信号
sighandler_t s = signal(SIGCHLD, recycle);
if(SIG_ERR == s)
{
perror("signal");
return -1;
}
int res = 0;
//以只写的方式打开fifo管道
int fd_w = open("fifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
while(1)
{
//终端输入
bzero(buf,sizeof(buf));
printf("A进程说>>>\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
//写入数据到fifo管道
res = write(fd_w,buf,sizeof(buf));
if(res < 0)
{
perror("write");
return -1;
}
if(0 == strcmp(buf,"quit"))
{
printf("A写端退出\n");
break;
}
}
//关闭文件描述符
close(fd_w);
//等待子进程退出
wait(NULL);
}
else if(0 == pid)
{
int res = 0;
int fd_r = open("fifo1", O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
while(1)
{
//从管道fifo1中读
bzero(buf,sizeof(buf));
res = read(fd_r,buf,sizeof(buf));
if(res < 0)
{
perror("read");
return -1;
}
else if(0 == res)
{
printf("B进程退出\n");
break;
}
printf("A进程接收到:%s\n",buf);
if(0 == strcmp(buf,"quit"))
{
printf("B写端退出\n");
break;
}
}
close(fd_r);
}
else
{
perror("fork");
return -1;
}
return 0;
}
B进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
char buf[128];
//重定义用sighandler_t代表返回值为void有一个int类型的参数的函数指针
typedef void (*sighandler_t)(int);
//回收僵尸进程的任务
void recycle(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
//回收僵尸进程的任务
umask(0);
//创建两个fifo管道,并排除文件已经存在的错误
if(mkfifo("./fifo",0777) < 0 )
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo create success\n");
if(mkfifo("./fifo1", 0777) < 0)
{
if(17 != errno)
{
perror("mkfifo");
return -1;
}
}
else
printf("fifo1 create success\n");
//创建子进程
pid_t pid = fork();
if(pid > 0)
{
//捕获信号
sighandler_t s = signal(SIGCHLD, recycle);
if(SIG_ERR == s)
{
perror("signal");
return -1;
}
int res = 0;
//以只写的方式打开fifo1管道
int fd_w = open("fifo1",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
while(1)
{
//终端输入
bzero(buf,sizeof(buf));
printf("B进程说>>>\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
//写入数据到fifo1管道
res = write(fd_w,buf,sizeof(buf));
if(res < 0)
{
perror("write");
return -1;
}
if(0 == strcmp(buf,"quit"))
{
printf("B写端退出\n");
break;
}
}
//关闭文件描述符
close(fd_w);
//等待子进程退出
wait(NULL);
}
else if(0 == pid)
{
int res = 0;
int fd_r = open("fifo", O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
while(1)
{
//从管道fifo中读
bzero(buf,sizeof(buf));
res = read(fd_r,buf,sizeof(buf));
if(res < 0)
{
perror("read");
return -1;
}
else if(0 == res)
{
printf("A进程退出\n");
break;
}
printf("B进程接收到:%s\n",buf);
if(0 == strcmp(buf,"quit"))
{
printf("A写端退出\n");
break;
}
}
close(fd_r);
}
else
{
perror("fork");
return -1;
}
return 0;
}