Linux初学第八天<进程间通信 一、通道和命名管道>

一、进程间通信

       进程间通信 IPC(InetProcess Communication):是指在不同进程之间传播或交换信息。
        IPC 的方式通常有管道(包括无名管道和命名管道)、消息队列信号量共享存储SocketStreams等。其中 SocketStreams 支持在不同主机上的两个进程 IPC

二、管道

       我们说的管道通常指的是无名管道,是UNIX系统PIC最古老的形式。
有以下几个特点:
       1. 它是半双工(即数据只能往一个方向流动,读和写不能同时进行),具有固定的读端和写端;
       2. 它只能用于具有亲缘关系的进程之间的通信(即父、子进程之间和兄弟进程之间);
       3. 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数,但是它不是普通的文件,并不属于其它的任何文件系统,并且只存在于内存中。

1.管道的建立

函数原型: int pipe(int fd[2]); //在 <unisyd.h> 头文件中
返回值: 若成功,返回 0,失败返回 -1
       当一个管道建立时,它会创建两个文件描述符:fd[0]fd[1],如下图:
在这里插入图片描述
       要关闭管道,只需要将这两个文件描述符关闭即可。写个父进程读管道数据,子进程来写数据的程序掌握一下 pipe函数:
实验代码:

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

int main()
{
        int fd[2];
        char *read_buf;
        pid_t pid;
        int status=10;
        printf("This is IPC test!\n");
        if(pipe(fd)==-1){
                printf("pipe creat fail!\n");
        }
        pid=fork();
        if(pid>0){
                waitpid(pid,&status,WNOHANG);//非挂起方式等待子进程
                printf("This is fathet curret!ID:%d\n",getpid());
                close(fd[1]);//关闭写
                read(fd[0],read_buf,20);//开始读
                printf("Father read:%s\n",read_buf);
        }
        if(pid==0){
                printf("This is child current!ID:%d\n",getpid());
                close(fd[0]);//关闭
                write(fd[1],"Hello Wrold!",strlen("Hello Wrold!"));
                //printf("Child read: %s\n",read_buf);
                exit(status);
        }
        return 0;
}

运行结果:
在这里插入图片描述
后面的乱码是因为我们读了20个字节所导致,因为我们真实写的时候,并没有20个字节那么多。

三、命名管道(FIFO)

       命名管道也叫FIFO,是一种文件类型。
特点:
       1. FIFO可以在无关的进程之间交换数据,与无名管道不同;
       2. FIFO有路径与之相关联,它以一种特殊文件形式存在于文件系统中。
函数原型: int mkfifo(const char *pathname,mode_t mode);//存在于 <sys/stat.h> 当中;
       其中的 mode 参数与open 的相同,一旦创建了一个 FIFO,就可以哦那个一般的文件 I/O 函数来操作它。
       当open 一个 FIFO 时,是否设置非阻塞标志( O_NONBLOCK)的区别:
        1. 若没有指定 O_NONBLOCK(默认),只读 open要阻塞到某个其他进程为而打开次 FIFO,类似的,只写 open 要阻塞到某个其他进程为 而打开它;
        2. 若指定了 O_NONBLOCK,则只读 open 立即返回 -1 ,如果没有进程已经为 而打开 FIFO,其 errnoENXIO

1.创建命名管道 FIFO

创建 FIFO 代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main()
{
        //int mkfifo(const char *pathname, mode_t mode);
        int mkfifo_s=mkfifo("./FIFO_1",0600);//创建一个FIFO 并赋予其可读可写权限
        if(mkfifo_s==0){
                printf("FIFO cerat succese!\n");
        }
        if(mkfifo_s==-1){

                printf("FIFO cerat fail!\n");
                perror("why");
        }
        return 0;
}

运行结果:
在这里插入图片描述
可以看到,我们在没有运行 ./crearfifo之前,当前目录并没有FIFO_1 文件,执行了 ./crearfifo 之后,便创建了一个FIFO_1文件。其实我们可以优化一下这个程序:
程序优化:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
int main()
{
        //int mkfifo(const char *pathname, mode_t mode);

        if((mkfifo("./FIFO_1",0600)==-1)&& errno == EEXIST){
                printf("Creat FIFO fail!");
                perror("why");
        }
        return  0;
}

这个程序就是把错误信息打印出来,假如文件已经存在,就打印文件已存在信息(file exists);
运行结果:
在这里插入图片描述
因为我们刚刚就创建了 FIIOF_1,所以打印信息:file exists ;

3.利用FIFO传递数据

       学会了创建FIFO,下面就开始使用它来给两个不相关的进程传递数据。因为命名管道也是管道的一种,依旧没办法读、写 同时进行,而且open FIFO 时,默认是阻塞型,即程序会卡在 read 处,会读不出数据,直到另一个进程 入之后且关闭FIFO之后,才能读出来,做个实现负责读数据的程序命名为:FIFO_FWCR3.c ;负责写入的程序命名为:FIFO_FWCR5.c
实验代码:
FIFO_FWCR3.c 不断读取FIFO 中的内容,如果FIFO_FWCR5.c 程序不运行的话,会卡住。

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

int main()
{
        //int mkfifo(const char *pathname, mode_t mode);
        char read_buf[30]={0};
        if((mkfifo("./FIFO_1",0600)==-1)&& errno == EEXIST){
                printf("Creat FIFO fail!");
                perror("why");
        }
        int fd=open("./FIFO_1",O_RDONLY);
        printf("open success\n");
        while(1){
                sleep(1);
                read(fd,read_buf,30);
                printf("read :%s\n",read_buf);
        }
        close(fd);
        return  0;
}

FIFO_FWCR5.c 负责给FIFO 写入“FIFO data!”.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main()
{
        //int mkfifo(const char *pathname, mode_t mode);
        char *str="FIFO data!";
        int cnt=5;
        int fd=open("./FIFO_1",O_WRONLY);
        printf("open success\n");

        while(cnt!=0){
                sleep(1);

                write(fd,str,strlen(str));
                cnt--;
        }
        close(fd);
        return  0;
}

FIFO_FWCR3.c 在FIFO_FWCR5.c 没运行之前的结果:
在这里插入图片描述
一直在等待写入,而当 FIFO_FWCR5.c 执行之后,我们再看看 FIFO_FWCR3.c 的结果:
在这里插入图片描述
FIFO_FWCR3.c 会不断的读取被FIFO_FWCR5.c 写到 FIFO 中的数据。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值