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

源程序:

#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

(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。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值