Linux管道、命名管道讲解

管道、命名管道

内容:

一、进程间的通信概述

二、管道

三、命名管道

 

一、进程间通信概述

1. 进程间通信(IPC:InterProcesses Communication)

    进程是一个独立的资源分配单元,不同进程之间的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程的资源。

    进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信。

2. 进程间通信功能:

数据传输:一个进程需要将它的数据发送给另一个进程。

资源共享:多个进程之间共享同样的资源。

通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件。

进程控制:有些进程希望完全控制另一个进程的执行,此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变

二、管道

1.管道(pipe)又称无名管道。

2.无名管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符。

3.管道是最古老的UNIXIPC方式,其特点是:

    1)半双工,数据在同一时刻只能在一个方向上流动。

    2)管道不是普通的文件,不属于某个文件系统,其只存在于内存中。

    3)管道没有名字,只能在具有公共祖先的进程之间使用。

    4)管道的缓冲区是有限的。管道是一个固定大小的缓冲区。在Linux中,该缓冲区的大小为4Kbyte。

4. 管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等。

5. 数据只能从管道的一端写入,从另一端读出。

6. 从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据。

7.函数

        #include <unistd.h>

        int pipe(int filedes[2]);

   功能:经由参数filedes返回两个文件描述符

   参数:

        filedes为int型数组的首地址,其存放了管道的文件描述符fd[0]、fd[1]。

        filedes[0]为读而打开,filedes[1]为写而打开

       管道,filedes[0]的输出是filedes[1]的输入。

  返回值:

        成功:返回 0

        失败:返回-1


例子:

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

int main()
{
    int parentFD[2],childFD[2];
    int parentPID,childPID;
    char msg[BUFSIZ];

    printf("程序开始\n");
    if( pipe(fd) < 0 ){
        perror("创建管道失败:");
    }
    printf("创建管道成功\n");

    pid = fork();
    if( pid < 0){
        perror("创建进程失败");
        exit(1);
    }else if(pid == 0){
        printf("子进程\n");
        close(fd[0]);//关闭读
        printf("请输入要写入的字符:");
        scanf("%s",msg);
        msg[0]='1';
        write(fd[1],msg,strlen(msg));//开始写
	    _exit(0);//结束进程
    }else{
        printf("父进程\n");
	    wait(NULL);//等待子进程执行完
        close(fd[1]);//关闭写
        read(fd[0],msg,BUFSIZ);
        printf("读取数据:%s\n",msg);
    }
    
    printf("程序结束\n");
    
    return 0;
}

8. 文件描述符概述

    文件描述符是非负整数,是文件的标识。

    内核利用文件描述符(file descriptor)来访问文件。

    利用open打开一个文件,内核会返回一个文件描述符。每个进程都有一张文 件描述符的表,进程刚被创建时,其计录了默认打开的标准输入、标准输出、标    准错误输出三个设备文件的文件描述符0、1、2。在进程中打开其他文件时, 系统会返回文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中

9. 复制文件的描述符

    dup和dup2是两个非常有用的系统调用,都是用来复制一个文件的描述符。

    int dup(intoldfd);

    int dup2(intoldfd, int newfd);

    dup和dup2经常用来重定向进程的stdin、stdout和stderr。

    1)dup函数

    #include<unistd.h>

    int dup(intoldfd);

    功能:

        复制oldfd文件描述符,并分配一个新的文件描述符,新的文件描述符是调用进程文件描述符表中最小可用的文件描述符。

    参数:

        oldfd:要复制的文件描述符oldfd。

    返回值:

      成功:新文件描述符。

      失败:返回-1,错误代码存于errno中。

    注意:

        新的文件描述符和oldfd指向的是同一个文件,共享oldfd所有的锁定、读写位置和各项权限或标志,但文件描述符之间并不共享close-on-exec标志。

    2dup2函数

    #include<unistd.h>

    int dup2(intoldfd, int newfd)

    功能:

        复制一份打开的文件描述符oldfd,并分配新的文件描述符newfd,newfd也标识oldfd所标识的文件。

    参数:

        要复制的文件描述符oldfd

        分配的新的文件描述符newfd

    返回值:

        成功:返回newfd

        失败:返回-1,错误代码存于errno中

    注:

        newfd是小于文件描述符最大允许值的非负整数,如果newfd是一个已     经打开的文件描述符,则首先关闭该文件,然后再复制。

三、命名管道(FIFO)

1.  命名管道(FIFO)和管道(pipe)基本相同,其特点是:

1)FIFO在文件系统中作为一个特殊的文件而存在。

2)虽然FIFO文件存在于文件系统中,但FIFO中的内容却存放在内存中,在Linux中,该缓冲区的大小为4Kbyte。

3)FIFO有名字,不同的进程可以通过该命名管道进行通信

4)FIFO所传送的数据是无格式的。

5)从FIFO读数据是一次性操作,数据一旦被读,它就从FIFO中被抛弃,释放空间以便写更多的数据。

6)当共享FIFO的进程执行完所有的I/O操作以后,FIFO将继续保存在文件系统中以便以后使用。

2.FIFO文件的创建

 #include <sys/types.h>

 #include <sys/stat.h>

 int mkfifo( const char *pathname, mode_tmode);

参数:

  pathname:FIFO的路径名+文件名。

  mode:mode_t类型的权限描述符。

返回值:

  成功:返回0

  失败:如果文件已经存在,则会出错且返回-1。

3.FIFO文件的读写

1)使用pipe的进程通过继承获得了pipe的文件描述符,所以pipe仅需要创建而不需要打开。

2)但是FIFO则需要打开,因为使用它们的进程可以没有任何关系。

3)一般文件的I/O函数都可以作用于FIFO,如open、close、read、write等。

    4)当打开FIFO时,非阻塞标志(O_NONBLOCK)产生下列影响:

        a.指定O_NONBLOCK:

            只读方式打开:如果没有进程已经为写而打开一个FIFO, 只读open成功,立即返回。

            只写方式打开:如果没有进程已经为读而打开一个FIFO,那么只写open将出错返回-1。

       b.不指定非阻塞标志O_NONBLOCK(即不写|O_NONBLOCK):

          只读open要阻塞到某个其他进程为写而打开此FIFO。

          只写open要阻塞到某个其他进程为读而打开此FIFO。

        注:

            1.不指定O_NONBLOCK时,除了只读、只写open会阻塞,调用read函数从 FIFO里读数据时read也会阻塞。

            2.通信过程中若写进程先退出了,则调用read函数从FIFO里读数据时不 阻塞;数 从FIFO里读数据时阻塞。

         若写进程又重新运行,则调用read函数从FIFO里读数据时阻塞。

            3.通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会退出

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amarao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值