中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > C/C++
请教蓝色键盘:关于name stream pipe的用法问题
作者:未知 时间:2005-09-13 19:26 出处:ChinaUnix.net 责编:chinaitpower
              摘要:请教蓝色键盘:关于name stream pipe的用法问题

SCO openserver 5 上可以通过/dev/spx创建无名流管道,再通过mknod为无名流管道捆绑一个文件名成为命名流管道。这部分代码在SCO的man spx中都有。

我的问题是,按如上方法创建出一个命名流管道后(假设文件名为"nspfile"),任意两个无关进程如何使用这个文件进行通信?

我试过如下方法:
进程1:
        fd=open("nspfile",O_RDWR);
        read( fd, buf, 10 );               // fail,errno=5
进程2:
        fd=open("nspfile",O_RDWR);
        write( fd, buf, 10 );              // success
运行结果是进程2的write正确,但是进程1的read出错,errno=5,I/O错误

请教正确的用法是怎样的?

 nde 回复于:2003-12-01 09:35:53
顶一下

 蓝色键盘 回复于:2003-12-01 12:17:21
read和write对应管道的fd0和fd1。

 nde 回复于:2003-12-01 13:21:40
[quote:1d477501ee="蓝色键盘"]read和write对应管道的fd0和fd1。[/quote:1d477501ee]
命名的流管道以一个文件名的形式存在,用open打开这个文件名只能得到一个fd,何来fd[0]、fd[1]?
是不是要连续open两次?

 nde 回复于:2003-12-01 13:31:34
按照open两次的思路改了一下程序,结果还是同样的错误

进程1: 
fd0=open("nspfile",O_RDONLY); 
fd1=open("nspfile",O_WRONLY); 
read( fd0, buf, 10 ); // fail,errno=5

进程2: 
fd0=open("nspfile",O_RDONLY); 
fd1=open("nspfile",O_WRONLY); 
write( fd1, buf, 10 ); // success

运行结果是进程2的write正确,但是进程1的read出错,errno=5,I/O错误

 nde 回复于:2003-12-01 14:35:37
补充说明:
以上代码的目的是进程1和进程2通过命名流管道nspfile通讯,进程2发送数据给进程1。nspfile是事先创建好的并以一个文件形式存在的命名流管道。

 mmHunter 回复于:2003-12-01 23:16:08
建议参考一下postfix的源代码,stream部分写的挺好的...

 nde 回复于:2003-12-02 09:30:16
[quote:4c6ece04a7="mmHunter"]建议参考一下postfix的源代码,stream部分写的挺好的...[/quote:4c6ece04a7]

多谢你的建议。postfix我不太熟,是否使用到SVR3.2的流管道也不清楚,所以我不打算花时间去看源码了。

SCO OpenServer 5是SVR3.2的版本,支持的是/dev/spx流管道,与SVR4的pipe和BSD的socketpair不同。

我想试的是SCO OpenServer 5的/dev/spx流管道。根据man spx中提供的源码已经成功创建了命名流管道,但是如何open/read/write在man spx中没有提及,我试过各种方法都不成功,怀疑可能是BUG。

SVR3.2的流管道没什么人用,实在搞不定就算了,仅仅是研究探讨一下。

 mmHunter 回复于:2003-12-02 10:51:51
postfix就是用了流管道,不过如果不是很大量很大量的通讯,没有必要采用流管道,unix domain socket就行,移植性也好...

 nde 回复于:2003-12-02 13:08:08
[quote:d8f17ef08a="mmHunter"]postfix就是用了流管道,不过如果不是很大量很大量的通讯,没有必要采用流管道,unix domain socket就行,移植性也好...[/quote:d8f17ef08a]

我查了postfix源码,用的是命名管道FIFO,没有使用/dev/spx命名流管道,因为/dev/spx是SVR3.2特有的,一般代码考虑移植性是不会使用。

 mmHunter 回复于:2003-12-02 13:25:30
哦,我想当然了... postfix用的是I_SENDFD方式的流...
另外,精华区有相关的文章,挺详细的呀?http://chinaunix.net/jh/23/107530.html

 nde 回复于:2003-12-02 15:03:49
[quote:f6b9b3cf61="mmHunter"]哦,我想当然了... postfix用的是I_SENDFD方式的流...
另外,精华区有相关的文章,挺详细的呀?http://chinaunix.net/jh/23/107530.html[/quote:f6b9b3cf61]

你真是个热心人,多谢了。
那篇文章我看过,作者蓝色键盘,这个帖子题目就是想请教他的。那篇文章的主要内容就是man spx输出的结果。其中uname stream pipe“无名”流管道的部分我已试验过OK,进一步试验named stream pipe“有名”流管道时遇到问题-create/open/write OK,read errno=5。这是man spx以及那篇文章中都没有提到的。我用google搜索过/dev/spx都没有找到相关信息。

 gadfly 回复于:2003-12-04 15:28:51
可惜我没有sco的环境。

不过我看了一下说明,通过spx建立无名管道,需要打开这个设备两次,
并通过ioctl对这两个描述符建立对应的联系。之后就和通常的pipe操作一样了。希望以下的代码对你有所帮助,并且,也讲述到了如何通过spx建立有名管道,以及传递文件描述符。

http://osr5doc.ca.caldera.com:457/cgi-bin/man/man?spx+HW
[code:1:88fbac74fc]
Examples
A routine to create an unnamed bi-directional stream pipe in the manner of pipe(S): 
#include <unistd.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/stat.h>
#include <termio.h>
#include <signal.h>
#define SPX "/dev/spx"

int spipe(fd)
int *fd;
{
   struct strfdinsert s;
   long p;

   if ( ( fd[0] = open(SPX, O_RDWR) ) < 0 )
          return(-1);
   if ( ( fd[1] = open(SPX, O_RDWR) ) < 0 ) /* open different minor */
          return(-1);

   s.ctlbuf.buf = (caddr_t) &p ;
   s.ctlbuf.maxlen = s.ctlbuf.len = sizeof(long);
   s.databuf.buf = (caddr_t) NULL;
   s.databuf.maxlen = s.databuf.len = -1; 
   s.fildes = fd[1];
   s.offset = s.flags = 0;

   if ( ioctl(fd[0], I_FDINSERT, &s) < 0 ) /* join loop drivers */
        return(-1);
   return(0);
}

A routine to create a named stream pipe from a unnamed one (this requires root privilege): 
   int nspipe(fd, pipename)
   int *fd;
   char *pipename;
   {
     struct stat status;
     int omask;
   
     if ( spipe(fd) < 0 )
    return(-1);
   
     if ( fstat(fd[0],&status) < 0 ) 
    return(-1);
   
     unlink(pipename);
     omask = umask(0);
     if ( mknod(pipename, S_IFCHR|0666, status.st_rdev) < 0 ) /* create node */
    return(-1);
     umask(omask);
   
     return(0);
   }

A routine to pass a file descriptor to another process: 
   int passfd(fd, sendfd)
   int fd, sendfd;
   {
      if ( ioctl(fd, I_SENDFD, sendfd) < 0 ) /* send descriptor sendfd */
    return(-1);
   }

A routine to receive a file descriptor from a process: 
   int recvfd(fd)
   int fd;
   {
    struct strrecvfd s;
   
    if ( ioctl(fd, I_RECVFD, (char *) &s) < 0 )
    return(-1);
   
   /* s.uid received effective user ID of sender
    s.gid received effective group ID of sender */
   
    return(s.fd); /* received file descriptor */
   }

[/code:1:88fbac74fc]

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有