这一章的阅读相对枯燥,20世纪80年代UNIX版本种类剧增以及他们之间的差别的扩大,导致很多用户呼吁对其进行标准化。
UNIX标准化介绍了ISO C IEEE POSIX Single UNIX Specification FIPS,这部分内容不详细总结。
UNIX系统实现介绍了 SVR4 4.4BSD Free BSD Linux Mac OSX Solaris.
UNIX系统中的“限制”,主要包括两类限制:
编译时限制,例如,短整型的最大值是多少。编译时限制可在头文件中定义,程序在编译时可包含这些头文件。
运行时限制,例如,文件名有多少个字符。运行时限制要求进程调用一个函数获得限制值。
但以上这些限制都不是绝对,某些限制在一个给定的实现中可能是固定的(可采用静态地在一个头文件中定义),而在另一个实现中可能是变动的(需要有一个运行时函数调用)。为了解决这类问题,操作系统提供了以下三种限制:
编译时限制(头文件)。
与文件或目录无关的运行时限制(sysconf函数)。
与文件或目录有关的运行时限制(pathconf和fpathconf函数)。
运行时限制可调用如下三个函数之一获得。
#include<unistd.h>
long sysconf(int name);
long pathconf(const char *pathname,int name);
long fpathname(int fd,int name);
后两个函数的差别是:一个用路径名作为参数,一个则取文件描述符作为参数。
这里要着重谈一下这三个函数的返回值:
如果name参数不正确,那么这三个函数都返回-1,并将errno设为EINVAL。
如果某个name返回的值不确定,那么同样返回-1,但此时不改变errno的值,所以对于这三个函数的利用,首先需要设置errno为0,在返回-1的情况下,同时需要检查errno的值,若此时errno仍然为0,那么说明这个值在操作系统中没有定义。如果errno值不为0,那么调用函数时发生了错误。
若返回值>=0,那么说明程序正常返回。
由于本章中用到awk,所以要了解必要的awk知识:
执行awk的方法如下:
语法形式:awk -f awk脚本文件名 被处理文件名
./makeconf.awk sysconf.sym sysopt.sym
由于在makeconf.awk中getline(sysconf.sym) getline(pathconf.sym),所以可以省略被处理文件名。
./makeconf.awk即可生成我们所需要的C语言代码。
#include "apue.h"
#include <errno.h>
#include <limits.h>
static void pr_sysconf(char *,int);
static void pr_pathconf(char *,char *,int);
int
main(int argc,char *argv[])
{
if (argc != 2)
err_quit("usage: a.out <dirname>");
#ifdef ARG_MAX
printf("ARG_MAX defined to be %ld\n",(long)ARG_MAX+0);
#else
printf("no symbol for ARG_MAX\n");
#endif
#ifdef _SC_ARG_MAX
pr_sysconf("ARG_MAX =",_SC_ARG_MAX);
#else
printf("no symbol for _SC_ARG_MAX\n");
#endif
#ifdef ATEXIT_MAX
printf("ATEXIT_MAX defined to be %ld\n",(long)ATEXIT_MAX+0);
#else
printf("no symbol for ATEXIT_MAX\n");
#endif
#ifdef _SC_ATEXIT_MAX
pr_sysconf("ATEXIT_MAX =",_SC_ATEXIT_MAX);
#else
printf("no symbol for _SC_ATEXIT_MAX\n");
#endif
#ifdef CHARCLASS_NAME_MAX
printf("CHARCLASS_NAME_MAX defined to be %ld\n",(long)CHARCLASS_NAME_MAX+0);
#else
printf("no symbol for CHARCLASS_NAME_MAX\n");
#endif
#ifdef _SC_CHARCLASS_NAME_MAX
pr_sysconf("CHARCLASS_NAME_MAX =",_SC_CHARCLASS_NAME_MAX);
#else
printf("no symbol for _SC_CHARCLASS_NAME_MAX\n");
#endif
#ifdef CHILD_MAX
printf("CHILD_MAX defined to be %ld\n",(long)CHILD_MAX+0);
#else
printf("no symbol for CHILD_MAX\n");
#endif
#ifdef _SC_CHILD_MAX
pr_sysconf("CHILD_MAX =",_SC_CHILD_MAX);
#else
printf("no symbol for _SC_CHILD_MAX\n");
#endif
#ifdef CLOCKTICKSPERSECOND /*clock ticks/second*/
printf("CLOCKTICKSPERSECOND /*clock ticks/second*/ defined to be %ld\n",(long)CLOCKTICKSPERSECOND /*clock ticks/second*/+0);
#else
printf("no symbol for CLOCKTICKSPERSECOND /*clock ticks/second*/\n");
#endif
#ifdef _SC_CLK_TCK
pr_sysconf("CLOCKTICKSPERSECOND /*clock ticks/second*/ =",_SC_CLK_TCK);
#else
printf("no symbol for _SC_CLK_TCK\n");
#endif
#ifdef COLL_WEIGHTS_MAX
printf("COLL_WEIGHTS_MAX defined to be %ld\n",(long)COLL_WEIGHTS_MAX+0);
#else
printf("no symbol for COLL_WEIGHTS_MAX\n");
#endif
#ifdef _SC_COLL_WEIGHTS_MAX
pr_sysconf("COLL_WEIGHTS_MAX =",_SC_COLL_WEIGHTS_MAX);
#else
printf("no symbol for _SC_COLL_WEIGHTS_MAX\n");
#endif
#ifdef DELAYTIMER_MAX
printf("DELAYTIMER_MAX defined to be %ld\n",(long)DELAYTIMER_MAX+0);
#else
printf("no symbol for DELAYTIMER_MAX\n");
#endif
#ifdef _SC_DELAYTIMER_MAX
pr_sysconf("DELAYTIMER_MAX =",_SC_DELAYTIMER_MAX);
#else
printf("no symbol for _SC_DELAYTIMER_MAX\n");
#endif
#ifdef HOST_NAME_MAX
printf("HOST_NAME_MAX defined to be %ld\n",(long)HOST_NAME_MAX+0);
#else
printf("no symbol for HOST_NAME_MAX\n");
#endif
#ifdef _SC_HOST_NAME_MAX
pr_sysconf("HOST_NAME_MAX =",_SC_HOST_NAME_MAX);
#else
printf("no symbol for _SC_HOST_NAME_MAX\n");
#endif
#ifdef IOV_MAX
printf("IOV_MAX defined to be %ld\n",(long)IOV_MAX+0);
#else
printf("no symbol for IOV_MAX\n");
#endif
#ifdef _SC_IOV_MAX
pr_sysconf("IOV_MAX =",_SC_IOV_MAX);
#else
printf("no symbol for _SC_IOV_MAX\n");
#endif
#ifdef LINE_MAX
printf("LINE_MAX defined to be %ld\n",(long)LINE_MAX+0);
#else
printf("no symbol for LINE_MAX\n");
#endif
#ifdef _SC_LINE_MAX
pr_sysconf("LINE_MAX =",_SC_LINE_MAX);
#else
printf("no symbol for _SC_LINE_MAX\n");
#endif
#ifdef LOGIN_NAME_MAX
printf("LOGIN_NAME_MAX defined to be %ld\n",(long)LOGIN_NAME_MAX+0);
#else
printf("no symbol for LOGIN_NAME_MAX\n");
#endif
#ifdef _SC_LOGIN_NAME_MAX
pr_sysconf("LOGIN_NAME_MAX =",_SC_LOGIN_NAME_MAX);
#else
printf("no symbol for _SC_LOGIN_NAME_MAX\n");
#endif
#ifdef NGROUPS_MAX
printf("NGROUPS_MAX defined to be %ld\n",(long)NGROUPS_MAX+0);
#else
printf("no symbol for NGROUPS_MAX\n");
#endif
#ifdef _SC_NGROUPS_MAX
pr_sysconf("NGROUPS_MAX =",_SC_NGROUPS_MAX);
#else
printf("no symbol for _SC_NGROUPS_MAX\n");
#endif
#ifdef OPEN_MAX
printf("OPEN_MAX defined to be %ld\n",(long)OPEN_MAX+0);
#else
printf("no symbol for OPEN_MAX\n");
#endif
#ifdef _SC_OPEN_MAX
pr_sysconf("OPEN_MAX =",_SC_OPEN_MAX);
#else
printf("no symbol for _SC_OPEN_MAX\n");
#endif
#ifdef PAGESIZE
printf("PAGESIZE defined to be %ld\n",(long)PAGESIZE+0);
#else
printf("no symbol for PAGESIZE\n");
#endif
#ifdef _SC_PAGESIZE
pr_sysconf("PAGESIZE =",_SC_PAGESIZE);
#else
printf("no symbol for _SC_PAGESIZE\n");
#endif
#ifdef PAGE_SIZE
printf("PAGE_SIZE defined to be %ld\n",(long)PAGE_SIZE+0);
#else
printf("no symbol for PAGE_SIZE\n");
#endif
#ifdef _SC_PAGE_SIZE
pr_sysconf("PAGE_SIZE =",_SC_PAGE_SIZE);
#else
printf("no symbol for _SC_PAGE_SIZE\n");
#endif
#ifdef RE_DUP_MAX
printf("RE_DUP_MAX defined to be %ld\n",(long)RE_DUP_MAX+0);
#else
printf("no symbol for RE_DUP_MAX\n");
#endif
#ifdef _SC_RE_DUP_MAX
pr_sysconf("RE_DUP_MAX =",_SC_RE_DUP_MAX);
#else
printf("no symbol for _SC_RE_DUP_MAX\n");
#endif
#ifdef RTSIG_MAX
printf("RTSIG_MAX defined to be %ld\n",(long)RTSIG_MAX+0);
#else
printf("no symbol for RTSIG_MAX\n");
#endif
#ifdef _SC_RTSIG_MAX
pr_sysconf("RTSIG_MAX =",_SC_RTSIG_MAX);
#else
printf("no symbol for _SC_RTSIG_MAX\n");
#endif
#ifdef SEM_NSEMS_MAX
printf("SEM_NSEMS_MAX defined to be %ld\n",(long)SEM_NSEMS_MAX+0);
#else
printf("no symbol for SEM_NSEMS_MAX\n");
#endif
#ifdef _SC_SEM_NSEMS_MAX
pr_sysconf("SEM_NSEMS_MAX =",_SC_SEM_NSEMS_MAX);
#else
printf("no symbol for _SC_SEM_NSEMS_MAX\n");
#endif
#ifdef SEM_VALUE_MAX
printf("SEM_VALUE_MAX defined to be %ld\n",(long)SEM_VALUE_MAX+0);
#else
printf("no symbol for SEM_VALUE_MAX\n");
#endif
#ifdef _SC_SEM_VALUE_MAX
pr_sysconf("SEM_VALUE_MAX =",_SC_SEM_VALUE_MAX);
#else
printf("no symbol for _SC_SEM_VALUE_MAX\n");
#endif
#ifdef SIGQUEUE_MAX
printf("SIGQUEUE_MAX defined to be %ld\n",(long)SIGQUEUE_MAX+0);
#else
printf("no symbol for SIGQUEUE_MAX\n");
#endif
#ifdef _SC_SIGQUEUE_MAX
pr_sysconf("SIGQUEUE_MAX =",_SC_SIGQUEUE_MAX);
#else
printf("no symbol for _SC_SIGQUEUE_MAX\n");
#endif
#ifdef STREAM_MAX
printf("STREAM_MAX defined to be %ld\n",(long)STREAM_MAX+0);
#else
printf("no symbol for STREAM_MAX\n");
#endif
#ifdef _SC_STREAM_MAX
pr_sysconf("STREAM_MAX =",_SC_STREAM_MAX);
#else
printf("no symbol for _SC_STREAM_MAX\n");
#endif
#ifdef SYMLOOP_MAX
printf("SYMLOOP_MAX defined to be %ld\n",(long)SYMLOOP_MAX+0);
#else
printf("no symbol for SYMLOOP_MAX\n");
#endif
#ifdef _SC_SYMLOOP_MAX
pr_sysconf("SYMLOOP_MAX =",_SC_SYMLOOP_MAX);
#else
printf("no symbol for _SC_SYMLOOP_MAX\n");
#endif
#ifdef TIMER_MAX
printf("TIMER_MAX defined to be %ld\n",(long)TIMER_MAX+0);
#else
printf("no symbol for TIMER_MAX\n");
#endif
#ifdef _SC_TIMER_MAX
pr_sysconf("TIMER_MAX =",_SC_TIMER_MAX);
#else
printf("no symbol for _SC_TIMER_MAX\n");
#endif
#ifdef TTY_NAME_MAX
printf("TTY_NAME_MAX defined to be %ld\n",(long)TTY_NAME_MAX+0);
#else
printf("no symbol for TTY_NAME_MAX\n");
#endif
#ifdef _SC_TTY_NAME_MAX
pr_sysconf("TTY_NAME_MAX =",_SC_TTY_NAME_MAX);
#else
printf("no symbol for _SC_TTY_NAME_MAX\n");
#endif
#ifdef TZNAME_MAX
printf("TZNAME_MAX defined to be %ld\n",(long)TZNAME_MAX+0);
#else
printf("no symbol for TZNAME_MAX\n");
#endif
#ifdef _SC_TZNAME_MAX
pr_sysconf("TZNAME_MAX =",_SC_TZNAME_MAX);
#else
printf("no symbol for _SC_TZNAME_MAX\n");
#endif
#ifdef FILESIZEBITS
printf("FILESIZEBITS defined to be %ld\n",(long)FILESIZEBITS+0);
#else
printf("no symbol for FILESIZEBITS\n");
#endif
#ifdef _PC_FILESIZEBITS
pr_pathconf("FILESIZEBITS =",argv[1],_PC_FILESIZEBITS);
#else
printf("no symbol for _PC_FILESIZEBITS\n");
#endif
#ifdef LINK_MAX
printf("LINK_MAX defined to be %ld\n",(long)LINK_MAX+0);
#else
printf("no symbol for LINK_MAX\n");
#endif
#ifdef _PC_LINK_MAX
pr_pathconf("LINK_MAX =",_PC_LINK_MAX);
#else
printf("no symbol for _PC_LINK_MAX\n");
#endif
#ifdef MAX_CANON
printf("MAX_CANON defined to be %ld\n",(long)MAX_CANON+0);
#else
printf("no symbol for MAX_CANON\n");
#endif
#ifdef _PC_MAX_CANON
pr_pathconf("MAX_CANON =",_PC_MAX_CANON);
#else
printf("no symbol for _PC_MAX_CANON\n");
#endif
#ifdef MAX_INPUT
printf("MAX_INPUT defined to be %ld\n",(long)MAX_INPUT+0);
#else
printf("no symbol for MAX_INPUT\n");
#endif
#ifdef _PC_MAX_INPUT
pr_pathconf("MAX_INPUT =",_PC_MAX_INPUT);
#else
printf("no symbol for _PC_MAX_INPUT\n");
#endif
#ifdef NAME_MAX
printf("NAME_MAX defined to be %ld\n",(long)NAME_MAX+0);
#else
printf("no symbol for NAME_MAX\n");
#endif
#ifdef _PC_NAME_MAX
pr_pathconf("NAME_MAX =",_PC_NAME_MAX);
#else
printf("no symbol for _PC_NAME_MAX\n");
#endif
#ifdef PATH_MAX
printf("PATH_MAX defined to be %ld\n",(long)PATH_MAX+0);
#else
printf("no symbol for PATH_MAX\n");
#endif
#ifdef _PC_PATH_MAX
pr_pathconf("PATH_MAX =",_PC_PATH_MAX);
#else
printf("no symbol for _PC_PATH_MAX\n");
#endif
#ifdef PIPE_BUF
printf("PIPE_BUF defined to be %ld\n",(long)PIPE_BUF+0);
#else
printf("no symbol for PIPE_BUF\n");
#endif
#ifdef _PC_PIPE_BUF
pr_pathconf("PIPE_BUF =",_PC_PIPE_BUF);
#else
printf("no symbol for _PC_PIPE_BUF\n");
#endif
#ifdef SYMLINK_MAX
printf("SYMLINK_MAX defined to be %ld\n",(long)SYMLINK_MAX+0);
#else
printf("no symbol for SYMLINK_MAX\n");
#endif
#ifdef _PC_SYMLINK_MAX
pr_pathconf("SYMLINK_MAX =",_PC_SYMLINK_MAX);
#else
printf("no symbol for _PC_SYMLINK_MAX\n");
#endif
#ifdef _POSIX_TIMESTAMP_RESOLUTION
printf("_POSIX_TIMESTAMP_RESOLUTION defined to be %ld\n",(long)_POSIX_TIMESTAMP_RESOLUTION+0);
#else
printf("no symbol for _POSIX_TIMESTAMP_RESOLUTION\n");
#endif
#ifdef _PC_TIMESTAMP_RESOLUTION
pr_pathconf("_POSIX_TIMESTAMP_RESOLUTION =",_PC_TIMESTAMP_RESOLUTION);
#else
printf("no symbol for _PC_TIMESTAMP_RESOLUTION\n");
#endif
exit(0);
}
static void
pr_sysconf(char *mesg,int name)
{
long val;
fputs(mesg,stdout);
errno = 0;
if ((val = sysconf(name)) < 0) {
if (errno != 0) {
if (errno == EINVAL)
fputs(" (not supported)\n",stdout);
else
err_sys("sysconf error");
} else {
fputs(" (no limit)\n",stdout);
}
} else {
printf(" %ld\n",val);
}
}
static void
pr_pathconf(char *mesg,char *path,stdout);
errno = 0;
if ((val = pathconf(path,name)) < 0) {
if (errno != 0) {
if (errno == EINVAL)
fputs(" (not supported)\n",stdout);
else
err_sys("pathconf error,path = %s",path);
} else {
fputs(" (no limit)\n",val);
}
}
功能测试宏
如果在编译一个程序时希望他至于POSIX的定义相关,而不与任何实现定义的常量冲突,那么就需要常量_POSIX_C_SOURCE。一旦定义_POSIX_C_SOURCE,所有POSIX.1头文件都使用此常量来排除任何实现转悠的定义。
关于apue第二章,我个人认为没有《Linux/UNIX系统编程手册》中讲解的清楚,可以参考我的博文TLPI-Chapter 11系统限制和选项