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_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成为一个合理的上限值。

Comments(0)

Continue with
to comment