Linux的IPC和管道

进程间通信(IPC机制)(Inter-Process Communication)

进程间通信的方法:
(1)管道 (2)信号量 (3)共享内存 (4)消息队列 (5)套接字

1.有名管道


管道的分类:有名管道和无名管道
有名管道也成为命名管道.
区别:有名管道在任意两个进程之间通信,无名管道在父子进程之间通信.
1.创建有名管道使用命令:mkfifo
2.打开管道:open();
关闭管道:close();
读数据:read();
写入数据:write();
2.有名管道来演示进程间通信:
思考:如果进程a要从键盘获取数据传递给另一个进程b,用已具备的知识思考如何完成?
使用文件即可.
问题:1很慢.2.读数据时不知道a什么时候会写入.
管道创建之后,它会在内存上分配一块空间.所以,管道的大小永远为0;
管道一个是读打开,一个是写打开.
代码如下:

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>

int main()
{
    int fd=open("fifo",O_WRONLY);
    assert(fd!=-1);

    printf("fd=%d\n",fd);
    write(fd,"hello",5); 

    close(fd);
}


//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>

int main()
{
    int fd=open("./fifo",O_RDONLY);
    assert(fd!=-1);

    printf("fd=%d\n",fd);   
    char buff[128]={0};
    read(fd,buff,127);
    printf("read:%s\n",buff);
 
    close(fd);

    exit(0);
}

思考1:管道的特点
(1)管道必须读,写进程同时open,否则会阻塞;
(2)如果管道没有数据,那么read会阻塞;
(3)管道的写端关闭,读read返回值为0;
(4)管道打开的时候只有只读和只写两种方式,读写方式打开是未定义的.

思考:2.a循环写入(从键盘写入),b循环读取?

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>

int main()
{
    int fd=open("fifo",O_WRONLY);
    assert(fd!=-1);

    printf("fd=%d\n",fd);
    while(1)
    {   
        printf("input:\n");
        char buff[128]={0};
        fgets(buff,128,stdin);
        if(strncmp(buff,"end",3)==0)
        {
            break;
        }
        write(fd,buff,strlen(buff));
    }   

    close(fd);
}


//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>

int main()
{
    int fd=open("./fifo",O_RDONLY);
    assert(fd!=-1);

    printf("fd=%d\n",fd);
    while(1)
    {   
      char buff[128]={0};
       if(read(fd,buff,127)==0)
       {
           break;
       }
       printf("read:%s\n",buff);
    }   
    close(fd);

    exit(0);
}

2.无名管道


无名管道:父子进程间通信
创建无名管道的命令:pipe
int pipe(int pipefd[2]);
调用pipe系统调用之后,返回两个文件描述符,fd[0]为读端,fd[1]为写端;

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>

int main()
{
    int fd[2];
    assert(pipe(fd)!=-1);
    //fd[0]  fd[1] 

    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
      close(fd[1]);
      char buff[128]={0};
      read(fd[0],buff,127);
      printf("child read:%s\n",buff);
      close(fd[0]);
    }
    else
    {
        close(fd[0]);
        write(fd[1],"hello",5);
        close(fd[1]);
    }
    exit(0);
}

管道的特点
(1)管道必须读,写进程同时open,否则会阻塞;
(2)如果管道没有数据,那么read会阻塞;
(3)管道的写端关闭,读read返回值为0;
(4)管道打开的时候只有只读和只写两种方式,读写方式打开是未定义的.
(5)无论有名还是无名,写入管道的数据都在内存中(管道的大小永远为0,面试的重点)
(6)管道是一种半双工通信方式(通信方式有单工,半双工,全双工)
(7)有名管道和无名管道的区别:有名管道可以在任意进程间使用,无名管道主要在父子进程间通信.
(8)管道的读端关闭,写会产生异常(发送信号SIGPIPE,注意,参考课件信号那里一句话:
读端关闭的描述符,写端写入时产生,该信号会终止程序(向无读进程的管道写数据))
//验证如下:

#include <signal.h>

void fun(int sig)

{

printf("sig=%d\n",sig);

}

int main()

{

signal(SIGPIPE,fun);

...

}

3.管道的实现

image-20220723110333174.png

循环队列
如果管道是空的,读操作会阻塞;如果管道是满的,写操作会阻塞;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值