首页 > 系统相关 >【Linux学习】进程间通信 (1) —— 管道

【Linux学习】进程间通信 (1) —— 管道

时间:2024-05-24 19:56:30浏览次数:15  
标签:int 间通信 管道 fd Linux 进程 include buf

下面是有关进程通信中管道的相关介绍,希望对你有所帮助!

小海编程心语录-CSDN博客

1. 进程通信的基本概念

1.1 概念

进程间通信简称 IPC ,指两个进程之间的通信。 IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。

1.2 目的

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

1.3 通信方式 

  1. UNIX IPC: 管道、FIFO、信号
  2. System V IPC: 信号量、消息队列、共享内存
  3. Socket IPC: 基于Socket进程间通信

2. 管道 

把一个进程连接到另一个进程的数据流称为管道,是一个半双工的通信方式。

管道分为有名管道无名管道两种,它们的区别是:

无名管道只能在有亲缘关系的进程之间进行通信。

有名管道又称为命名管道,可以在任意两个进程之间进行通信。

2.1 无名管道 

//函数原型
#include <unistd.h>

int pipe( int fd[2] );

匿名管道适用于一对一的、具有亲缘关系的进程间的通信

是一个半双工的通信方式,具有固定的读端和写端。

管道可以看做是一种特殊的文件,对管道的读写可以使用普通的read() ,write()函数,但管道不属于任何文件系统的,只存在于内存中。

2.1.1 如何操作无名管道

  1. 创建 :(pipe函数用来创建无名管道)
  2. 操作 :(read读;write写)  写是 fd[1],读是 fd[0]
  3. 关闭操作端口 :(close)

2.1.2 示例代码 

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

int main()
{
    //创建无名管道
    int fd[2];
    pipe(fd);
    
    if(fork() == 0)
    {
        close(fd[0]);   //读关闭
        char *buf = "hello world"; 
        write(fd[1], buf, strlen(buf)); //写操作
    }
    else
    {
        close(fd[1]);  //写关闭
        char showbuf[100];
        bzero(showbuf, 100);  //清空缓冲区

        read(fd[0], showbuf, 100); //读操作

        printf("txt is :%s\n", showbuf); //打印内容

        exit(0);
      
    }
}

代码运行结果

2.2 有名管道 

//函数原型
#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
//  pathname:具名管道的名称 
//  mode:文件权限模式,例如0666

具名管道通常又被称为FIFO,它是对无名管道的一种改进,其更接近普通文件,有文件名、可以open打开、支持read()/write()等读写操作

Linux在共享文件夹下,创建管道文件是创建不了的,运行结果为空,因此要将执行文件移到非共享文件夹下。因为共享文件夹和Windows是共享的,有些文件windows是没有的。

特性

它可以使互不相关的两个进程实现彼此通信

该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立管道之后,两个进程就可以把它当作普通文件进行读写,使用非常方便。

FIFO严格遵循先进先出原则,对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。有名管道不支持如Iseek()等文件的定位操作。

2.2.1 如何操作具名管道

  1. 创建有名管道文件 :(mkfifo即是命令也是函数;mknod也可以创建管道文件)
  2. 打开有名管道 :(open)
  3. 读/写 :(read/write)
  4. 关闭 :(close)

具名管道一旦没有任何读者和写者,系统判定管道处于空闲状态,会释放管道中的所有数据

1.写者

  1. 创建有名管道文件 mkfifo()
  2. 打开有名管道 open()
  3. 创建缓冲区,写内容 buf
  4. 写操作 write()
  5. 关闭有名管道 close()

2.读者

  1. 打开有名管道 open()
  2. 创建缓冲区,清空缓冲区 buf bzero()
  3. 读操作,打印 read()
  4. 关闭有名管道 close()

2.2.2 示例代码 

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

int main()
{
    int fd = open("./fifo", O_RDWR);  //打开有名管道

    char showbuf[100];   //创建缓冲区
    bzero(showbuf, 100);  //清空缓冲区

    read(fd, showbuf, 100);  //读

    printf("%s\n", showbuf); //打印

    close(fd);  //关闭

    return 0;

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

int main()
{
    mkfifo("./fifo", 0666);    //创建有名管道文件

    int fd = open("./fifo", O_RDWR);  //打开有名管道

    char *buf = "hello world";   //写
    write(fd, buf, strlen(buf));

    close(fd);   //关闭

    return 0;

}

注意:

在Linux在共享文件夹下,创建管道文件是创建不了的,运行结果为空,因此要将执行文件移到非共享文件夹下,这里我把执行文件放到家目录的test文件夹下了。

打开两个终端执行命令,这里可用Ctrl+shift+n快速打开相同路径下的终端

代码运行结果

3. 相关练习

编写两个程序,一个客户端、一个服务器端,服务器端创建并且监视管道,发现如果有数据就把它保存到指定位置,客户端将当前系统时间和自己的PID写入管道 

3.1 客户端

//cilent 客户端
#include <stdio.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <sys/types.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <time.h>
int main()
{
    int fd = open("./fifo", O_RDWR);  //打开有名管道

    char buf[1000];     //创建缓冲区
    time_t tim;

    while(1)
    {
        bzero(buf,1000);      //清空缓冲区
        time(&tim);         //时间
        sprintf(buf,"[%d]:  %s",getpid(),ctime(&tim)); //打印到buf指向的字符串中

        write(fd,buf,strlen(buf)); //写操作,在日志文件中写入数据
        
        sleep(2);

    }
    
    return 0;

}

3.2 服务器端 

//server 服务器端
#include <stdio.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <sys/types.h> 
#include <fcntl.h> 
#include <stdlib.h> 

int main()
{
    mkfifo("./fifo", 0666);    //创建有名管道文件
    int logfd = open("./log.txt",O_RDWR | O_CREAT,0777); //创建日志文件
    int fd = open("./fifo", O_RDWR);  //打开有名管道

    char buf[1000];     //创建缓冲区
    while(1)
    {
        bzero(buf,1000);      //清空缓冲区
        read(fd,buf,1000);     //读取缓冲区数据
        write(logfd,buf,strlen(buf)); //在日志文件中写入数据
    }
    
    return 0;

}

代码运行结果 


如果喜欢请不吝给予三连支持!

小海编程心语录-CSDN博客

 

标签:int,间通信,管道,fd,Linux,进程,include,buf
From: https://blog.csdn.net/qq_59715605/article/details/139182538

相关文章

  • Linux-Nginx安装及启动命令
    目录1、安装依赖2、nginx安装3、防火墙打开80端口4、nginx启动停止1、安装依赖yum-yinstallgcc-c++ yum-yinstallpcrepcre-devel yum-yinstallzlibzlib-devel yum-yinstallopensslopenssl—devel2、nginx安装mkdir/usr/local/src/nginxcd......
  • Windows下分卷压缩后到Linux进行解压的方法
    windows分卷压缩后linux解压缩 Linux服务器在内网,中途隔了一层堡垒机。文件太大,堡垒机对此有限制,需要在Windows上分包,然后上送到Linux上进行合并解压。我探索出来的办法有两个,以下依次介绍:1、WinRAR+7za命令WinRAR上需要选择压缩格式为zip,输入分卷大小: 然后将分卷都传......
  • Linux系统中如何查看磁盘情况
    Linux不像windows系统那样方便的图形界面,特别是作为服务器使用的时候,只有命令行可以使用。我有个云服务器平时用来做一些数据分享用的,最近想看看磁盘和其中文件的占用情况,于是搜索并学习了一些查看磁盘空间信息的命令,命令虽然简单,但对我自己来说还是有些新的东西值得记录。1.df......
  • orangepi zero2在linux5.4以上内核使用ili9341
    背景根据orangepizero2用户手册说明,linux5.13内核不能使用modprobefbtft_device驱动spilcd查看linux内核源码提交记录,发现在v5.4-rc3中删除了fbtft_device.c文件commit如下staging/fbtft:Removefbtft_deviceCommitc440eee("Staging:fbtft:Switchtothegpiode......
  • Linux系统postdrop服务进程持续增加导致无法登录
    临时解决方案:#servicepostfixstatus#servicesendmailstatus#servicepostfixstop[root@wign~]#ps-ef|grepsendmail|wc-l3038[root@wign~]#ps-ef|greppostdrop|wc-l3162停止postdrop服务,杀掉postdrop的进程#psaux|greppostdrop|grep-vgrep|cut-c9-15|xargs......
  • Linux安装卸载MySQL
    大家好,我是Java陈序员。今天,给大家分享下在Linux环境中如何安装卸载MySQL.关注微信公众号:【Java陈序员】,获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。MySQL安装准备一台Linux服务器下载Linux版MySQL安装包下载地址:https://downloads.m......
  • GDB对Linux信号的处理方式
    前言在软件开发过程中,调试工具是程序员不可或缺的助手。GDB(GNUDebugger)作为一个强大的调试器,广泛应用于Linux系统中的C/C++程序调试。然而,信号处理机制的复杂性常常给调试带来挑战。特别是在处理异步和同步信号时,不同的信号处理方式对程序执行流和调试工具的行为会产生显......
  • Bash反弹shell & 搭建网页服务器 & 文件描述符学习 & ssh连接vm虚拟机 & sftp进行文件
    环境:kali:┌──(kali㉿kali)-[~/Desktop]└─$cat/proc/versionLinuxversion6.0.0-kali5-amd64([email protected])(gcc-12(Debian12.2.0-9)12.2.0,GNUld(GNUBinutilsforDebian)1.建立一个简单的链接进行nc,可以进行两个端口通信!#首先使用nc监听......
  • C++Linux系统编程——文件和目录操作函数
    stat函数(重要)#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>​intstat(constchar*path,structstat*buf);intlstat(constchar*pathname,structstat*buf);功能: 获取文件状态信息 stat和lstat的区别:   当文件是一个符号......
  • [IMX6ULL驱动开发]-Linux对中断的处理(一)
    目录中断概念的引入ARM架构中断的流程异常向量表Linux系统对中断的处理ARM对程序和中断的处理Linux进程中断处理中断概念的引入如何理解中断,我们可以进行如下抽象。把CPU看做一个母亲,当它正在执行任务的时候,可以看为是一个母亲在看书。此时可能发生许多不同的情况,比......