LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1858|回复: 20

学习fcntl的功能时例子程序,有点迷糊。

[复制链接]
发表于 2003-10-15 19:00:54 | 显示全部楼层 |阅读模式
请帮忙分析以下的程序,有点迷糊。
程序的功能到底是对什么进行操作?
我随便输入a.out file都是write only

  1. #include <sys/types.h>
  2. #include <fcntl.h>
  3. #include "selfdef.h"

  4. int
  5. main(int argc, char *argv[])
  6. {

  7.         int accmode, val;
  8.        
  9.         if (argc != 2)
  10.                 err_quit("usage:a.out <descriptor#>");
  11.         if ((val=fcntl(atoi(argv[1]), F_GETFL, 0))<0)
  12.                 err_sys("fcntl error for fd %d", atoi(argv[1]));
  13.         accmode=val & O_ACCMODE;
  14.         if (accmode=O_RDONLY) printf("read only");
  15.         else if (accmode=O_WRONLY) printf("write only");
  16.         else if (accmode=O_RDWR) printf("read write");
  17.         else err_dump("unknown access mode");
  18.        
  19.         if (val & O_APPEND)
  20.          printf(", append");
  21.         if (val & O_NONBLOCK)
  22.          printf(", nonblocking");
  23.        
  24. #if !defined (_POSIX_SOURCE) && defined (O_SYNC)
  25.         if (val & O_SYNC)
  26.          printf(", synchronous writes");
  27. #endif

  28.         putchar('\n');
  29.        
  30. exit(0);
  31. }

复制代码
发表于 2003-10-15 19:12:39 | 显示全部楼层
if ((val=fcntl(atoi(argv[1]), F_GETFL, 0))<0)
这句错了,fcntl的第一个参数是文件描述符,应该是用open打开的文件返回的描述符,atoi是把字符串参数转换成int,atoi("22a")返回22,atoi("aa")返回0,所以你这里不论传入什么命令行参数,只要第一个字符不是数字,就变成对0(标准输入)调用fcntl,所以就全都是"write only"
 楼主| 发表于 2003-10-15 19:43:48 | 显示全部楼层
明白了,谢谢你的帮助。
但是我还是不明白这段程序的意思,
我是照这一本书上写的,
他说这个程序获取指定的一个文件描述符的命令行参数,并打印该描述符的文件标志说明。
到底它怎么实现啊?应该是要我输入一个fd,但是还是不懂它的意思。
 楼主| 发表于 2003-10-15 19:47:06 | 显示全部楼层
比如我输入一个a.out -1,它能打印出
fcntl error for fd -1:Bad file descriptor。
我输入0或者正数时都是write only。
它的使用我不明白,a.out <descriptor#>
是不是要我写a.out O_RDONLY啊?
他那个atoi的用法我想是为了转换O_RDONLY这样的fd到
整形的fd的作用吧。所以我想这个应该没有错,
关键是不知道怎么运行这个东东。
发表于 2003-10-15 21:46:09 | 显示全部楼层
if (accmode=O_RDONLY) printf("read only");
else if (accmode=O_WRONLY) printf("write only");
else if (accmode=O_RDWR) printf("read write");

这几句有问题,应该是"==",全写成"="了。
发表于 2003-10-15 21:53:48 | 显示全部楼层

  1.         if (accmode=O_RDONLY) printf("read only");
  2.         else if (accmode=O_WRONLY) printf("write only");
  3.         else if (accmode=O_RDWR) printf("read write");

复制代码


有没有写错呀!
if 是条件语句,括号里一般为关系表达式。
if (accmode=O_RDONLY)
是赋值语句,永远为真。
是不是应该改成 :
if (accmode==O_RDONLY)

讲得就是 unix 的系统调用中的文件操作,每一个文件被打开后,都会返回一个文件描述符 fd,然后可以用 fcntl 对指定的 fd 进行各种文件操作。在这个例子中就是判断指定文件的访问模式。

man 2 fcntl

if ((val=fcntl(atoi(argv[1]), F_GETFL, 0))<0)
很容易看懂,fcntl(atoi(argv[1]), F_GETFL, 0) 通过 F_GETFL 获取文件描述标志,如果正确返回标志值,出现错误返回 -1。

然后把标志值和预知的模式进行比较。
 楼主| 发表于 2003-10-16 10:08:53 | 显示全部楼层
如果我直接运行这个程序该怎么样呢?
当我运行a.out <O_RDONLY#>
会出现-bash: syntax error near unexpected token `newline'
发表于 2003-10-16 10:53:28 | 显示全部楼层
我改成 (accmode == O_RDONLY)等等以后

运行结果是:
$./x 5 5</tmp/x
read only
$./x 5 5>/tmp/x
write only
$./x 5 5<>/tmp/x
read write,
$./x 5 5>>/tmp/x
write only, append

x 是编译连接的结果。

但是
$./x 0
read write
$./x 1
read write
$./x 2
read write

我却不能解释。
 楼主| 发表于 2003-10-16 12:04:08 | 显示全部楼层
我和你运行的结果是一样的,但是
谁能解释一下吗?
我真的很迷糊,不了解这个程序的工作。
发表于 2003-10-16 12:55:41 | 显示全部楼层
fnctl 用于 file descriptor 的各种各样的操作。
具体是什么操作(manipulate), 由 第二个参数 cmd 决定。
第一个参数是一个 file descriptor, 一般由 open 系统调用返回。
一个程序有 三个标准的 file descriptor , 在进程创建的时候打开。
0 stand in
1 stand out
2 stand err

运行结果是:
$./x 5 5</tmp/x
read only
$./x 5 5>/tmp/x
write only
$./x 5 5<>/tmp/x
read write,
$./x 5 5>>/tmp/x
write only, append

F_GETFL 用于得到 descriptor's flags . 也就是 open 的时候的 flag.

5 < /tmp/x 是 shell 的语法,用于把 file descriptor 5 用于输入。
同样
5 > /tmp/x 用于输出重定向。
5 <> /tmp/x  用于输入输出重定向
5 >> /tmp/x 用于追加输出重定向。


x 是编译连接的结果。

但是
$./x 0   #我期待的是 read only
read write
$./x 1      #我期待是 write only
read write
$./x 2     # 我期待是 write only
read write
我没有办法解释,请高手指点。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表