Chinaunix

标题: 关于select能否用于普通文件操作的疑问。 [打印本页]

作者: NewCore    时间: 2007-06-01 23:57
标题: 关于select能否用于普通文件操作的疑问。
问题是这样的:

我想把普通文件的读写设置成异步模式的,

fd = open();
fd_set rfds;
int maxfd;

fcntl(fd, F_SETFL, O_NONBLOCK);
mafd = fd + 1;
FD_SET(fd, &rfds);
/*... */
int ret = selete(maxfd, NULL, &rfds, NULL, &tv)
{
if(FD_ISSET(fd, &rfds))
{
    /** ??? **/
}
}
我想通过这种方式来设置文件为异步读方式,如果有数据可读,就去读,否则就等待。但是现在是一直能有读时间触发,就是???号那个地方始终可以进入,没有阻塞
请问到底可不可以这样,或者我有哪个地方搞错了?谢谢,我晚上在线等回答...
作者: NewCore    时间: 2007-06-02 00:08
纠正一下笔误:
int ret = selete(maxfd, NULL, &rfds, NULL, &tv) ——————〉
int ret = selete(maxfd, &rfds, NULL, NULL, &tv)
作者: MMMIX    时间: 2007-06-02 00:11
原帖由 NewCore 于 2007-6-1 23:57 发表于 1楼  
问题是这样的:

我想把普通文件的读写设置成异步模式的,

fd = open();
fd_set rfds;
int maxfd;

fcntl(fd, F_SETFL, O_NONBLOCK);
mafd = fd + 1;
FD_SET(fd, &rfds);
/*... */
int ret =  ...

select 是为了那些可能会永远 block 的 I/O 操作准备的,而对普通文件的 I/O 操作不属于此类。具体参见 APUE2 相关章节。
作者: NewCore    时间: 2007-06-02 00:24
MMMIX 你好,那么我如何来做到文件的异步读写呢?写文件不是由我控制的,但是我需要在有数据的时候,把数据读出来,该如何处理呢?谢谢,我等待你的答复。
作者: MMMIX    时间: 2007-06-02 00:25
原帖由 NewCore 于 2007-6-2 00:24 发表于 4楼  
MMMIX 你好,那么我如何来做到文件的异步读写呢?写文件不是由我控制的,但是我需要在有数据的时候,把数据读出来,该如何处理呢?谢谢,我等待你的答复。

请给出更全面详细的问题描述。
作者: NewCore    时间: 2007-06-02 00:39
原帖由 MMMIX 于 2007-6-2 00:25 发表于 5楼  

请给出更全面详细的问题描述。


先谢谢你的关注。

原始问题是这样的:执行tar命令,然后把tar输出到标准输出的文件列表截获下来,作为我们自己的程序使用。最好的方式是管道和重定向,但是因为某种原因,这种方式不可行。不可行是因为我们的系统里面执行system(...)的时候,命令的输出不是到标准输出的,至于输出到哪里,我也不清楚。(因为嵌入式系统里面,可能存在这样的问题吧。如果你知道,那谢谢告诉我)。那么所有,重定向的操作的方案就都不可行了。于是,我只有使用这样的方法,就是system("tar ... > file"),然后另外一个进城从file去读数据,但是什么时候有数据呢,不是我决定的,而是tar命令的执行来决定的,这就是比较详细地问题描述。我等候你的答复。
作者: scutan    时间: 2007-06-02 10:05
原帖由 NewCore 于 2007-6-2 00:39 发表于 6楼  


先谢谢你的关注。

原始问题是这样的:执行tar命令,然后把tar输出到标准输出的文件列表截获下来,作为我们自己的程序使用。最好的方式是管道和重定向,但是因为某种原因,这种方式不可行。不可行是因为我 ...



你的tar结束之后system()函数才会返回.
如果你想同时进行的话,就弄两个进程吧.
作者: NewCore    时间: 2007-06-02 10:48
原帖由 scutan 于 2007-6-2 10:05 发表于 7楼  



你的tar结束之后system()函数才会返回.
如果你想同时进行的话,就弄两个进程吧.


现在就是两个进程,一个进程执行system("tar"),另外一个进程去读文件,但是这种方式可行吗|?我测试的结果是什么都读不出来....
作者: scutan    时间: 2007-06-02 11:04
原帖由 NewCore 于 2007-6-2 10:48 发表于 8楼  


现在就是两个进程,一个进程执行system("tar"),另外一个进程去读文件,但是这种方式可行吗|?我测试的结果是什么都读不出来....



你看看你system()函数的返回值, 看其是否正确地执行了.
另外, 你在执行tar的时候, 注意你重定向的文件的路径的问题. 必要时写上绝对路径.
作者: MMMIX    时间: 2007-06-02 11:21
原帖由 NewCore 于 2007-6-2 00:39 发表于 6楼  


先谢谢你的关注。

原始问题是这样的:执行tar命令,然后把tar输出到标准输出的文件列表截获下来,作为我们自己的程序使用。最好的方式是管道和重定向,但是因为某种原因,这种方式不可行。不可行是因为我 ...

不要用 system,直接用 fork+exec 来执行 tar 命令,然后通过管道来传递数据。
作者: MMMIX    时间: 2007-06-02 11:28
原帖由 NewCore 于 2007-6-2 10:48 发表于 8楼  


现在就是两个进程,一个进程执行system("tar"),另外一个进程去读文件,但是这种方式可行吗|?我测试的结果是什么都读不出来....

可行的,但是在读文件的时候需要用 tail -f 命令。
作者: NewCore    时间: 2007-06-02 11:30
原帖由 scutan 于 2007-6-2 11:04 发表于 9楼  



你看看你system()函数的返回值, 看其是否正确地执行了.
另外, 你在执行tar的时候, 注意你重定向的文件的路径的问题. 必要时写上绝对路径.


system执行是绝对没有问题的,因为解包后的文件已生成。
tar命令我就是用的绝对路径。
作者: NewCore    时间: 2007-06-02 11:32
原帖由 MMMIX 于 2007-6-2 11:21 发表于 10楼  

不要用 system,直接用 fork+exec 来执行 tar 命令,然后通过管道来传递数据。


我开始就是用得这样的标准揭发,但是因为我上面说的原因,system执行的结果没有到管道,所以才采用重定向到文件,再读文件的方法。
我马上用exec试一下。
作者: NewCore    时间: 2007-06-02 11:33
原帖由 MMMIX 于 2007-6-2 11:28 发表于 11楼  

可行的,但是在读文件的时候需要用 tail -f 命令。


c代码里面怎么用tail -f命令读文件?不明白.
作者: MMMIX    时间: 2007-06-02 11:37
原帖由 NewCore 于 2007-6-2 11:33 发表于 14楼  


c代码里面怎么用tail -f命令读文件?不明白.

呃……还得用重定向,又绕回去了

当然,你也可以自己实现和 tail -f 类似的功能,这个倒是可行。

[ 本帖最后由 MMMIX 于 2007-6-2 11:38 编辑 ]
作者: NewCore    时间: 2007-06-02 12:12
原帖由 MMMIX 于 2007-6-2 11:37 发表于 15楼  

呃……还得用重定向,又绕回去了

当然,你也可以自己实现和 tail -f 类似的功能,这个倒是可行。


我用execv和execvp试了下,问题一样,没有数据到管道...

我来看看tail -f怎么用,好不好实现。

有没有其他思路|?难道不能重定向到管道,这个还真变成impossible mission了....
作者: MMMIX    时间: 2007-06-02 13:25
原帖由 NewCore 于 2007-6-2 12:12 发表于 16楼  


我用execv和execvp试了下,问题一样,没有数据到管道...

我来看看tail -f怎么用,好不好实现。

有没有其他思路|?难道不能重定向到管道,这个还真变成impossible mission了....

呃,我觉得你应该检查下其他的方面,例如说 tar 有没有输出,你是不是错把标准错误当作标准输出了等等。再不然就把你不能工作的代码精简成一个完整的例子贴上来。
作者: isnowran    时间: 2007-06-02 16:28
类似tail -f,有新数据就读,否则等待
有很多情况没有判断,演示而已

  1. int main()
  2. {
  3.         int fd = open( "hello", O_RDWR |  O_CREAT, 0755 );
  4.         char buf[4096] = {};
  5.         int filesize = 0;
  6.         struct stat st;
  7.         while( 1 )
  8.         {
  9.                 fstat( fd, &st );
  10.                 if( st.st_size > filesize )
  11.                 {
  12.                         filesize = st.st_size;
  13.                         bzero( buf, sizeof( buf ) );
  14.                         int retval = read( fd, buf, sizeof( buf ) - 1 );
  15.                         printf( "%s\n", buf );
  16.                 }
  17.                 else
  18.                 {
  19.                         printf( "no new data\n" );
  20.                         sleep( 1 );
  21.                 }
  22.         }

  23.         return 0;
  24. }
复制代码

[ 本帖最后由 isnowran 于 2007-6-2 16:30 编辑 ]
作者: SuperZ    时间: 2007-06-02 20:24
请重定向到命名管道,而不是普通文件。
作者: NewCore    时间: 2007-06-02 21:09
我谢大家的关注,我已解决了此问题。还是采用子进程system("tar > file"),父进程从文件读的方式,不过有些细节还需要特殊处理下。

to isnowran:
方法不错,我记下了,以后也许会有用到的时候。

to SuperZ:
谢谢你的回复,不过请看完前面的帖子再说,否则随便答复,你不觉得很不负责任吗?

anyway, 该问题暂时算告一段落。3ks all.
作者: flw2    时间: 2007-06-02 23:16
linux
google inotify
作者: flw2    时间: 2007-06-02 23:22
select的作用是对不能立马读到的fd设置超时,而你需要的是监控文件又没有变化。
select对普通文件根本不会超时。
作者: flw2    时间: 2007-06-02 23:23
如果select能用于普通文件,那么它应该就成为U_SelEct
作者: zhugcx    时间: 2007-06-04 12:29
怎么不用popen ,,我很奇怪哦
作者: NewCore    时间: 2007-06-04 17:43
to zhugcx,不能用popen!!! 你以为我不想用啊,哎,我有苦难言.

各位,我现在遇到了新的问题,请继续跟踪帖子http://linux.chinaunix.net/bbs/v ... &extra=page%3D1




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2