APUE读书笔记-2

Unix系统基础

Posted by Nathaniel on 2017-08-15

APUE读书笔记-2

第二章

  1. 2.1 We mentioned in Section 2.8 that some of the primitive system data types are defined in more than one header. For example, in FreeBSD 8.0, size_t is defined in 29 different headers. Because all 29 headers could be included in a program and because ISO C does not allow multiple typedefs for the same name, how must the headers be written?

    个人认为,遇到这种情况时,假设多重定义的类型为#size_t,那么可以采用include guard的策略,即在头文件中,声明size_t时,进行一次#ifndef#endif的保护,从而可以避免size_t的多重定义。

  2. 2.2 Examine your system’s headers and list the actual data types used to implement the primitive system data types.

    我的系统是macOS 10.12.6,也算是认证的Unix系统了,于是在对<sys/types.h>进行暗中观察😏之后,得出结论如下:

    typedef unsigned char u_char;
    typedef unsigned short u_short;
    typedef unsigned int u_int;
    #ifndef _U_LONG
    typedef unsigned long u_long;
    #define _U_LONG
    #endif
    typedef unsigned short ushort; /* Sys V compatibility */
    typedef unsigned int uint; /* Sys V compatibility */
    #endif
    typedef u_int64_t u_quad_t; /* quads */
    typedef int64_t quad_t;
    typedef quad_t * qaddr_t;
    typedef char * caddr_t; /* core address */
    typedef int32_t daddr_t; /* disk address */
    typedef u_int32_t fixpt_t; /* fixed point number */
    typedef int32_t segsz_t; /* segment size */
    typedef int32_t swblk_t; /* swap offset */
    typedef __int32_t fd_mask;

    这里仅仅列出了一些基本数据类型的实现,在sys/_types文件夹下的头文件中还有许多的其他的常见类型,如size_ttime_t等的实现,再此由于篇幅有限就不予详述了,总体而言,Unix下的不少以_t结尾的类型,都是随各个系统的实现方式而可能发生变化的,具体的实现只要观察<sys/types.h>即可得知。这个信息可以帮助我们解决一些潜在的bug。

    简单的介绍一些常见的unix定义的变量类型:

名称 表示数据
clock_t CPU时钟周期
comp_t 压缩后的CPU时钟周期(不属于POSIX标准)
dev_t 设备编号
fd_set 文件描述符集合
fpos_t 文件位置
gid_t 用户组ID
ino_t inode值(inode为一种文件系统对象,用于区分文件和文件夹等文件类型)
mode_t 文件类型、文件权限
nlink_t 该目录的链接数
off_t 文件大小和偏移量
pid_t 进程ID和进程组ID
pthread_t 线程ID
ptrdiff_t 两个指针相减的结果
rlim_t 资源上限
sig_atomic_t 可用作信号量的原子数据类型
sigset_t 信号量集合
size_t 对象的大小(非负)
ssize_t 对象的大小或-1
time_t 日历时间单位
uid_t 用户ID
wchar_t 宽字符
  1. 2.3 Update the program in Figure 2.17 to avoid the needless processing that occurs when sysconf returns LONG_MAX as the limit for OPEN_MAX.

    Fig 2.17内容如下:

    #include "apue.h"
    #include <errno.h>
    #include <limits.h>
    #ifdef OPEN_MAX
    static long openmax = OPEN_MAX;
    #else
    static long openmax = 0;
    #endif
    /*
    * If OPEN_MAX is indeterminate, this might be inadequate.
    */
    #define OPEN_MAX_GUESS 256
    long
    open_max(void)
    {
    if (openmax == 0) {
    errno = 0;
    /* first time through */
    if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
    if (errno == 0)
    openmax = OPEN_MAX_GUESS; /* it’s indeterminate */
    else
    fprintf(stderr, "sysconf error for _SC_OPEN_MAX");
    }
    }
    return(openmax);
    }

    由于实在没读懂题意,我去Google了一下,获得了如下的答案:

    #include "apue.h"
    #include <limits.h>
    #include <sys/resource.h>
    #define OPEN_MAX_GUESS 256
    long
    open_max(void)
    {
    long openmax;
    struct rlimit rl;
    if ((openmax = sysconf(_SC_OPEN_MAX)) < 0 ||
    openmax == LONG_MAX) {
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
    err_sys("can't get file limit");
    if (rl.rlim_max == RLIM_INFINITY)
    openmax = OPEN_MAX_GUESS;
    else
    openmax = rl.rlim_max;
    }
    return(openmax);
    }

    简单的来说,如果sysconf函数返回了LONG_MAX,那么这也表明OPEN_MAX是不确定的,同时,我们可以使用geTRlimit函数来获得每个进程最大的同时打开文件数量,从而使OPEN_MAX成为一个合理的上限值。