Chinaunix首页 | 论坛 | 博客
  • 博客访问: 166447
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 675
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-26 00:58
文章分类
文章存档

2014年(2)

2013年(41)

我的朋友

分类: C/C++

2013-03-11 19:55:25

我第一次看完这个例子,基本就懂了,但是dup2不是很懂。
下面挂两个链接,一个是这个例子的出处,一个dup2的讲解。
http://linux.chinaunix.net/techdoc/develop/2008/02/21/979889.shtml

但是这里还有点问题,就是管道的同步问题,ls,wc如果由于调度原因,先执行的父进程,也就是wc,wc没有输出,如何输出到标准输出?
对于写管道:
   写入管道的数据按到达次序排列。如果管道满,则对管道的写被阻塞,直到管道的数据被读操作读取。对于写操作,如果一次write调用写的数据量小于 管道容量,则写必须一次完成,即如果管道所剩余的容量不够,write被阻塞直到管道的剩余容量可以一次写完为止。如果write调用写的数据量大于管道 容量,则写操作分多次完成。如果用fcntl设置管道写端口为非阻塞方式,则管道满不会阻塞写,而只是对写返回0。
  
  对于读管道:
   读操作按数据到达的顺序读取数据。已经被读取的数据在管道内不再存在,这意味着数据在管道中不能重复利用。如果管道为空,且管道的写端口是打开状 态,则读操作被阻塞直到有数据写入为止。一次read调用,如果管道中的数据量不够read指定的数量,则按实际的数量读取,并对read返回实际数量 值。如果读端口使用fcntl设置了非阻塞方式,则当管道为空时,read调用返回0。
#include
int fd[2];
void run_ls()
{
      dup2(fd[1],1);
     close(fd[0]);
     close(fd[1]);
     execve("/bin/ls",NULL,NULL);
}
void run_wc()
{
      dup2(fd[0],0);
     close(fd[0]);
     close(fd[1]);
     execve("/usr/bin/wc",NULL,NULL);
}
int main()
{
    pipe(fd);
    if(fork()==0)
        run_ls();
    else
        run_wc();
     return 0;
}
好,先面说说我的理解。pipe,建立一个管道,0是read,1是write。
子进程与行run_ls(父进程雷同,只说一个)。dup2的作用:
每个进程有自己的文件描述符表。
我们把fd看成一个结构体类型,就如上面图形中画的那样,我们不妨把之定义为:
struct fd_t {
int index;
filelistitem *ptr;
};
这 里 dup2(fd[1],1);的结果就是1这个fd原本指向的fileitem关闭了,他现在和fd[0]共享一个fileitem,fd[0]关闭后1 存在,所以这个fileitem不会关闭。1是原本是STDOUT,也就是标准输出关闭了,1指向了之前开辟的管道。
从上面的分析我们可以看 出,linux中创建进程是从父进程"fork"出来,然后再execve,而不是在创建时就指定它要运行的函数,完成独立地创建,这样天然的进程的继承 关系,为管道的实现提供了很大的方便,因为管道的实现利用了子进程继承父进程的文件描述符表这一特性。
阅读(3828) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~