Linux管道通信笔记

目录

概述:

pipe API:

补充:

FIFO:

共享存储映射:

mmap练习代码:


概述:

管道 进程通信
管道 使用最简单
信号 开销最小
共享映射区 无血缘关系
本地套接字 最稳定 难度最强

pipe 函数  未名管道
管道一般读写行为

fifo 有名管道
用于非血缘关系进程通信

共享内存
mmap 函数的参数使用注意事项
用于非血缘关系进程通信

linux 文件类型
- 文件
d 目录
l 符号链接
s 套接字
b 块设备
c 字符设备
p 管道

前三种占用磁盘存储

后四种 为 伪文件  实质是一个内核缓冲区
由两个文件描述符引用,一个表示读端,一个表示写端
规定数据从管道的写端流入管道,从读端流出。
管道原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现

磁盘扇区 一个文件最小要占用一个扇区512b  pipe 占用了8个 所以就是8X512b =4K 4个字节 

管道数据不能重复读取,读队列就相当于数据出队,不能重复读,且不能入队的一边读,比如不能自己往管道写入数据,

然后再自己读出来,这样是不可以的。

管道半双工通信,数据只能在一个方向上通信。既可以只往左流动,也可以只往右流,但是不能同时突然往左突然往右,这是全双工。

只能在有公共祖先的进程间通信。

 

pipe API:

 

SYNOPSIS
       #include <unistd.h>

       int pipe(int pipefd[2]);

       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <fcntl.h>              /* Obtain O_* constant definitions */
       #include <unistd.h>

       int pipe2(int pipefd[2], int flags);
 

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

DESCRIPTION

       pipefd[0] refers to the read end of the pipe.
       pipefd[1] refers to the write end of the pipe.  Data written to the  write  end  of
       the  pipe is buffered by the kernel until it is read from the read end of the pipe.
pipefd数组  pipefd[0] 代表读端 pipefd[1]代表写端。

补充:

读管道

①管道中有数据 read返回读到的字节数。

② 管道中无数据 ,写端全部关闭,read返回0;仍然有写端打开:阻塞等待。

写管道

①读端全部关闭,进程异常终止(SIGPIPE信号)

②有读端打开, 管道未满:写数据,返回写入字节数; 管道已满,:阻塞(少见)。

 

父子进程通信   ls | wc -l

兄弟进程间通信

获取管道缓冲区大小

命令: ulimit -a

函数:fpathconf 参数2: __PC_PIPE_BUF

优点 实现简单

缺点:单向  只能有血缘的进程。

FIFO:

命名管道(Linux基础文件类型)

创建

命令: mkfifo

函数:mkfifo     参数  name   , mode:八进制 。  返回值 成功 0 ,失败 -1,设置error。

没有血缘关系进程间通信: 使用同一FIFO,可多读端,多写端。 

也必须在同一路径下才行。

共享存储映射:

mmap函数: 参数:

             返回值:

借助共享内存访问磁盘文件。

            借助指针访问磁盘文件。

父子进程、血缘关系进程、通信 。

匿名映射区 如何创建 使用。

mmap API

SYNOPSIS
       #include <sys/mman.h>

       void *mmap2(void *addr, size_t length, int prot,  int flags, int fd, off_t pgoffset);

DESCRIPTION
       This  is probably not the system call you are interested; instead, see mmap(2), which describes
       the glibc wrapper function that invokes this system call.

       The mmap2() system call provides the same interface as mmap(2), except that the final  argument
       specifies  the  offset  into  the  file  in  4096-byte  units  (instead of bytes, as is done by
       mmap(2)).  This enables applications that use a 32-bit off_t to map large  files  (up  to  2^44
       bytes).

RETURN VALUE
       On success, mmap2() returns a pointer to the mapped area.  On error -1 is returned and errno is
       set appropriately.
 

参数:

addr:    建立映射区的首地址 linux内核自动指定,使用时直接传NULL

length: 欲创建映射区大小

prot:    映射区权限,PROT_READ  PROT_WRITE    PROT_READ|PROT_WRITE

flags:     标志位参数(常用语设定更新物理区域、设置共享内存、创建匿名映射区)

             MAP_SHARED:会将映射区所做的操作反映到物理设备(磁盘)上。

             MAP_PRIVATE:映射区所做的修改不会反映到物理设备上。

fd:         用来建立映射区的文件描述符

offset:映射文件的偏移(4K的整数倍)4096的整数倍

文件打开函数

lseek函数  

ftruncate函数

其他注意事项:

  1. 映射区的权限小于等于打开文件的权限,而且定义映射区的时候,会隐含一次读文件的操作
  2. 映射区一单创建成功,文件描述符就没用了,及时早关闭也不会对mmap产生影响了。
  3. mem++ munmap不会成功
  4. 映射区的释放与文件关闭无关,只要映射区成功建立,文件可以立即关闭。
  5. 特别注意,当映射文件大小为0时,不能创建映射区。所以映射的文件必须要要有实际大小。mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。
  6. munmap 传入的地址一定是mmap的返回地址。
  7. 如果文件偏移量必须为4k整数倍
  8. mmap创建映射区出错的概率非常高,一定要检查返回值,确保创建成功再后续操作。
  9. 杜绝映射区首地址++ -- 操作。

mmap练习代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/mman.h>
#include<string.h>
#include<fcntl.h>

int main()
{
    int len, ret;
    char *p = NULL;
    int fd = open("mytest.txt",O_CREAT|O_RDWR,0644);
    if(fd < 0){
        perror("open error:");
        exit(1);
    }
    len = ftruncate(fd,4); 
    if (len == -1){
        perror("ftruncate error:");
        exit(1);
    }

    p = (char*)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//创建映射区
    if (p == MAP_FAILED){
        perror("mmap error:");
        exit(1);
    }
    strcpy(p,"abc"); //写数据
    
    ret = munmap(p,4);//释放映射区
    if (ret == -1){
        perror("munmap error:");
        exit(1);
    }
    close(fd);
    

    return 0;
}   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值