Back

APUE reading notes-2

Tue, Aug 15 20173 min read
Nathaniel

第二章

  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_tCPU时钟周期
comp_t压缩后的CPU时钟周期(不属于POSIX标准)
dev_t设备编号
fd_set文件描述符集合
fpos_t文件位置
gid_t用户组ID
ino_tinode值(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成为一个合理的上限值。

Comments(0)

Continue with
to comment