APUE reading notes-2

第二章
- 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
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_t、time_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
| 宽字符
|
- 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成为一个合理的上限值。