❤️进程间的通信(1)--管道❤️

本文详细介绍了进程间通信中的无名管道和有名管道。无名管道是半双工的,数据只能单向流动,且存在于内存中。有名管道则是一种特殊类型的文件,允许不同进程间通信。文章讲解了管道的创建、特点以及如何通过fcntl设置管道的阻塞特性,并探讨了文件描述符的复制和FIFO(有名管道)的创建与使用。
摘要由CSDN通过智能技术生成

.一.进程间通信概述

进程间通信(IPC:Inter Processes Communication)
每个进程都是一个独立的资源分配单元,一个进程中不能访问另一个进程,但是不同的进程需要进行数据的交互,因此需要进程间通信。

进程间通信功能
数据传输:一个进程需要将它的数据发送给另一个进程。
资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件。
进程控制:有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的 所有操作,并能够及时知道它的状态改变。
在这里插入图片描述

三.进程间的通信-- 无名管道和有名管道

3.1管道概述

管道又称为无名管道,具体体现在应用层的两个文件描述符上。
在这里插入图片描述

3.2管道的特点

  1. 半双工,同一时刻只能在一个方向流动
  2. 数据只能从管道一遍写入,从另一端读出,比如进程A把数据通过管道写入,进程B从管道里面读取出来
  3. 先入先出
  4. 因为数据是无格式的,所以要约定好数据的格式
  5. 管道存在于内存中,并对应着一个缓冲区,每个系统的缓冲区不太一样
  6. 管道数据被取走后将会立马清空
  7. 无名管道只能在父子进程中使用

3.3无名管道的创建pipe函数

#include <unistd.h>
int pipe(int fd[2])
返回两个文件描述符

参数:
	fd[0]为读并且打开
	fd[1]为写并且打开
返回子:
	成功:0
	失败:-1

代码的编写

在子进程中写,父进程中读

/* ************************************************************************
 *       Filename:  01_pipe_simple.c
 *    Description:  
 *        Version:  1.0
 *        Created:  2021年09月07日 10时08分18秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:  魔动山霸 , 
 *        Company:  
 * ************************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc,char *argv[])
{
/*01--创建*/
int fd[2];
char buf[] = "hello world";
pid_t pid;
if(pipe(fd) < 0)
{
	perror("pipe");
}
pid = fork();
if(pid == 0)
{
	write(fd[1],argv[1],strlen(argv[1]));
	_exit(0);	
}
else if(pid > 0)
{
	wait(NULL);
	memset(buf,0,sizeof(buf));
	read(fd[0],buf,sizeof(buf));
	printf("子进程传过来的数据:%s\n",buf);
}

}

运行效果:
在这里插入图片描述

读写的特点

  1. read从管道读默认带阻塞
  2. write缓冲区满时也会阻塞
  3. 通信过程中,读端口全部关闭后,写进程向管道内写数据时,写进程会(收到 SIGPIPE 信号)退出。

第三点意思是说读端口关闭后,即close(fd[0])
这个时候即使你还在往管道写入,内核会发送一个信号退出程序。

如何通过fcntl设置管道的阻塞特性

我们一般都是在open的时候就设置了文件的特性,但是管道不一样,我们可以通过fcntl这个函数进行
函数原型:

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);         

int fcntl(int fd, int cmd, struct flock *lock);

描述:

           fcntl()针对(文件)描述符提供控制.参数fd是被参数cmd操作(如下面的描述)的描述符.            

    针对cmd的值,fcntl能够接受第三个参数(arg)

fcntl函数有5种功能:

     1.复制一个现有的描述符(cmd=F_DUPFD).

       2.获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).
       
        3.获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).

         4.获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).

         5.获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).

设置为阻塞: fcntl(fd, F_SETFL, 0);
设置为非阻塞: fcntl(fd, F_SETFL, O_NONBLOCK);

4.文件描述符的复制

dup 和 dup2 是两个非常有用的系统调用,都是用来复制一个文件的描述符,使新的文件描述符也标识旧的文件描述符所标识的文件

int dup(int oldfd); 
int dup2(int oldfd, int newfd);

这两个系统调用常用来重定向进程的标准输入,标准输出和标准错误

4.1dup函数
#include <unistd.h> int dup(int oldfd);
 功能:复制 oldfd 文件描述符,并分配一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用 的文件描述符。 
 参数:要复制的文件描述符 oldfd。 返回值:成功:新文件描述符。
 失败:返回-1,错误代码存于 errno 中。

5.有名管道

概念:有名管道和无名管道大体相同

函数原型:
		  #include <sys/types.h>
      	  #include <sys/stat.h>
           int mkfifo(const char *pathname, mode_t mode);


  1. 半双工
  2. 写入先出
  3. 约定好数据格式
  4. FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。
  5. 管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。
  6. 从 FIFO 读数据是一次性操作,数据一旦被读,它就从 FIFO 中被抛弃,释放空间以便写更多的数据
  7. 当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
  8. 特殊类型文件,可通过ls进行查看,用于不相通进程间的通信

5.1创建有名管道

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔动山霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值