Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1643912
  • 博文数量: 245
  • 博客积分: 10378
  • 博客等级: 上将
  • 技术积分: 2571
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-27 08:19
文章分类

全部博文(245)

文章存档

2013年(4)

2012年(8)

2011年(13)

2010年(68)

2009年(152)

分类: LINUX

2009-04-02 21:03:13

 我们知道,进程间的通信既为ipc常见的进程间的方法有: 管道、命名管道、信号、内存映射、消息队列、信号量、共享内存、套接字,现在来简单的写一些自己在实际的编程过程中遇到的问题,管道相关函数:
 

#include <unistd.h>
int fd[2] //  存储文件描述符
int pipe(fd); //  成功返回0  失败返回 -1

管道在多进程中通信以及数据共享时,非常的方便,但自己一直对管道的理解有一些偏差,首先,管道是一个特殊的文件,定义int fd[2],就是为了存储管道两端的文件描述符,可以把管道历程成一段临时区域,通过两端的文件相连,由于管道对应一段内存区域,那么它不肯能同时进行读写的操作,所以认为管道是单工的,一定要明确的是管道是一段特殊的内存区域,而这段内存区域是由内核来控制的,如果要详细的理解管道的实现细节,就需要去阅读内核代码了,这里只是写一些感性认识,多是一些实践的来的经验了。

   在编程实践中发现,多进程中,管道的使用不一定要关闭一些读写端口,比如开启管道后,子进程送数据给父进程,而在父进程中就不是必须把写即fd[2]关闭,同样在子进程就不是必须把读fd[0]关闭,管道就比如一个杯子插入多个吸管,而这些吸管在同一时刻只有一个可以工作,只要保证在读或者写不要重复就可以了。
   管道另外一个特点是在子进程消亡后,管道中的信息不会消失,但前提是这个管道是由父进程创建并初始化的,这样的话,即便是在子进程中写入信息到管道,而父进程又创建了自己新的子进程,在原子进程消亡后,新的子进程还可以读取到原来子进程发送在管道中的数据,有一些细节的东西是需要注意的,在读管道的信息时,如果管道中没有数据,那么这时就会发生阻塞现象,直到管道中有新的数据写入,特别需要注意的是管道的中断,如果管道的读取端即fd[0]关闭,而这时还继续想管道中写入数据,那么就会发生管道中断,默认的系统操作就是进程结束。

    感悟: linux中的文件概念非常的广泛,不仅是管道,很多的东西都可以理解为文件,而它实际的实现也是通过文件来是实现的。这就是linux的伟大。一个文件走遍天下

一起看看pipe的真实面貌:

int pipe(int pfd[2])
{
        int r;
        struct Fd *fd0, *fd1;  //文件描述符相关数据结构
        void *va

        // allocate the file descriptor table entries

        if ((r = fd_alloc(&fd0)) < 0   //内核操作函数,不知道干什么的
            || (r = sys_page_alloc(0, fd0, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0)  //估计是开辟空间
                goto err;            // 以后读内核代码了解细节

        if ((r = fd_alloc(&fd1)) < 0
            || (r = sys_page_alloc(0, fd1, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0)
                goto err1;   //c中忌讳的跳转在这里用的很多,高效的跳转

        // allocate the pipe structure as first data page in both

        va = fd2data(fd0);
        if ((r = sys_page_alloc(0, va, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0)
                goto err2;
        if ((r = sys_page_map(0, va, 0, fd2data(fd1), PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0)
                goto err3;

        // set up fd structures

        fd0->fd_dev_id = devpipe.dev_id;
        fd0->fd_omode = O_RDONLY;  //知道为什么fd[0]是为读而开

        fd1->fd_dev_id = devpipe.dev_id;
        fd1->fd_omode = O_WRONLY; //fd[1]为写开的

        if (debug)
                cprintf("[%08x] pipecreate %08x\n", env->env_id, vpt[VPN(va)]);

        pfd[0] = fd2num(fd0);
        pfd[1] = fd2num(fd1);
        return 0;

    err3:
        sys_page_unmap(0, va);
    err2:
        sys_page_unmap(0, fd1);
    err1:
        sys_page_unmap(0, fd0);
    err:
        return r;
}

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