APUE学习笔记(1)-限制查询
2009-10-27 11:05 htc开发 阅读(165) 评论(0) 编辑 收藏 举报
写在前面
1. 学习 linux 环境下的编程,《 UNIX 环境高级编程》(行话叫 APUE )应该是必读的一本书。毫无疑问, APUE 可以作为 API 的参考手册。但是,个人认为书中的许多概念和思想仍然需要细细揣摩。细节的积累,一来是良好模式设计的基础,二来为学习内核知识提供了上层视角。读书笔记的目的正在于此,而 linux 开放、自由的思想始终是一种原动力。
2. APUE.2e 及其源码可以从 这里 下载。源码在 linux 下的编译需要做几处修改,可以参考《 在 Linux 下编译 APUE 的例子 》。我使用的系统是 Ubuntu 9.04 ( linux-2.6.29.3 , gcc-4.3.3 )。
3. 关于 Makefile 和 GDB 的使用,可以参考《 Makefile 备忘录 》和《 用 GDB 调试程序 》
4. 本文内容对应《 UNIX 环境高级编程》 ( 第 2 版 ) 》第 2 章。
5. 主要记录了查询系统限制的 3 个函数: sysconf , pathconf 和 fpathconf 。虽然,在学习的开始阶段,过多的考虑各个标准和不同系统之间的限制和差异,会让人举步维艰,但是至少应该知道它们的存在。这是编写高可移植性代码的重要组成部分。
6. 如果你和我一样,是 linux 世界的入门选手(俗称菜鸟),那么让我们共同努力吧:)
几个标准
l ISO C ,它的意图是提供 C 程序的可移植性,使其能适合于大量不同的操作系统,而不只是 UNIX 系统。此标准不仅定义了 C 程序设计语言的语法和语义,还定义了其标准库。
l POSIX ( Portable OOperating System Interface ),指的是可移植的操作系统接口。该标准的目的是提高应用程序在各种 UNIX 系统环境之间的可移植性,定义了“依从 POSIX ”的操作系统必须提供的各种服务。
l SUS ( Single UNIX Specification ),是 POSIX 标准的一个超集,定义了一些附加的接口,扩展了基本的 POSIX.1 规范所提供的功能。相应的系统接口全集被成为 X/Open 系统接口( XSI , X/Open System Interface )。只有遵循 XSI 的实现才能成为 UNIX 系统。
到目前为止,对这些标准毫无头绪。等碰到哪个 Undefined 函数再说吧:)
系统限制
了解系统限制的最主要目的是,保证应用程序可移植性。这些限制主要分为两类:编译时限制和运行时限制。编译时限制可在头文件中定义,如 ISO C 标准在文件 <limits.h> 中关于类型最大值和最小值的限制。运行时限制则要求进程调用一个函数以获得这种限制,主要包含使用 sysconf 函数查询的不与文件或目录相关联的运行时限制,以及使用 pathconf 或 fpathconf 函数查询的与文件或目录相关联的运行时限制。实际上,这种说法并不准确。编译时限制仍然能够通过函数进行查询,如 sysconf(_SC_CHAR_MAX) ,而通过以上三个函数查询的限制也可以定义在头文件中。或许只有那些由内核通过 proc 文件系统进行读取或配置的才能称为运行时限制。可以在终端中输入下面命令,找出这些限制。
$ find /proc/sys -name '*max*' |
这里,希望记住的只是如何利用上述函数查询系统限制。
#include <unistd.h> long sysconf(int name); long pathconf(const char *pathname, int name); long fpathconf(int filedes, int name); |
其中, sysconf 函数所使用的 name 参数以 _SC_ 开头, pathconf 和 fpathconf 函数所使用的 name 参数以 _PC_ 开头,它们都用于标识系统限制,可以在 man 中查询各标识代表的具体限制。 pathconf 和 fpathconf 函数都用于查询与文件或目录相关的限制,区别在于前者使用路径名作为参数,后者使用文件描述符作为参数。至于应该指向文件还是目录,由 name 标识的限制决定,仍然可以参考 man 手册。正常情况下,三个函数将返回限制的具体值。如果 name 参数不是一个已定义的常量,则三个函数都返回- 1 ,并将 errno 设置为 EINVAL 。有些系统限制是不确定的,这时,三个函数同样返回- 1 ,但是不改变 errno 的值。因此,要区分后两种情况,需要结合返回值和 errno 进行判断。函数的使用范例如下:
#include <stdio.h> #include <unistd.h> #include <errno.h>
#define NAME_MAX_GUESS 255 /* 限制不确定时使用*/
int main() { int namemax=0;
errno = 0; /* 先置0 ,然后判断是否被改变*/ if((namemax=pathconf("/", _PC_NAME_MAX)) < 0) { if(errno == 0) { printf("_PC_NAME_MAX is inderterminate./n"); namemax = NAME_MAX_GUESS; } else { printf("pathconf error for _PC_NAME_MAX./n"); } } printf("namemax=%d./n", namemax);
return 0; } |