IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 进程通信--匿名管道和命名管道 -> 正文阅读

[系统运维]进程通信--匿名管道和命名管道

通信的本质是传递数据,是相互的。进程之间不能“直接”相互传递数据,因为进程具有独立性,所有的数据操作都会发生写时拷贝,所以一定要通过媒介的方式来传播。
什么是管道?管道是Unix最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

一.匿名管道

供具有血缘关系的进程进行进程间通信,常见于父子进程。
1.父进程创建管道
以读方式打开一次,以写方式打开一次,文件描述符3,4就会指向同一个文件
请添加图片描述
2.父进程fork出子进程
子进程写时拷贝父进程
请添加图片描述
3.父进程关闭fd[0],子进程关闭fd[1]
父子进程各自关闭不需要的文件描述符,来达到构建单向通信的信道目的,父进程写入,子进程读取请添加图片描述
为什么曾经读写端都要打开?因为不打开rw,子进程拿到的文件打开方式必定和父进程一样,两个都是r或者两个都是w,无法通信;父进程w子进程r或者子进程w父进程r更加灵活。
为什么一定要关闭呢?因为放置误操作。
管道为什么只能单向通信呢?因为读写位只有一个。

例子:从键盘读取数据,写入管道,读取管道,写到屏幕
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main( void )
{
    int fds[2];
    char buf[100];
    int len;
    
    if ( pipe(fds) == -1 )
        perror("make pipe"),exit(1);
    // read from stdin
    while ( fgets(buf, 100, stdin) ) {
        len = strlen(buf);
        // write into pipe
        if ( write(fds[1], buf, len) != len ) {
             perror("write to pipe");
             break;
        }
        memset(buf, 0x00, sizeof(buf));
        
        // read from pipe
        if ( (len=read(fds[0], buf, 100)) == -1 ) {
            perror("read from pipe");
            break;
        }
        
       // write to stdout
       if ( write(1, buf, len) != len ) {
           perror("write to stdout");
           break;
        }
    }
 }

二.匿名管道的特性

如果管道里面没有消息,父进程(读端)就会等待,等子进程写入,管道内部有数据就绪;如果管道里面写端已经写满了,不能继续写了,等待父进程读取,管道内部有空闲空间;如果读端在读,但是写端不写并且关闭,读端读取到0,文件结束;如果读端不读,而且读端关闭,一直写毫无意义,一直写本质就是在浪费系统资源,写进程会立马被OS终止掉,此时写进是子进程,通过发送信号的方式
(1)管道自带同步机制
(2)管道是单向通信的
(3)管道是面向字节流的
(4)管道只能保证是具有血缘关系的进程通信,常用于父子
(5)管道可以保证一定程度的数据读取的原子性
(6)进程退出,曾经打开的文件也会被关掉,管道也是文件,管道的声明周期是随进程的

三.命名管道

请添加图片描述

管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件
命名管道可以从命令行上创建,命令行方法是使用下面这个命令:$ mkfifo filename
命名管道也可以从程序里创建,相关函数有:int mkfifo(const char *filename,mode_t mode);
创建命名管道:

int main(int argc, char *argv[])
{
 mkfifo("p2", 0644);
 return 0;
}

匿名管道和命名管道的区别:
(1)匿名管道由pipe函数创建并打开。
(2)命名管道由mkfifo函数创建,打开用open
(3)FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

四.用命名管道实现server&client通信

# ll
total 12
-rw-r--r--. 1 root root 46 Sep 18 22:37 clientPipe.c
-rw-r--r--. 1 root root 164 Sep 18 22:37 Makefile
-rw-r--r--. 1 root root 46 Sep 18 22:38 serverPipe.c

# cat Makefile
.PHONY:all
all:clientPipe serverPipe
serverPipe.c
clientPipe:clientPipe.c
     gcc -o $@ $^
serverPipe:serverPipe.c
     gcc -o $@ $^
 
.PHONY:clean
clean:
     rm -f clientPipe serverPipe

serverPipe.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define ERR_EXIT(m) \
do{\
    perror(m);\
    exit(EXIT_FAILURE);\
}while(0)

int main()
{
    umask(0);
    if(mkfifo("mypipe", 0644) < 0){
        ERR_EXIT("mkfifo");
    }
    int rfd = open("mypipe", O_RDONLY);
    if(rfd < 0){
         ERR_EXIT("open");
    }
    
    char buf[1024];
    while(1){
        buf[0] = 0;
        printf("Please wait...\n");
        ssize_t s = read(rfd, buf, sizeof(buf)-1);
        if(s > 0 ){
             buf[s-1] = 0;
             printf("client say# %s\n", buf);
        }else if(s == 0){
            printf("client quit, exit now!\n");
            exit(EXIT_SUCCESS);
        }else{
            ERR_EXIT("read");
        }
    }
    close(rfd);
    return 0;
}

clientPipe.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define ERR_EXIT(m) \
do{\
   perror(m);\
   exit(EXIT_FAILURE);\
}while(0)
int main()
{
    int wfd = open("mypipe", O_WRONLY);
    if(wfd < 0){
         ERR_EXIT("open");
    }
    char buf[1024];
    while(1){
          buf[0] = 0;
          printf("Please Enter# ");
          fflush(stdout);
          ssize_t s = read(0, buf, sizeof(buf)-1);
          if(s > 0 ){
               buf[s] = 0;
               write(wfd, buf, strlen(buf));
          }else if(s <= 0){
                ERR_EXIT("read");
           }
   }
   close(wfd);
   return 0;
}
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:59:52  更:2022-03-08 23:02:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 3:43:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码