zoukankan      html  css  js  c++  java
  • linux 进程间通信机制(IPC机制)- 管道

    一,定义:

    管道又可以分为无名管道命名管道,两者的用途是不一样的。

    无名管道PIPE:主要用于具有亲缘关系的进程之间的通信,无名管道的通信是单向的,只能由一段到另外一段;无名管道是临时性的,完成通信后将自动消失。一般采用先创建无名管道,再创建子进程,使子进程继承父进程的管道文件描述符,从而实现父子进程间的通信;在非亲缘关系管道之间,如果想利用无名管道进行通信,则需要借助另外的文件描述符传递机制。

    有名管道FIFO:有名管道是一个实际存在的特殊文件,利用有名管道可以实现同主机任意进程之间的数据交互。

    二,应用:

    1,Shell中的无名管道

    在Shell命令行中使用无名管道是到过管道符“ | ” 实现的。如ps -ax|grep mysql, 将ps -ax的内容通过管道传给grep mysql

    2.创建无名管道

    (1.)函数:

    pipe(建立管道):
    1) 头文件

      #include<unistd.h>
    2) 原型:

       int pipe(int filedes[2]);
    3) 函数说明:

      pipe()会建立管道,并将文件描述词由参数filedes数组返回。

      filedes[0]为管道里的读取端

          filedes[1]则为管道的写入端。
    4) 返回值: 

       若成功则返回零,否则返回-1,错误原因存于errno中。

    5)错误代码: 
             EMFILE 进程已用完文件描述词最大量
             ENFILE 系统已无文件描述词可用。
             EFAULT 参数 filedes 数组地址不合法。

    (2)使用:

      #include<stdio.h>
      #include<unistd.h>
      #include<string.h>
    
      int main()
      {
            int p[2];
            int pid;
            char *str = "HelloWorld";
            char buf[128];
            memset(buf,'',128);
    
            if(pipe(p) == -1)
            {
                    printf("function pipe() calls failed.");
                    return -1;
            }
    
            if((pid=fork()) == -1)  //创建一个子进程
            {
                    printf("function fork() calls failed.
    ");
                    return -1;
            }
            else if(pid == 0)  //在子进程中
            {
                    printf("In sub : pid=%d
    ",getpid());
                    write(p[1],str,strlen(str)); //向无名管道中写入str
            }else {  //在父进程中
                    printf("In father : pid=%d
    ",getpid());
                    read(p[0],buf,strlen(str));  //读取无名管道
                    printf("In father : buf=%s
    ",buf);
            }
      }
    结果:

    注意:read和write为阻塞模式

    3.创建有名管道

    (1)函数:mkfifo(建立具名管道)

    相关函数 pipe,popen,open,umask
    1)表头文件

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

      int mkfifo(const char * pathname,mode_t mode);
    3)函数说明

    mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此umask值也会影响到FIFO文件的权限。

    4)返回值 若成功则返回0,否则返回-1,错误原因存于errno中。
    5)错误代码

      EACCESS 参数pathname所指定的目录路径无可执行的权限
      EEXIST 参数pathname所指定的文件已存在。
      ENAMETOOLONG 参数pathname的路径名称太长。
      ENOENT 参数pathname包含的目录不存在
      ENOSPC 文件系统的剩余空间不足
      ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
      EROFS 参数pathname指定的文件存在于只读文件系统内。

    (2)使用:

    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    
    main()
    {
        char buffer[80];
        int fd;
        unlink(FIFO);
        mkfifo(FIFO,0666);
        if(fork()>0)
        {
            char s[ ] = “hello!
    ”;
            fd = open (FIFO,O_WRONLY);
            write(fd,s,sizeof(s));
            close(fd);
        }
        else
        {
            fd= open(FIFO,O_RDONLY);
            read(fd,buffer,80);
            printf(“%s”,buffer);
            close(fd);
        }
    }    
    

    参考:linux c 中文函数手册

    
    
  • 相关阅读:
    Github for Windows使用介绍
    Activity生命周期
    Java日期LocalDate使用
    一、安装Windows 2012域控(For SQLServer 2014 AlwaysOn)
    .NET(C#):分析IL中的if-else,while和for语句并用Emit实现
    sqlserver中几种典型的等待
    ServiceStack.Redis常用操作
    ServiceStack.Redis 之 IRedisTypedClient<第四篇>
    ServiceStack.Redis之IRedisClient<第三篇>
    Redis常用命令速查 <第二篇>
  • 原文地址:https://www.cnblogs.com/yaosj/p/6740233.html
Copyright © 2011-2022 走看看