【Linux-Day9-进程间通信】

进程间通信

前提引入: 我们之前接触过管道 | 将前一个命令的输出结果作为后一个命令的输入

如:ps | grep “sleep”

其实就是将 ps 的结果写入到一个区域,在从这个区域读出目标数据

【Linux-Day9-进程间通信】_第1张图片

有名管道

mkfifo

创建管道文件 : mkfifo fifo ->创建一个名为fifo的管道文件

【Linux-Day9-进程间通信】_第2张图片

如图,管道文件的大小为0,是因为他是在内存中写入,读取,并不会占用磁盘空间,因此速度会快很多。

管道文件只有:只读,只写两种权限。

1.执行写入文件a.c

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd = open("fifo",O_WRONLY);
    if(fd == -1)
    {
        printf("none file\n");
        exit(1);
    }
    char buff[128];
    while(1)
    {
        printf("intput:");
        fflush(stdout);
        fgets(buff,128,stdin);
        buff[strlen(buff)-1]=0;
        if(strcmp(buff,"end") == 0)
        {
            break;
        }
        write(fd,buff,strlen(buff));
    }
    close(fd);
    exit(0);
}

2.执行读取文件 b.c

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd = open("fifo",O_RDONLY);
    if(fd == -1)
    {
        printf("none file\n");
        exit(1);
    }
    printf("fd = %d\n",fd);
    while(1)
    {
       char buff[128]={0};
       int n = read(fd,buff,127);
       if(n != 0)
       {
        printf("%s\n",buff);
       }
       else
       {
           break;
       }
    }
    close(fd);
    exit(0);
}

管道文件必须同时被只读,只写打开,否则无法成功打开

1.只写无法打开

【Linux-Day9-进程间通信】_第3张图片

2.只读无法打开

【Linux-Day9-进程间通信】_第4张图片

3.正确方式:只读,只写同时打开

【Linux-Day9-进程间通信】_第5张图片

写端关闭,读端read返回0,退出循环

【Linux-Day9-进程间通信】_第6张图片

读端关闭,写端write时会收到异常信号(SIGPIPE),进而结束该进程

【Linux-Day9-进程间通信】_第7张图片

验证是否产生该信号

写端a.c 测试代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

void fun_sig(int sig)
{
    printf("%d,%d\n",sig,13 == sig);
}
int main()
{
    signal(SIGPIPE,fun_sig);
    int fd = open("fifo",O_WRONLY);
    if(fd == -1)
    {
        printf("none file\n");
        exit(1);
    }
    char buff[128];
    while(1)
    {
        printf("intput:");
        fflush(stdout);
        fgets(buff,128,stdin);
        buff[strlen(buff)-1]=0;
        if(strcmp(buff,"end") == 0)
        {
            break;
        }
        write(fd,buff,strlen(buff));
    }
    close(fd);
    exit(0);
}

如图:

【Linux-Day9-进程间通信】_第8张图片

有名管道能在任意两个进程间使用

无名管道

利用函数 int pipe(int fds[2]);

int pipe(int fds[2]);

pipe()成功返回 0,失败返回-1

fds[0]是管道读端的描述符

fds[1]是管道写端的描述符

测试代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int fd[2];
    if(pipe(fd) == -1)  exit(1);
   int pid = fork();
    if(pid == 0)
    {
        close(fd[0]);
        printf("child input\n");
        write(fd[1],"hello",6);
    }
    else
    {
        char buff[128]={0};
        close(fd[1]);
        printf("parent read:");
        read(fd[0],buff,127);
        printf("%s\n",buff);
    }
    exit(0);
}


如图:

无名管道主要应用于父子进程间的通信。

管道的特点

◼ 无论有名还是无名,写入管道的数据都在内存中

◼ 管道是一种半双工通信方式(通信方式有单工、半双工、全双工)

◼ 有名和无名管道的区别:有名可以在任意进程间使用,而无名主要在父子进程间

【Linux-Day9-进程间通信】_第9张图片

你可能感兴趣的:(Linux学习,linux)