您的位置:首页 > 编程语言

unix环境高级编程 程序3-11(fileflags.c)全面解析

2017-01-18 11:09 204 查看
源程序:

#include "apue.h"
#include <fcntl.h>

int
main(int argc, char *argv[])
{
int val;

if (argc != 2)
err_quit("usage: a.out <descriptor#>");

if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0)
err_sys("fcntl error for fd %d", atoi(argv[1]));

switch (val & O_ACCMODE) {
case O_RDONLY:
printf("read only");
break;

case O_WRONLY:
printf("write only");
break;

case O_RDWR:
printf("read write");
break;

default:
err_dump("unknown access mode");
}

if (val & O_APPEND)
printf(", append");
if (val & O_NONBLOCK)
printf(", nonblocking");
if (val & O_SYNC)
printf(", synchronous writes");

#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC)
if (val & O_FSYNC)
printf(", synchronous writes");
#endif

putchar('\n');
exit(0);
}程序运行结果:(如何运行该书实例代码 参见
APUE.3e 安装(基于ubuntu12.0.4) )
 root@ubuntu:/home/yuccess/shiyan/apue.3e/fileio# ./fileflags 0 < /dev/tty
read only
root@ubuntu:/home/yuccess/shiyan/apue.3e/fileio# ./fileflags 1 > temp.foo
root@ubuntu:/home/yuccess/shiyan/apue.3e/fileio# cat temp.foo
write only
root@ubuntu:/home/yuccess/shiyan/apue.3e/fileio# ./fileflags 2 2>>temp.foo
write only, append
root@ubuntu:/home/yuccess/shiyan/apue.3e/fileio# ./fileflags 5 5<>temp.foo
read write
问题1:./fileflags 0 < /dev/tty 什么意思?
知识点重定向(讲解重定向比较好的文章)

< /dev/tty 的意思就是将标准输入重定向为文件tty

0是main()第二个参数(在问题2中讲解)

第一个参数是./fileflags

问题2: ./fileflags 2 2>>temp.foo怎么解释。

有了重定向的知识后,我们知道了2>>temp.foo的意识就是 将一个标准错误输出重定向到一个文件或设备 追加到原来的文件

那么 中间的那个2 又是什么意思?从源程序说起

main(int argc, char *argv[]) main函数参数argv此时为什么?

可以用print()将argv打印出来,不过这样的话就得重新编译了。这时候采用GDB调试的方法,来查看argv。

step1:在终端输入gcc fileflags.c -g -o fileflags -l apue 

step2:输入 gdb fileflags

step3:进入gdb后输入调试代码:

(gdb) l  -->显示代码

(gdb) b -->设置断点

(gdb) r 2 2>>temp.foo -->run<
4000
/p>
(gdb) p argv[1] --> 显示结果为 $2 = 0xbffff565 "2"

(gdb) p *argv@2 -->显示数组里的前两个结果 $6 = {0xbffff537 "/home/yuccess/shiyan/apue.3e/fileio/fileflags", 0xbffff565 "2"}

至此我们gdb调试完毕,可以发现 2 是main的第二个参数,而 2>>temp.foo表示将标准输出重定向到temp.foo上(类似于 < /dev/tty),不是一个参数,至于为什么不太清清楚。

感受:gdb调试全键盘的操作,比vs2013、xcode神马的爽爆了啊!

附gdb调试常用命令:

命令描述
backtrace(或bt)查看各级函数调用及参数
finish连续运行到当前函数返回为止,然后停下来等待命令
frame(或f) 帧编号选择栈帧
info(或i) locals查看当前栈帧局部变量的值
list(或l)列出源代码,接着上次的位置往下列,每次列10行
list 行号列出从第几行开始的源代码
list 函数名列出某个函数的源代码
next(或n)执行下一行语句
print(或p)打印表达式的值,通过表达式可以修改变量的值或者调用函数
quit(或q)退出
gdb
调试环境
set var修改变量的值
start开始执行程序,停在
main
函数第一行语句前面等待命令
step(或s)执行下一行语句,如果有函数调用则进入到函数中
在gdb中,和调试步进相关的命令主要有如下几条:

continue    继续运行程序直到下一个断点(类似于VS里的F5)

next        逐过程步进,不会进入子函数(类似VS里的F10)

setp        逐语句步进,会进入子函数(类似VS里的F11)

until        运行至当前语句块结束

finish    运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)

问题3:下面这句 话的解释if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0)
首先fcntl()函数的意思是改变/返回一个已经打开文件的属性。

参数F_GETFL说明,该函数要返回文件(第一个参数)的状态标识。

可以调试查看val的结果,如果想显示宏O_ACCMODE的值的话,需要在终端这样输入:gcc
-gdwarf-2 -g3 fileflags.c -l apue -o fileflags

具体细枝末节请参阅APUE 3.14小节

总结:至此已经基本完全理解了该实例,学习了重定向,GDB调试,fcntl等知识,通过调试实践APUE上面的知识,相信对初学linux编程的童鞋会有帮助。

接下来继续啃APUE。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: