Linux进程间通信之有名管道(四)

1.有名管道的特点

命名管道(FIFO)和管道(pipe)基本相同,但也有一些显著的不同,其特点是:
1、半双工,数据在同一时刻只能在一个方向上流动。
2、写入FIFO中的数据遵循先入先出的规则。
3、FIFO所传送的数据是无格式的,这要求FIFO的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等。
4、FIFO在文件系统中作为一个特殊的文件而存在,但FIFO中的内容却存放在内存中。
5、管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。
6、从FIFO读数据是一次性操作,数据一旦被读,它就从FIFO中被抛弃,释放空间以便写更多的数据。
7、当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用。
8、FIFO有名字,不相关的进程可以通过打开命名管道进行通信。

2.有名管道创建和使用

	int mkfifo( const char *pathname, mode_t mode);

功能:
有名管道创建

参数:
pathname:FIFO的路径名+文件名。
mode:mode_t类型的权限描述符。

返回值:
成功:返回 0
失败:如果文件已经存在,则会出错且返回-1。

3.有名管道读写的特点

操作FIFO文件时的特点 系统调用的I/O函数都可以作用于FIFO,如open、close、read、write等。 打开FIFO时,非阻塞标志(ONONBLOCK)产生下列影响: 特点一: 不指定ONONBLOCK(即open没有位或O_NONBLOCK) 1、open以只读方式打开FIFO时,要阻塞到某个进程为写而打开此FIFO 2、open以只写方式打开FIFO时,要阻塞到某个进程为读而打开此FIFO。 3、open以只读、只写方式打开FIFO时会阻塞,调用read函数从FIFO里读数据时read也会阻塞。 4、通信过程中若写进程先退出了,则调用read函数从FIFO里读数据时不阻塞;若写进程又重新运行,则调用read函数从FIFO里读数据时又恢复阻塞。 5、通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到SIGPIPE信号)退出。 6、调用write函数向FIFO里写数据,当缓冲区已满时write也会阻塞。
打开FIFO时,非阻塞标志(ONONBLOCK)产生下列影响: 特点二: 指定ONONBLOCK(即open位或O_NONBLOCK) 1、先以只读方式打开:如果没有进程已经为写而打开一个FIFO, 只读open成功,并且open不阻塞。 2、先以只写方式打开:如果没有进程已经为读而打开一个FIFO,只写open将出错返回-1。 3、read、write读写命名管道中读数据时不阻塞。 4、通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到SIGPIPE信号)退出。 注意: open函数以可读可写方式打开FIFO文件时的特点: 1、open不阻塞。 2、调用read函数从FIFO里读数据时read会阻塞。 3、调用write函数向FIFO里写数据,当缓冲区已满时write也会阻塞。

4.客户端与服务器通信

说明:需要先运行服务器才可以运行客户端,否在会先运行客户端会失败。因为管道没有打开。

4.1.参考代码(客户端)

//=============================================================================
// File Name    : process_mkfifo_client.c
// Author       : FengQQ
//
// Description  : 创建有名管道客户端
// Annotation   : 
//
// Created by FengQQ. 2020-9-29
//=============================================================================
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>

#define BUFFER_SIZE 256

const char *write_fifo = "write_fifo";
const char *read_fifo = "read_fifo";

int main(int argc,char *argv[])
{
	int ret;
	int read_fd;
	int write_fd;
	char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];

	read_fd = open(write_fifo,O_RDONLY);			//打开写管道
	
	if(read_fd < 0)
	{
		printf("open write_fifo failed...\r\n");
		exit(1);
	}
	if(access(read_fifo,F_OK))						//判断是否具有存取文件的权限	
	{
		ret = mkfifo(read_fifo,0755);				//创建有名管道
		if(ret < 0)
		{
			printf("mkfifo create failed...\r\n");
			exit(1);
		}
	}
	
	write_fd = open(read_fifo,O_WRONLY);			//打开读管道
	if(write_fd < 0)
	{
		printf("open read_fifo failed..\r\n");
		exit(1);
	}
	
	while(1)
	{
		memset(recvbuf,0x00,strlen(recvbuf));
		read(read_fd,recvbuf,BUFFER_SIZE);			//向管道中读取数据
		printf("Ser:%s\n",recvbuf);					//打印服务端数据
		printf("Cli:");								//打印客户端数据
		scanf("%s",sendbuf);						//获取键盘输入
		if(strcmp(sendbuf,"quit") == 0)				//判断是否退出
		{
			unlink(read_fifo);						//删除文件
			break;
		}
		write(write_fd,sendbuf,strlen(sendbuf+1));	//向管道中写数据
	}
	
	close(write_fd);								//关闭文件			
	close(read_fd);									//关闭文件			
	
	return 0;
}

4.2.参考代码(服务器)

//=============================================================================
// File Name    : process_mkfifo_server.c
// Author       : FengQQ
//
// Description  : 创建有名管道服务端
// Annotation   : 
//
// Created by FengQQ. 2020-9-29
//=============================================================================
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>

#define BUFFER_SIZE 256
const char *write_fifo= "write_fifo";
const char *read_fifo= "read_fifo";

int main(int argc,char *argv[])
{
	int ret;
	int write_fd;
	int read_fd;
	char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
	
	if(access(write_fifo,F_OK))
    {
        ret= mkfifo(write_fifo,0755);				//创建有名管道
        if(ret== -1)
        {
            perror("mkfifo");
            exit(1);
        }
    }
    write_fd= open(write_fifo,O_WRONLY);			//打开写管道		
    if(write_fd== -1)
    {
        perror("open write_fifo.");
        exit(1);
    }
    
    while(1)
    {
        read_fd= open(read_fifo,O_RDONLY);				//打开读管道
        if(read_fd== -1)
        {
            sleep(1);
            continue;
        }
        break;
    }
    
    while(1)
    {
        printf("Ser:");									//打印服务端数据
        scanf("%s",sendbuf);							//获取键盘输入
        if(strcmp(sendbuf,"quit")== 0)					//判断是否退出
        {
            unlink(write_fifo);							//删除文件
            break;
        }
        write(write_fd,sendbuf,strlen(sendbuf)+ 1);		//向管道中写数据
		memset(recvbuf,0x00,strlen(recvbuf));
        read(read_fd,recvbuf,BUFFER_SIZE);				//向管道中读取数据
        printf("Cli:%s\n",recvbuf);						//打印客户端数据
    }
    close(write_fd);									//关闭文件
    close(read_fd);										//关闭文件
    return 0;
	
}

Linux进程间通信之消息队列(五)
链接: link.(https://blog.csdn.net/qq_39721016/article/details/119281014?spm=1001.2014.3001.5501)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值