Chinaunix首页 | 论坛 | 博客
  • 博客访问: 162823
  • 博文数量: 48
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 262
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-30 15:16
个人简介

本人无才,非专业出生,笔记仅记录学习,其中很多基于网络或他人原创,如有侵权和冒犯,或者错误,请谅解指正……谢谢!

文章存档

2016年(1)

2015年(3)

2013年(44)

我的朋友

分类: LINUX

2015-05-21 14:34:55

    最进在做IPC——管道实验时,发现管道有一些特别的地方,特总结下。若有不正确的地方,企望指正,谢谢!


实验步骤:

    使用mkfifo创建管道文件,read/write读写管道操作


实验总结:

    1.管道文件实际上是个虚拟的文件,存在与虚拟内存中,不存在物理内存上(文件的大小为0
 
    2.数据有序(先进先出),使用read读取管道文件时,若文件中没有数据read阻塞,而且read后数据是被删除
 
    3.打开的描述符号既可以读操作也可以写操作(two-way双工)
        //建议使用shutdownman 2 shutdown)可以将一个描述符的读属性,或者写属性关闭,确保两个进程间使用管道通讯,数据方向的一致性。
 
    4.管道文件关闭后,数据不持久.
 
    5.管道的数据存储在内核缓冲中,如果没有指向该文件的描述符,系统会自动将该缓冲的链接删除(管道文件被删除了)
 
    6.这个管道缓冲打开后,管道文件可以删除,内核没有和管道文件建立映射(管道文件只是决定了内核创建文件描述符指向的内核缓冲的数据结构——先进先出而已)
 
        7.有名的管道的名字仅仅是内核识别是否返回同一个fd的标示.所以当管道名失去表示作用的时候,实际可以不要名字——匿名管道.
在父子进程之间:打开文件描述后创建进程.父子进程都有描述符号(子进程复制父进程的文件描述符)所以管道文件在父子进程中没有价值.
 
        8.个不同的进程(非父子进程)只能使用命名管道,而父子进程中既可以使用命名管道,也可以使用匿名管道.匿名管道只能使用在父子进程.



以上这几个都比较容易理解,第6点比较有意思,来看一下:
范例代码:


//FifoDemoA.c
#include
#include
#include
#include
#include
#include
#include

int fd;
int i;
/*
关闭管道信号处理函数的实现*/
void  endfifo(int s){
    close(fd);    //
关闭管道    
    unlink("my.pipe");//
删除管道
    exit(-1);


int main(void){
    int fd_file;
    signal(SIGINT,endfifo);    //
使用CTRL-C信号关闭管道文件
    
    fd_file = open("my.txt",O_CREAT,0666);
    if(fd_file <0){
        printf("open file error!\n");
    }else{
        printf("open file sucessful! fd_file= %d\n",fd_file);
    }

    mkfifo("my.pipe",0666);//
建立管道
    //
一般只要磁盘空间足够,很少出现创建文件错误,故没有做错误处理
    
    fd=open("my.pipe",O_RDWR);//
打开管道
    //shutdown(fd,SHUT_RD);
管道方向,关闭读取文件描述符
    i=0;//
初始化i变量的值
    while(1){//
每隔1秒写数据
        sleep(1);
        write(fd,&i,4);
        i++;
        printf("
写入my.pipe的数据是:%d\n",i);
    }
    return 0;
}

 


另一个程序代码如下:


//FifoDemoA.c
#include
#include
#include
#include
#include
#include
int fd;
void endfifo(int s){
    close(fd);//
关闭管道
    exit(-1);
}
int main(void){
    int i;    
    signal(SIGINT,endfifo);
    fd=open("my.pipe",O_RDWR);//
打开管道
    //shutdown(fd,SHUT_WR);//
管道方向,关闭写入文件描述符
    while(1){
        read(fd,&i,4);
        printf("
my.pipe读取到数据是:%d\n",i);
    }
    return 0;
}




实验效果如下:(左上为FifoDemoB程序,左下为FifoDemoA程序,右边为另开的终端)

可以很容易的得到以下证明:
1、首先编译运行FifoDemoA.c,可以发现打开my.txt的文件描述符为3
2、之后编译运行FifoDemoA.c
3、进入/proc/{PID}/fd中查看两者的fd指向,发现尽管其fd数值不同,但指向的都是同一文件。
4、使用rm -f my.pipe删除管道文件,发现程序依旧运行正确,进入proc目录查看fd信息,发现都已显示deleted状态。
5、使用CTRL+C退出FifoDemoB程序,之后再重新运行,发现其读取的就是错误的值。如下:

 

阅读(2133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~