[APUE]第二章UNIX标准及实现

59 篇文章 1 订阅

这一章的阅读相对枯燥,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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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 =", argv[1], _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, int name)
{
    long    val;

    fputs(mesg, 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", stdout);
        }
    } else {
        printf(" %ld\n", val);
    }
}
功能测试宏

如果在编译一个程序时希望他至于POSIX的定义相关,而不与任何实现定义的常量冲突,那么就需要常量_POSIX_C_SOURCE。一旦定义_POSIX_C_SOURCE,所有POSIX.1头文件都使用此常量来排除任何实现转悠的定义。
关于apue第二章,我个人认为没有《Linux/UNIX系统编程手册》中讲解的清楚,可以参考我的博文TLPI-Chapter 11系统限制和选项

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值