概述
现在Linux进程间通信方式包括:无名管道(pipe)及有名管道(fifo)、信号(signal)、消息队列(message queue)、共享内存(shared memory)、信号量(semaphore)、套接字(socket)
管道:把一个程序的输出直接连接到另一个程序的输入。
无名管道
(1)只能用于具有亲缘关系的进程之间的通信(父进程和子进程之间)
(2)单工通信模式,固定读端和写端
(3)特殊的文件,可以使用普通的read()、write()等函数,不属于文件系统,只存在于系统中
创建与关闭——pipe()、close()
头文件;#include <unistd.h>
函数原型:int pipe(int fd []);
fd:包含两个元素的整型数组,存放管道对于文件描述符
成功:0
失败:-1
创建管道
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pfd[2];
int ret=pipe(pfd);
if(ret<0)
{
perror("fail to pipe");
exit(-1);
}
}
无名管道是基于文件描述符的通信方式。当一个管道建立时,他会创造两个文件描述符:fd[0]--读端、fd[1]--写端
管道关闭时只需要用close()函数将两个文件描述符关闭
示例:首先创建管道,然后父进程使用fork()函数创建子进程,最后通过关闭父进程的读描述符和子进程的写描述符,建立它们之间的管道通信
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h> //?
#include <sys/wait.h>
#include <string.h>
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
int main()
{
pid_t pid;
int pipe_fd[2];
char buf[MAX_DATA_LEN];
const char data[]="Pipe Test Program";
int real_read,real_write;
memset(buf,0,sizeof(buf));
if(pipe(pipe_fd[2])<0) //创建管道
{
perror("fail to pipe");
exit(-1);
}
if((pid=fork())==0) //创建子进程
{
close(pipe_fd[1]); //子进程关闭写描述符
sleep(DELAY_TIME); //通过暂停1s等待父程序关闭相应的读描述符
if((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) //子进程读取管道内内容到buf里
{
printf("%d bytes read from the pipe is '%s'n",real_read,buf);
}
close(pipe_fd[0]); //关闭子程序读描写符
exit(0);
}
else if(pid>0)
{
close(pipe_fd[0]); //关闭父进程读描述符
if((real_write=write(pipe_fd[1],data,strlen(data)))!=-1)
{
printf(""parent wrote %d bytes:'%s'n",real_write,data);
}
close(pipe_fd[1]); //关闭父进程写描述符
wait(pid,NULL,0); //收集子进程退出信息
exit(0);
}
}
有名管道
创建管道——mkfifo()
头文件:
#include <sys/types.h>
#include <sys/state.h>
函数原型:int mkfifo(const char *filename, mode_t mode)
filename:要创建的管道名
mode:管道的访问权限
成功:0
失败:-1
创建成功后可以使用open()、read()、write()。对于为读而打开的管道可在open()中设置O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY。
示例:示例包含两个程序,一个用于读管道,另一个用于写管道。在读管道的程序里创建管道,并且作为main()函数里的参数由用户输入要写入的内容。读管道的程序会读出用户写入管道的内容。
写管道:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#define MYFIFO "/tmp/myfifo" //有名管道文件名
int main(int argc,char *argv[])
{
int fd;
int nwrite;
if(argv<2)
{
printf("Usage:./fifo_write stringn");
exit(-1);
}
if((fd=open(MYFIFO,O_WRONLY))<0) //以只写方式打开FIFO管道
{
perror("fail to open fifo");
exit(-1);
}
if((nwrite=write(fd,argv[1],strlen(argv[1])+1))>0) //向管道中写入字符串
{
printf("Write '%s' to FIFOn",argv[1]);
}
close(fd);
return 0;
}
读管道:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#define MYFIFO "/tmp/myfifo" //有名管道文件名
int main()
{
char buf[256];
int fd;
//判断有名管道是否已存在,若尚未建立,则以相应的权限创建
if(access(MYFIFO,F_OK)==-1) //管道不存在
{
if(mkfifo(MYFIFO,O666)<0)
{
perror("fail to mkfifo");
exit(-1);
}
}
//以只读的方式打开有名管道
if((fd=open(MYFIFO,O_RDONLY))<0)
{
perror("fail to open fifo");
exit(-1);
}
while(1)
{
memset(buf,0,sizeof(buf)); //?
if((nread=read(fd,buf,256))>0)
{
printf("Read '%s' from FIFOn",buf);
}
}
close(fd);
return 0;
}
最后
以上就是优雅毛巾为你收集整理的【Linux】管道通信的全部内容,希望文章能够帮你解决【Linux】管道通信所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复